1 /*
2  *  This file is part of the XForms library package.
3  *
4  *  XForms is free software; you can redistribute it and/or modify it
5  *  under the terms of the GNU Lesser General Public License as
6  *  published by the Free Software Foundation; either version 2.1, or
7  *  (at your option) any later version.
8  *
9  *  XForms is distributed in the hope that it will be useful, but
10  *  WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public License
15  *  along with XForms.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
19 /**
20  * \file choice.c
21  *
22  *  This file is part of the XForms library package.
23  *  Copyright (c) 1996-2002  T.C. Zhao and Mark Overmars
24  *  All rights reserved.
25  *
26  * FL_CHOICE class
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include "include/forms.h"
34 #include "flinternal.h"
35 #include "private/pchoice.h"
36 #include "private/flvasprintf.h"
37 #include <string.h>
38 #include <stdlib.h>
39 
40 
41 #define NO_TITLE_MASK      1
42 #define ALIGN_BOTTOM_MASK  2
43 
44 
45 
46 /***************************************
47  ***************************************/
48 
49 static void
free_choice(FLI_CHOICE_SPEC * sp)50 free_choice( FLI_CHOICE_SPEC * sp )
51 {
52     int i;
53 
54     for ( i = 1; i <= FL_CHOICE_MAXITEMS; i++ )
55     {
56         if ( sp->items[ i ] )
57             fli_safe_free( sp->items[ i ] );
58         if ( sp->shortcut[ i ] )
59             fli_safe_free( sp->shortcut[ i ] );
60     }
61 }
62 
63 
64 /***************************************
65  * Draws a choice object
66  ***************************************/
67 
68 static void
draw_choice(FL_OBJECT * ob)69 draw_choice( FL_OBJECT * ob )
70 {
71     FL_COLOR c1;
72     FLI_CHOICE_SPEC *sp = ob->spec;
73     int absbw = FL_abs(ob->bw);
74     int off1 = 0,
75         off2 = 0;
76 
77     c1 = ob->belowmouse ? FL_CHOICE_MCOL : ob->col1;
78 
79     fl_draw_box( ob->boxtype, ob->x, ob->y, ob->w, ob->h, c1, ob->bw );
80 
81     if ( ob->type == FL_NORMAL_CHOICE2 )
82     {
83         int dh = FL_max( 6 + ( ob->bw > 0 ), ob->h * 0.1 );
84         int dw = FL_max( 0.11 * ob->w, 13 );
85         int dbh = FL_max( absbw - 1, 1 );
86         int align = fl_to_outside_lalign( sp->align );
87 
88         fl_draw_box( FL_UP_BOX,
89                      ob->x + ob->w - dw - absbw - 2,
90                      ob->y + ( ob->h - dh ) / 2,
91                      dw, dh, ob->col1, - dbh );
92 
93         off1 = fl_is_center_lalign( align ) ? ( dw / 2 ) : 0;
94         off2 = align == FL_ALIGN_RIGHT ? dw : 0;
95     }
96 
97     fl_draw_text_beside( ob->align, ob->x, ob->y, ob->w, ob->h, ob->lcol,
98                          ob->lstyle, ob->lsize, ob->label );
99 
100     /* String can conceivably contain "type flags". need to get rid of them
101        on the fly */
102 
103     if ( sp->val > 0 && sp->val <= sp->numitems )
104     {
105         char *str = fl_strdup( sp->items[ sp->val ] ),
106              *cc  = strchr( str, '%' );
107 
108         if ( cc )
109         {
110             if ( cc[ 1 ] == '%' )
111                 cc[ 1 ] = '\0';
112             else
113                 cc[ 0 ] = '\0';
114         }
115 
116         fl_set_text_clipping( ob->x + absbw, ob->y,
117                               ob->w - 2 * absbw, ob->h );
118         fl_draw_text( sp->align, ob->x - off1, ob->y, ob->w - off2,
119                       ob->h, ob->col2, sp->fontstyle, sp->fontsize,
120                       str + ( str && ( *str == '\010' ) ) );
121         fl_unset_text_clipping( );
122         fl_free( str );
123     }
124 }
125 
126 
127 /***************************************
128  ***************************************/
129 
130 static void
draw_droplist_choice(FL_OBJECT * ob)131 draw_droplist_choice( FL_OBJECT * ob )
132 {
133     FL_COLOR c1;
134     FLI_CHOICE_SPEC *sp = ob->spec;
135     FL_Coord dw = ob->h,
136              dx = ob->w - dw,
137              bw;
138 
139     c1 = sp->below ? FL_CHOICE_MCOL : ob->col1;
140     bw = ob->bw;
141     if ( bw > 0 )
142         bw -= ob->bw > 1;
143 
144     /* Arrows */
145 
146     fl_draw_box( sp->pushed ? FL_DOWN_BOX : FL_UP_BOX, ob->x + dx, ob->y,
147                  dw, ob->h, c1, bw );
148     if ( sp->no_title & ALIGN_BOTTOM_MASK )
149         fl_draw_text( FL_ALIGN_CENTER, ob->x + dx + 2, ob->y + 2,
150                       dw - 4, ob->h - 4,
151                       FL_BLACK, 0, 0, "@#8->" );
152     else
153         fl_draw_text( FL_ALIGN_CENTER, ob->x + dx + 2, ob->y + 2,
154                       dw - 4, ob->h - 4,
155                       FL_BLACK, 0, 0, "@#2->" );
156 
157     /* Choice box */
158 
159     fl_draw_box( ob->boxtype, ob->x, ob->y, dx, ob->h, ob->col1, ob->bw );
160     fl_draw_text_beside( ob->align, ob->x, ob->y, dx, ob->h, ob->lcol,
161                          ob->lstyle, ob->lsize, ob->label );
162 
163     /* String can conceivably contain "type flags", need to get rid of them
164        on the fly */
165 
166     if ( sp->val > 0 && sp->val <= sp->numitems )
167     {
168         char *str = fl_strdup( sp->items[ sp->val ] ),
169              *cc = strchr( str, '%' );
170 
171         if ( cc )
172         {
173             if ( cc[ 1 ] == '%')
174                 cc[ 1 ] = '\0';
175             else
176                 cc[ 0 ] = '\0';
177         }
178 
179         fl_set_text_clipping( ob->x + FL_abs( ob->bw ), ob->y,
180                               ob->w - 2 * FL_abs( ob->bw ), ob->h );
181         fl_draw_text( sp->align, ob->x, ob->y, dx, ob->h, ob->col2,
182                       sp->fontstyle, sp->fontsize,
183                       str + ( str && ( *str == '\010' ) ) );
184         fl_unset_text_clipping( );
185         fl_free( str );
186     }
187 }
188 
189 
190 /***************************************
191  * Due to grayout, need to find out which one is valid
192  ***************************************/
193 
194 static int
set_next_entry(FLI_CHOICE_SPEC * sp,int dir)195 set_next_entry( FLI_CHOICE_SPEC * sp,
196                 int               dir )
197 {
198     int target = 0;
199     int min = 1,
200         max = sp->numitems;
201 
202     if ( sp->numitems == 0 )
203         return -1;
204 
205     while ( sp->mode[ min ] & FL_PUP_GREY && min < max )
206         min++;
207 
208     while ( sp->mode[ max ] & FL_PUP_GREY && max > min )
209         max--;
210 
211     if ( min == max )
212         return -1;
213 
214     if ( dir > 0 )
215     {
216         target = sp->val + 1;
217         if ( target > max )
218             target = min;
219     }
220     else if ( dir < 0 )
221     {
222         target = sp->val - 1;
223         if ( target < min )
224             target = max;
225     }
226 
227     for ( ; target >= min && target <= max; target += dir )
228         if ( ! ( sp->mode[ target ] & FL_PUP_GREY ) )
229             return sp->val = target;
230 
231     M_err( "set_next_entry", "No valid entries" );
232     return -1;
233 }
234 
235 
236 /***************************************
237  ***************************************/
238 
239 static int
do_pup(FL_OBJECT * ob)240 do_pup( FL_OBJECT * ob )
241 {
242     int popup_id;
243     FLI_CHOICE_SPEC *sp = ob->spec;
244     int i,
245         val;
246 
247     popup_id = fl_newpup( FL_ObjWin( ob ) );
248 
249     /* Fake a title */
250 
251     if (    ob->label
252          && ob->label[ 0 ]
253          && ob->type != FL_DROPLIST_CHOICE
254          && ! ( sp->no_title & NO_TITLE_MASK ) )
255     {
256         char *t = fl_malloc( strlen( ob->label ) + 3 );
257 
258         strcpy( t, ob->label );
259         strcat( t, "%t" );
260         fl_addtopup( popup_id, t );
261         fl_free( t );
262     }
263 
264     for ( i = 1; i <= sp->numitems; i++ )
265     {
266         fl_addtopup( popup_id, sp->items[ i ] );
267 
268         if ( sp->modechange[ i ] || sp->mode[ i ] != FL_PUP_NONE )
269         {
270             fl_setpup( popup_id, i, sp->mode[ i ] );
271             sp->modechange[ i ] = 0;
272         }
273 
274         fl_setpup_shortcut( popup_id, i, sp->shortcut[ i ] );
275     }
276 
277     fl_setpup_shadow( popup_id, ob->type != FL_DROPLIST_CHOICE );
278     fl_setpup_selection( popup_id, sp->val );
279 
280     fl_setpup_softedge( popup_id, ob->bw < 0 );
281 
282     if ( sp->no_title & ALIGN_BOTTOM_MASK )
283         fl_setpup_align_bottom( );
284 
285     val = fl_dopup( popup_id );
286 
287     if ( val > 0 )
288     {
289         sp->mode[ val ] = fl_getpup_mode( popup_id, i );
290         sp->modechange[ val ] = 1;
291         sp->val = val;
292     }
293 
294     fl_freepup( popup_id );
295     return val;
296 }
297 
298 
299 #define Within( x, y, w, h )   (    mx >= ( x )              \
300                                  && mx <= ( ( x ) + ( w ) )  \
301                                  && my >= ( y )              \
302                                  && my <= ( ( y ) + ( h ) ) )
303 
304 
305 /***************************************
306  * Handles an event, returns whether value has changed.
307  ***************************************/
308 
309 static int
handle_choice(FL_OBJECT * ob,int event,FL_Coord mx,FL_Coord my,int key,void * ev FL_UNUSED_ARG)310 handle_choice( FL_OBJECT * ob,
311                int         event,
312                FL_Coord    mx,
313                FL_Coord    my,
314                int         key,
315                void *      ev   FL_UNUSED_ARG )
316 {
317     FLI_CHOICE_SPEC *sp = ob->spec;
318     int val;
319     int ret = FL_RETURN_NONE;
320 
321 #if FL_DEBUG >= ML_DEBUG
322     M_info2( "handle_choice", fli_event_name( event ) );
323 #endif
324 
325     switch ( event )
326     {
327         case FL_ATTRIB :
328             /* always force outside alignment */
329 
330             ob->align = fl_to_outside_lalign( ob->align );
331             break;
332 
333         case FL_DRAW:
334             if ( ob->type == FL_DROPLIST_CHOICE )
335                 draw_droplist_choice( ob );
336             else
337                 draw_choice( ob );
338             break;
339 
340         case FL_DRAWLABEL:
341             fl_draw_text_beside( ob->align, ob->x, ob->y, ob->w, ob->h,
342                                  ob->lcol, ob->lstyle, ob->lsize, ob->label );
343             break;
344 
345         case FL_PUSH:
346             if ( key == FL_MBUTTON2 || key == FL_MBUTTON3 )
347             {
348                 sp->counter = 0;
349                 val = set_next_entry( sp, key == FL_MBUTTON3 ? 1 : -1 );
350                 sp->pushed = 0;
351                 fl_redraw_object( ob );
352                 if ( val > 0 )
353                     ret |= FL_RETURN_CHANGED;
354                 break;
355             }
356 
357             if ( key != FL_MBUTTON1 || sp->numitems == 0 )
358                 break;
359 
360             if ( ob->type != FL_DROPLIST_CHOICE )
361             {
362                 if ( do_pup( ob ) > 0 )
363                     ret |= FL_RETURN_CHANGED;
364                 break;
365             }
366 
367             /* Droplist choices only become active when the mouse button
368                has been released */
369 
370             if ( Within( ob->x + ob->w - ob->h, ob->y, ob->h, ob->h ) )
371             {
372                 sp->pushed = 1;
373                 draw_droplist_choice( ob );
374             }
375             break;
376 
377         case FL_UPDATE:
378             if (    ( key == FL_MBUTTON2 || key == FL_MBUTTON3 )
379                  && ++sp->counter % 15 == 0 )
380             {
381                 sp->counter = 0;
382                 val = set_next_entry( sp, key == FL_MBUTTON3 ? 1 : -1 );
383                 sp->pushed = 0;
384                 fl_redraw_object( ob );
385                 if ( val > 0 )
386                     ret |= FL_RETURN_CHANGED;
387             }
388             break;
389 
390         case FL_MOTION:
391             if ( sp->numitems == 0 || ob->type != FL_DROPLIST_CHOICE )
392                 break;
393 
394             if ( Within( ob->x + ob->w - ob->h, ob->y, ob->h, ob->h ) )
395             {
396                 if ( ! sp->below )
397                 {
398                     sp->below = 1;
399                     draw_droplist_choice( ob );
400                 }
401             }
402             else if ( sp->below )
403             {
404                 sp->below = 0;
405                 draw_droplist_choice( ob );
406             }
407             break;
408 
409         case FL_RELEASE:
410             if ( sp->numitems == 0 )
411                 break;
412 
413             if (    key == FL_MBUTTON4
414                  || key == FL_MBUTTON5 )
415             {
416                 val = set_next_entry( sp, key == FL_MBUTTON5 ? 1 : -1 );
417                 sp->pushed = 0;
418                 fl_redraw_object( ob );
419                 if ( val > 0 )
420                     ret |= FL_RETURN_CHANGED | FL_RETURN_END;
421                 break;
422             }
423 
424             if ( ob->type != FL_DROPLIST_CHOICE || ! sp->pushed )
425                 break;
426 
427             if ( ! Within( ob->x + ob->w - ob->h, ob->y, ob->h, ob->h ) )
428             {
429                 sp->pushed = 0;
430                 fl_redraw_object( ob );
431                 break;
432             }
433 
434             if ( sp->no_title & ALIGN_BOTTOM_MASK )
435                 fl_setpup_position( - ( ob->form->x + ob->x + ob->w ),
436                                     ob->form->y + ob->y - FL_PUP_PADH );
437             else
438                 fl_setpup_position( - ( ob->form->x + ob->x + ob->w ),
439                                     ob->form->y + ob->y + ob->h + FL_PUP_PADH );
440             sp->pushed = 0;
441             if ( do_pup( ob ) > 0 )
442                 ret |= FL_RETURN_CHANGED | FL_RETURN_END;
443             break;
444 
445         case FL_LEAVE:
446             sp->below = 0;
447             fl_redraw_object( ob );
448             break;
449 
450         case FL_ENTER:
451             if ( sp->numitems == 0 )
452                 break;
453 
454             if (    (    ob->type == FL_DROPLIST_CHOICE
455                       && Within( ob->x + ob->w - ob->h, ob->y, ob->h, ob->h ) )
456                  || ob->type != FL_DROPLIST_CHOICE )
457             {
458                 sp->below = 1;
459                 fl_redraw_object( ob );
460             }
461             break;
462 
463         case FL_SHORTCUT:
464             if ( sp->numitems == 0 )
465                 break;
466 
467             fl_setpup_position( ob->form->x + ob->x + 10,
468                                 ob->form->y + ob->y + ob->h / 2 );
469             val = do_pup( ob );
470             fl_redraw_object( ob );
471             if ( val > 0 )
472                 ret |= FL_RETURN_CHANGED | FL_RETURN_END;
473             break;
474 
475         case FL_FREEMEM:
476             free_choice( ob->spec );
477             fl_free( ob->spec );
478             break;
479     }
480 
481     return ret;
482 }
483 
484 
485 /***************************************
486  * Creates an object
487  ***************************************/
488 
489 FL_OBJECT *
fl_create_choice(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * label)490 fl_create_choice( int          type,
491                   FL_Coord     x,
492                   FL_Coord     y,
493                   FL_Coord     w,
494                   FL_Coord     h,
495                   const char * label )
496 {
497     FL_OBJECT *obj;
498     int i;
499     FLI_CHOICE_SPEC *sp;
500 
501     obj = fl_make_object( FL_CHOICE, type, x, y, w, h, label, handle_choice );
502 
503     obj->boxtype     = type == FL_NORMAL_CHOICE2 ? FL_UP_BOX : FL_CHOICE_BOXTYPE;
504     obj->col1        = FL_CHOICE_COL1;
505     obj->col2        = FL_CHOICE_COL2;
506     obj->lcol        = FL_CHOICE_LCOL;
507     obj->align       = FL_CHOICE_ALIGN;
508     obj->want_update = 1;
509     obj->spec = sp   = fl_calloc( 1, sizeof *sp );
510 
511     sp->fontsize  = fli_cntl.choiceFontSize ?
512                     fli_cntl.choiceFontSize : FL_DEFAULT_SIZE;
513     sp->fontstyle = FL_NORMAL_STYLE;
514     sp->align     = FL_ALIGN_CENTER;
515 
516     for ( i = 0; i <= FL_CHOICE_MAXITEMS; i++ )
517     {
518         sp->items[ i ] = NULL;
519         sp->shortcut[ i ] = NULL;
520     }
521 
522     fl_set_object_return( obj, FL_RETURN_CHANGED );
523 
524     return obj;
525 }
526 
527 
528 /***************************************
529  * Adds an object
530  ***************************************/
531 
532 FL_OBJECT *
fl_add_choice(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * l)533 fl_add_choice( int          type,
534                FL_Coord     x,
535                FL_Coord     y,
536                FL_Coord     w,
537                FL_Coord     h,
538                const char * l )
539 {
540     FL_OBJECT *ob;
541 
542     ob = fl_create_choice( type, x, y, w, h, l );
543     fl_add_object( fl_current_form, ob );
544     return ob;
545 }
546 
547 
548 /***************************************
549  * Clears the choice object
550  ***************************************/
551 
552 void
fl_clear_choice(FL_OBJECT * ob)553 fl_clear_choice( FL_OBJECT * ob )
554 {
555     FLI_CHOICE_SPEC *sp = ob->spec;
556 
557 #if FL_DEBUG >= ML_ERR
558     if ( ! IsValidClass( ob, FL_CHOICE ) )
559     {
560         M_err( "fl_clear_choice", "%s is not choice class",
561                ob ? ob->label : "" );
562         return;
563     }
564 #endif
565 
566     free_choice( sp );
567 
568     sp->val = 0;
569     sp->numitems = 0;
570     fl_redraw_object( ob );
571 }
572 
573 
574 /***************************************
575  * Add a single choice item
576  ***************************************/
577 
578 static void
addto_choice(FL_OBJECT * ob,const char * str)579 addto_choice( FL_OBJECT *  ob,
580               const char * str )
581 {
582     FLI_CHOICE_SPEC *sp = ob->spec;
583 
584     if ( sp->numitems >= FL_CHOICE_MAXITEMS )
585         return;
586 
587     sp->items[ ++sp->numitems ] = fl_strdup( str );
588 
589     sp->shortcut[ sp->numitems ] = fl_strdup( "" );
590 
591     sp->mode[ sp->numitems ] = FL_PUP_NONE;
592     sp->modechange[ sp->numitems ] = 0;
593 
594     if ( sp->val == 0 )
595     {
596         sp->val = 1;
597         fl_redraw_object( ob );
598     }
599 }
600 
601 
602 /***************************************
603  * User interface routine.
604  ***************************************/
605 
606 int
fl_addto_choice(FL_OBJECT * ob,const char * str)607 fl_addto_choice( FL_OBJECT *  ob,
608                  const char * str )
609 {
610     FLI_CHOICE_SPEC *sp = ob->spec;
611     char *t,
612          *c;
613 
614 #if FL_DEBUG >= ML_ERR
615     if ( ! IsValidClass( ob, FL_CHOICE ) )
616     {
617         M_err( "fl_addto_choice", "%s is not choice class",
618                ob ? ob->label : "" );
619         return 0;
620     }
621 #endif
622 
623     if ( sp->numitems >= FL_CHOICE_MAXITEMS )
624         return sp->numitems;
625 
626     /* Split up string at '|' chars and create an entry for each part */
627 
628     t = fl_strdup( str );
629 
630     for ( c = strtok( t, "|" );
631           c && sp->numitems < FL_CHOICE_MAXITEMS;
632           c = strtok( NULL, "|" ) )
633         addto_choice( ob, c );
634 
635     if ( t )
636         fl_free( t );
637 
638     return sp->numitems;
639 }
640 
641 
642 /***************************************
643  ***************************************/
644 
645 int
fl_addto_choice_f(FL_OBJECT * ob,const char * fmt,...)646 fl_addto_choice_f( FL_OBJECT *  ob,
647                    const char * fmt,
648                    ... )
649 {
650     int n;
651     char *buf;
652 
653     EXPAND_FORMAT_STRING( buf, fmt );
654     n = fl_addto_choice( ob, buf );
655     fl_free( buf );
656     return n;
657 }
658 
659 
660 /***************************************
661  * Replaces a line to the choice item.
662  ***************************************/
663 
664 void
fl_replace_choice(FL_OBJECT * ob,int numb,const char * str)665 fl_replace_choice( FL_OBJECT *  ob,
666                    int          numb,
667                    const char * str )
668 {
669     FLI_CHOICE_SPEC *sp = ob->spec;
670 
671     if ( numb < 1 || numb > sp->numitems )
672         return;
673 
674     if ( sp->items[ numb ] )
675         fl_free( sp->items[ numb ] );
676     sp->items[ numb ] = fl_strdup( str );
677 
678     if ( sp->val == numb )
679         fl_redraw_object( ob );
680 }
681 
682 
683 /***************************************
684  ***************************************/
685 
686 void
fl_replace_choice_f(FL_OBJECT * ob,int numb,const char * fmt,...)687 fl_replace_choice_f( FL_OBJECT *  ob,
688                      int          numb,
689                      const char * fmt,
690                      ... )
691 {
692     char *buf;
693 
694     EXPAND_FORMAT_STRING( buf, fmt );
695     fl_replace_choice( ob, numb, buf );
696     fl_free( buf );
697 }
698 
699 
700 /***************************************
701  * Removes a line from the choice item.
702  ***************************************/
703 
704 void
fl_delete_choice(FL_OBJECT * ob,int numb)705 fl_delete_choice( FL_OBJECT * ob,
706                   int         numb )
707 {
708     int i;
709     FLI_CHOICE_SPEC *sp = ob->spec;
710 
711     if ( numb < 1 || numb > sp->numitems )
712         return;
713 
714     if ( sp->items[ numb ] )
715         fl_free( sp->items[ numb ] );
716     if ( sp->shortcut[ numb ] )
717         fl_free( sp->shortcut[ numb ] );
718 
719     for ( i = numb; i < sp->numitems; i++ )
720     {
721         sp->items[ i ] = sp->items[ i + 1 ];
722         sp->shortcut[ i ] = sp->shortcut[ i + 1 ];
723     }
724 
725     sp->items[ sp->numitems ] = NULL;
726     sp->shortcut[ sp->numitems ] = NULL;
727     sp->numitems--;
728 
729     if ( sp->val == numb )
730     {
731         if ( sp->val > sp->numitems )
732             sp->val = sp->numitems;
733         fl_redraw_object( ob );
734     }
735     else if ( sp->val > numb )
736         sp->val--;
737 }
738 
739 
740 /***************************************
741  * Sets the number of the choice.
742  ***************************************/
743 
744 void
fl_set_choice(FL_OBJECT * ob,int choice)745 fl_set_choice( FL_OBJECT * ob,
746                int         choice )
747 {
748     FLI_CHOICE_SPEC *sp = ob->spec;
749 
750     if (    choice < 1
751          || choice > sp->numitems
752          || sp->mode[ choice ] & FL_PUP_GREY )
753         sp->val = 0;
754     else
755         sp->val = choice;
756     fl_redraw_object( ob );
757 }
758 
759 
760 /***************************************
761  * Similar to set_choice, except we use txt
762  ***************************************/
763 
764 void
fl_set_choice_text(FL_OBJECT * ob,const char * txt)765 fl_set_choice_text( FL_OBJECT *  ob,
766                     const char * txt )
767 {
768     FLI_CHOICE_SPEC *sp;
769     int i;
770 
771 #if FL_DEBUG >= ML_ERR
772     if ( ! IsValidClass( ob, FL_CHOICE ) )
773     {
774         M_err( "fl_set_choice_text", "%s not choice class",
775                ob ? ob->label : "" );
776         return;
777     }
778 #endif
779     sp = ob->spec;
780 
781     for ( i = 1; i <= sp->numitems; i++ )
782         if ( strcmp( txt, sp->items[ i ] ) == 0 )
783         {
784             fl_set_choice( ob, i );
785             return;
786         }
787 
788     M_err( "fl_set_choice_text", "%s not found", txt );
789 }
790 
791 
792 /***************************************
793  ***************************************/
794 
795 void
fl_set_choice_text_f(FL_OBJECT * ob,const char * fmt,...)796 fl_set_choice_text_f( FL_OBJECT *  ob,
797                       const char * fmt,
798                       ... )
799 {
800     char *buf;
801 
802     EXPAND_FORMAT_STRING( buf, fmt );
803     fl_set_choice_text( ob, buf );
804     fl_free( buf );
805 }
806 
807 
808 /***************************************
809  ***************************************/
810 
811 int
fl_get_choice_item_mode(FL_OBJECT * ob,int item)812 fl_get_choice_item_mode( FL_OBJECT *  ob,
813                          int          item )
814 {
815     FLI_CHOICE_SPEC *sp = ob->spec;
816 
817     if ( item < 1 || item > sp->numitems )
818     {
819         M_err( "fl_get_choice_item_mode", "Bad item index %d", item );
820         return -1;
821     }
822 
823     return sp->mode[ item ];
824 }
825 
826 
827 
828 /***************************************
829  * Set the mode of an item in a choice object
830  ***************************************/
831 
832 void
fl_set_choice_item_mode(FL_OBJECT * ob,int item,unsigned int mode)833 fl_set_choice_item_mode( FL_OBJECT *  ob,
834                          int          item,
835                          unsigned int mode )
836 {
837     FLI_CHOICE_SPEC *sp = ob->spec;
838 
839     if ( item < 1 || item > sp->numitems )
840     {
841         M_err( "fl_set_choice_item_mode", "Bad item index %d", item );
842         return;
843     }
844 
845     sp->mode[ item ] = mode;
846     sp->modechange[ item ] = 1;
847 }
848 
849 
850 /***************************************
851  ***************************************/
852 
853 void
fl_set_choice_item_shortcut(FL_OBJECT * ob,int item,const char * sc)854 fl_set_choice_item_shortcut( FL_OBJECT *  ob,
855                              int          item,
856                              const char * sc )
857 {
858     FLI_CHOICE_SPEC *sp = ob->spec;
859 
860     if ( item < 1 || item > sp->numitems )
861     {
862         M_err( "fl_set_choice_item_shortcut", "Bad item index %d", item );
863         return;
864     }
865 
866     if ( sp->shortcut[ item ] )
867         fl_free( sp->shortcut[ item ] );
868 
869     sp->shortcut[ item ] = fl_strdup( sc ? sc : "" );
870 }
871 
872 
873 /***************************************
874  * Returns the number of the choice.
875  ***************************************/
876 
877 int
fl_get_choice(FL_OBJECT * ob)878 fl_get_choice( FL_OBJECT * ob )
879 {
880 #if FL_DEBUG >= ML_ERR
881     if ( ! IsValidClass( ob, FL_CHOICE ) )
882     {
883         M_err( "fl_get_choice", "%s is not choice class", ob ? ob->label : "" );
884         return 0;
885     }
886 #endif
887 
888     return ( ( FLI_CHOICE_SPEC * ) ob->spec )->val;
889 }
890 
891 
892 /***************************************
893  ***************************************/
894 
895 int
fl_get_choice_maxitems(FL_OBJECT * ob)896 fl_get_choice_maxitems( FL_OBJECT * ob )
897 {
898     return ( ( FLI_CHOICE_SPEC * ) ob->spec )->numitems;
899 }
900 
901 
902 /***************************************
903  * Returns the text of the choice.
904  ***************************************/
905 
906 const char *
fl_get_choice_text(FL_OBJECT * ob)907 fl_get_choice_text( FL_OBJECT * ob )
908 {
909     FLI_CHOICE_SPEC *sp = ob->spec;
910 
911 #if FL_DEBUG >= ML_ERR
912     if ( ! IsValidClass( ob, FL_CHOICE ) )
913     {
914         M_err( "fl_get_choice_text", "%s is not choice class",
915                ob ? ob->label : "" );
916         return 0;
917     }
918 #endif
919 
920     if ( sp->val == 0 )
921         return NULL;
922     return sp->items[ sp->val ];
923 }
924 
925 
926 /***************************************
927  ***************************************/
928 
929 const char *
fl_get_choice_item_text(FL_OBJECT * ob,int n)930 fl_get_choice_item_text( FL_OBJECT * ob,
931                          int         n )
932 {
933     FLI_CHOICE_SPEC *sp = ob->spec;
934 
935     if ( n < 1 || n > sp->numitems )
936         return NULL;
937 
938     return sp->items[ n ];
939 }
940 
941 
942 /***************************************
943  * Sets the font size inside the choice.
944  ***************************************/
945 
946 void
fl_set_choice_fontsize(FL_OBJECT * ob,int size)947 fl_set_choice_fontsize( FL_OBJECT * ob,
948                         int         size )
949 {
950     FLI_CHOICE_SPEC *sp = ob->spec;
951 
952     if ( sp->fontsize != size )
953     {
954         sp->fontsize = size;
955         fl_redraw_object( ob );
956     }
957 }
958 
959 
960 /***************************************
961  * Sets the font style inside the choice.
962  ***************************************/
963 
964 void
fl_set_choice_fontstyle(FL_OBJECT * ob,int style)965 fl_set_choice_fontstyle( FL_OBJECT * ob,
966                          int         style )
967 {
968     FLI_CHOICE_SPEC *sp = ob->spec;
969 
970     if ( sp->fontstyle != style )
971     {
972         sp->fontstyle = style;
973         fl_redraw_object( ob );
974     }
975 }
976 
977 
978 /***************************************
979  ***************************************/
980 
981 void
fl_set_choice_align(FL_OBJECT * ob,int align)982 fl_set_choice_align( FL_OBJECT * ob,
983                      int         align )
984 {
985     FLI_CHOICE_SPEC *sp = ob->spec;
986 
987     if ( sp->align != align )
988     {
989         sp->align = align;
990         fl_redraw_object( ob );
991     }
992 }
993 
994 
995 /***************************************
996  ***************************************/
997 
998 int
fl_set_choice_entries(FL_OBJECT * ob,FL_PUP_ENTRY * ent)999 fl_set_choice_entries(FL_OBJECT * ob, FL_PUP_ENTRY * ent )
1000 {
1001     int i,
1002         k;
1003 
1004     fl_clear_choice( ob );
1005 
1006     for ( k = 0; ent && ent->text; ent++, k++ )
1007     {
1008         i = fl_addto_choice( ob, ent->text );
1009         if ( ent->mode == FL_PUP_GRAY )
1010             fl_set_choice_item_mode( ob, i, ent->mode );
1011         if ( ent->shortcut && *ent->shortcut )
1012             fl_set_choice_item_shortcut( ob, i, ent->shortcut );
1013     }
1014 
1015     return k;
1016 }
1017 
1018 
1019 /***************************************
1020  ***************************************/
1021 
1022 int
fl_set_choice_notitle(FL_OBJECT * ob,int n)1023 fl_set_choice_notitle( FL_OBJECT * ob,
1024                        int         n )
1025 {
1026     FLI_CHOICE_SPEC *sp = ob->spec;
1027     int old = sp->no_title & NO_TITLE_MASK ? 1 : 0;
1028 
1029     if ( n )
1030         sp->no_title |= NO_TITLE_MASK;
1031     else
1032         sp->no_title &= ~ NO_TITLE_MASK;
1033 
1034     return old;
1035 }
1036 
1037 
1038 /***************************************
1039  ***************************************/
1040 
1041 int
fl_set_choice_align_bottom(FL_OBJECT * ob,int n)1042 fl_set_choice_align_bottom( FL_OBJECT * ob,
1043                             int         n )
1044 {
1045     FLI_CHOICE_SPEC *sp = ob->spec;
1046     int old = sp->no_title & ALIGN_BOTTOM_MASK ? 1 : 0;
1047 
1048     if ( n )
1049         sp->no_title |= ALIGN_BOTTOM_MASK;
1050     else
1051         sp->no_title &= ~ ALIGN_BOTTOM_MASK;
1052 
1053     return old;
1054 }
1055 
1056 
1057 
1058 
1059 /*
1060  * Local variables:
1061  * tab-width: 4
1062  * indent-tabs-mode: nil
1063  * End:
1064  */
1065