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