1 /*
2 * This file is part of XForms.
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 sp_menu.c
21 *
22 * This file is part of XForms package
23 * Copyright (c) 1996-2002 T.C. Zhao and Mark Overmars
24 * All rights reserved.
25 *
26 * Setting menu class specific attributes.
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <ctype.h>
34
35 #include "fd_main.h"
36 #include "fd_spec.h"
37 #include "sp_menu.h"
38 #include "private/pmenu.h"
39 #include "spec/menu_spec.h"
40
41 static FD_menuattrib *menu_attrib;
42 static FL_OBJECT *curobj;
43
44 static const char * int_out( FL_OBJECT * ob,
45 double val,
46 int prec );
47 static char * get_pupentry_name( FL_OBJECT * obj );
48
49
50 /***************************************
51 ***************************************/
52
53 FL_FORM *
menu_create_spec_form(void)54 menu_create_spec_form( void )
55 {
56 if ( menu_attrib )
57 return menu_attrib->menuattrib;
58
59 menu_attrib = create_form_menuattrib( );
60 fl_addto_choice( menu_attrib->mode, get_pupmode_string( ) );
61 fl_addto_choice( menu_attrib->scope, "local|global" );
62 fl_set_choice_item_shortcut( menu_attrib->mode, 1, "Nn#N" );
63 fl_set_choice_item_shortcut( menu_attrib->mode, 1, "Gg#G" );
64 fl_set_choice_item_shortcut( menu_attrib->mode, 1, "Bb#B" );
65 fl_set_choice_item_shortcut( menu_attrib->mode, 1, "Cc#C" );
66 fl_set_choice_item_shortcut( menu_attrib->mode, 1, "Rr#R" );
67 fl_set_browser_dblclick_callback( menu_attrib->content_br,
68 change_menu_item_cb, 0 );
69
70 return menu_attrib->menuattrib;
71 }
72
73
74 /***************************************
75 ***************************************/
76
77 void
menu_fill_in_spec_form(FL_OBJECT * obj)78 menu_fill_in_spec_form( FL_OBJECT * obj )
79 {
80 FLI_MENU_SPEC *sp = obj->spec;
81 SuperSPEC *ssp = get_superspec( obj );
82 int i;
83 int mval = sp->numitems + 1;
84
85 curobj = obj;
86
87 fl_freeze_form( menu_attrib->content_br->form );
88
89 fl_set_button( menu_attrib->new_menuapi, ssp->new_menuapi );
90 fl_clear_browser( menu_attrib->content_br );
91
92 for ( i = 1; i <= sp->numitems; i++ )
93 {
94 fl_add_browser_line( menu_attrib->content_br, sp->items[ i ] );
95 if ( sp->mval[ i ] >= mval )
96 mval = sp->mval[ i ] + 1;
97 }
98
99 fl_set_choice( menu_attrib->scope, ssp->global_scope + 1 );
100
101 if ( ssp->new_menuapi )
102 fl_hide_object( menu_attrib->id );
103 else
104 fl_show_object( menu_attrib->id );
105
106 fl_set_counter_filter( menu_attrib->id, int_out );
107 fl_set_counter_value( menu_attrib->id, sp->numitems + 1 );
108
109 fl_unfreeze_form( menu_attrib->content_br->form );
110 }
111
112
113 /***************************************
114 ***************************************/
115
116 void
menu_emit_spec_fd_code(FILE * fp,FL_OBJECT * obj)117 menu_emit_spec_fd_code( FILE * fp,
118 FL_OBJECT * obj )
119 {
120 FL_OBJECT *defobj = fl_create_menu( obj->type, 0, 0, 0, 0, "" );
121 FLI_MENU_SPEC *sp = obj->spec,
122 *defsp = defobj->spec;
123 SuperSPEC *ssp = get_superspec( obj ),
124 *defssp = get_superspec( defobj );
125 int i;
126
127 if ( ssp->new_menuapi != defssp->new_menuapi )
128 fprintf( fp, " struct: %d\n", ssp->new_menuapi );
129
130 if ( ssp->global_scope != defssp->global_scope )
131 fprintf( fp, " global: %d\n", ssp->global_scope );
132
133 for ( i = 1; i <= sp->numitems; i++ )
134 {
135 if ( sp->items[ i ] )
136 fprintf( fp, " content: %s\n", sp->items[ i ] );
137 fprintf( fp, " id: %d\n", sp->mval[ i ] );
138
139 if ( sp->mode[ i ] != defsp->mode[ i ] )
140 fprintf( fp, " mode: %s\n", get_pupmode_name(sp->mode[ i ] ) );
141
142 if ( sp->shortcut[ i ] && *sp->shortcut[ i ] )
143 fprintf( fp, " shortcut: %s\n", sp->shortcut[ i ] );
144
145 if ( ssp->callback && ssp->callback[ i ] )
146 fprintf( fp, " callback: %s\n", ssp->callback[ i ] );
147 }
148
149 free_superspec( defobj );
150 fl_free_object( defobj );
151 }
152
153
154 /***************************************
155 ***************************************/
156
157 void
menu_emit_spec_c_code(FILE * fp,FL_OBJECT * obj)158 menu_emit_spec_c_code( FILE * fp,
159 FL_OBJECT * obj )
160 {
161 FL_OBJECT *defobj;
162 FLI_MENU_SPEC *sp = obj->spec,
163 *defsp;
164 SuperSPEC *ssp;
165
166 if ( sp->numitems == 0 )
167 return;
168
169 /* Create a default object */
170
171 defobj = fl_create_menu( obj->type, 0, 0, 0, 0, "" );
172 defsp = defobj->spec;
173
174 ssp = get_superspec( obj );
175
176 if ( ssp->new_menuapi )
177 fprintf( fp, " fl_set_menu_entries( obj, %s );\n", ssp->misc_char );
178 else
179 {
180 int i;
181
182 for ( i = 1; i <= sp->numitems; i++ )
183 {
184 fprintf( fp, " fl_addto_menu( obj, \"%s\" );\n",
185 sp->items[ i ] );
186
187 if ( sp->mode[ i ] != defsp->mode[ i ] )
188 fprintf(fp, " fl_set_menu_item_mode( obj, %d, %s );\n",
189 i, get_pupmode_name( sp->mode[ i ] ) );
190
191 if ( sp->shortcut[ i ] && *sp->shortcut[ i ] )
192 fprintf( fp,
193 " fl_set_menu_item_shortcut( obj, %d, \"%s\" );\n",
194 i, sp->shortcut[ i ] );
195
196 if ( ssp->callback[ i ] && *ssp->callback[ i ] )
197 fprintf( fp, " fl_set_menu_item_callback( obj, %d, %s );\n",
198 i, ssp->callback[ i ] );
199
200 if ( sp->mval[ i ] != i )
201 fprintf( fp, " fl_set_menu_item_id( obj, %d, %d );\n",
202 i, sp->mval[ i ] );
203 }
204 }
205
206 fl_free_object( defobj );
207 }
208
209
210 /***************************************
211 * emit things that are needed before code emission (file scope)
212 ***************************************/
213
214 void
menu_emit_spec_header(FILE * fp,FL_OBJECT * obj)215 menu_emit_spec_header( FILE * fp,
216 FL_OBJECT * obj )
217 {
218 FLI_MENU_SPEC *sp = obj->spec;
219 SuperSPEC *ssp = get_superspec( obj );
220 int i;
221
222 if ( ! ssp->new_menuapi || sp->numitems <= 0 )
223 return;
224
225 get_pupentry_name( obj );
226
227 fprintf( fp, "\n%sFL_PUP_ENTRY %s[ ] = {\n",
228 ssp->global_scope ? "" : "static ", ssp->misc_char );
229 fprintf( fp, " /* itemtext callback shortcut mode */\n" );
230
231 for ( i = 1; i <= sp->numitems; i++ )
232 fprintf( fp, " { \"%s\", %s, \"%s\", %s, { 0, 0 } },\n",
233 sp->items[ i ],
234 ( ssp->callback[ i ] && *ssp->callback[ i ] ) ?
235 ( char * ) ssp->callback[ i ] : "NULL",
236 sp->shortcut[ i ] ? sp->shortcut[ i ] : "",
237 get_pupmode_name( sp->mode[ i ] ) );
238
239 /* sentinel */
240
241 fprintf( fp, " { NULL, 0, NULL, 0, { 0, 0 } }\n};\n\n");
242 }
243
244
245 /***************************************
246 * emit header info that is global in nature
247 ***************************************/
248
249 void
menu_emit_spec_global_header(FILE * fp,FL_OBJECT * obj)250 menu_emit_spec_global_header( FILE * fp,
251 FL_OBJECT * obj )
252 {
253 FLI_MENU_SPEC *sp = obj->spec;
254 SuperSPEC *ssp = get_superspec( obj );
255
256 if ( ! ssp->new_menuapi || sp->numitems <= 0 || ! ssp->global_scope )
257 return;
258
259 get_pupentry_name( obj );
260
261 fprintf( fp, "extern FL_PUP_ENTRY %s[ ];\n", ssp->misc_char );
262 }
263
264
265 /***************************************
266 * Emit menu item callback prototypes or function definitions
267 ***************************************/
268
269 void
menu_emit_item_callback_headers(FILE * fn,FL_OBJECT * obj,int code)270 menu_emit_item_callback_headers( FILE * fn,
271 FL_OBJECT * obj,
272 int code )
273 {
274 FLI_MENU_SPEC *sp = obj->spec;
275 SuperSPEC *ssp = get_superspec( obj );
276 int i;
277
278 if ( ssp->new_menuapi || sp->numitems <= 0 )
279 return;
280
281 for ( i = 1; i <= sp->numitems; i++ )
282 {
283 if ( ! ssp->callback[ i ] )
284 continue;
285
286 if ( ! code )
287 fprintf( fn, "int %s( int );\n", ssp->callback[ i ] );
288 else
289 {
290 fprintf( fn, "/***************************************\n"
291 " ***************************************/\n\n" );
292 fprintf( fn, "int %s( int menu_item_ID )\n{\n",
293 ssp->callback[ i ] );
294 fprintf( fn, " /* fill-in code for menu item callback */\n\n"
295 " return menu_item_ID;\n}\n\n\n" );
296 }
297 }
298 }
299
300
301 /***************************************
302 ***************************************/
303
304 static const char *
int_out(FL_OBJECT * ob FL_UNUSED_ARG,double val,int prec FL_UNUSED_ARG)305 int_out( FL_OBJECT * ob FL_UNUSED_ARG,
306 double val,
307 int prec FL_UNUSED_ARG )
308 {
309 static char buf[ 20 ];
310
311 sprintf( buf, "%d", FL_nint( val ) );
312 return buf;
313 }
314
315
316 /***************************************
317 * create a name for the [menu|choice]_entry API and hang it off
318 * sp->misc_char
319 ***************************************/
320
321 static char *
get_pupentry_name(FL_OBJECT * obj)322 get_pupentry_name( FL_OBJECT * obj )
323 {
324 static int n = 0;
325 char pupname[ 128 ],
326 *p;
327 char objname[ 128 ],
328 cbname[ 128 ],
329 argname[ 128 ];
330 FLI_MENU_SPEC *sp = obj->spec;
331 SuperSPEC *ssp = get_superspec( obj );
332 int i;
333
334 if ( ! ssp->new_menuapi || sp->numitems <= 0 )
335 return "";
336
337 if ( ssp->misc_char && *ssp->misc_char )
338 return ssp->misc_char;
339
340 get_object_name( obj, objname, cbname, argname );
341
342 if ( *objname )
343 sprintf( pupname, "fdmenu_%s_%d", objname, n );
344 else if ( *obj->label )
345 sprintf( pupname, "fdmenu_%s_%d", obj->label, n );
346 else
347 sprintf( pupname, "fdmenu_%d", n );
348
349 n++;
350
351 /* Get rid of illegal chars */
352
353 for ( i = 0, p = pupname; *p; p++ )
354 if ( isalnum( ( unsigned char ) *p ) || *p == '_' )
355 pupname[ i++ ] = *p;
356
357 pupname[ i++ ] = '\0';
358 fli_safe_free ( ssp->misc_char );
359 ssp->misc_char = fl_strdup( pupname );
360
361 return ssp->misc_char;
362 }
363
364
365 /*
366 * attributes callbacks
367 */
368
369 /***************************************
370 * callbacks and freeobj handles for form choiceattrib
371 ***************************************/
372
373 void
add_menu_item_cb(FL_OBJECT * obj FL_UNUSED_ARG,long data FL_UNUSED_ARG)374 add_menu_item_cb( FL_OBJECT * obj FL_UNUSED_ARG,
375 long data FL_UNUSED_ARG )
376 {
377 FLI_MENU_SPEC *sp = curobj->spec;
378 int i,
379 k;
380
381 const char *s = fl_get_input( menu_attrib->input );
382 const char *sc = fl_get_input( menu_attrib->shortcut );
383 const char *mode = fl_get_choice_text( menu_attrib->mode );
384 const char *item_cb = fl_get_input( menu_attrib->item_cb );
385 int mval = fl_get_counter_value( menu_attrib->id );
386
387 if ( ! s || ! *s )
388 return;
389
390 fl_addto_browser( menu_attrib->content_br, s );
391
392 i = fl_addto_menu( curobj, s );
393
394 k = sp->mval[ i ];
395 fl_set_menu_item_shortcut( curobj, k, sc );
396
397 fl_set_menu_item_mode( curobj, k, get_pupmode_value( mode ) );
398
399 fli_safe_free( sp->cb[ i ] );
400
401 if ( item_cb && *item_cb )
402 fl_set_menu_item_callback( curobj, k,
403 ( FL_PUP_CB ) fl_strdup( item_cb ) );
404 if ( k != mval )
405 fl_set_menu_item_id( curobj, i, mval );
406
407 if ( fl_get_button( menu_attrib->auto_clear ) )
408 clear_menu_field_cb( menu_attrib->auto_clear, 0 );
409
410 redraw_the_form( 0 );
411 }
412
413
414 /***************************************
415 ***************************************/
416
417 void
replace_menu_item_cb(FL_OBJECT * obj FL_UNUSED_ARG,long data FL_UNUSED_ARG)418 replace_menu_item_cb( FL_OBJECT * obj FL_UNUSED_ARG,
419 long data FL_UNUSED_ARG )
420 {
421 FLI_MENU_SPEC *sp = curobj->spec;
422 int i = fl_get_browser( menu_attrib->content_br );
423 const char *s = fl_get_input( menu_attrib->input );
424 const char *sc = fl_get_input( menu_attrib->shortcut );
425 const char *mode = fl_get_choice_text( menu_attrib->mode );
426 const char *item_cb = fl_get_input( menu_attrib->item_cb );
427 int mval = fl_get_counter_value( menu_attrib->id );
428 int k;
429
430 if ( ! *s || i <= 0 )
431 return;
432
433 fl_replace_browser_line( menu_attrib->content_br, i, s );
434
435 k = sp->mval[ i ];
436
437 fl_replace_menu_item( curobj, k, s );
438
439 fl_set_menu_item_shortcut( menu_attrib->vdata, k, sc );
440
441 fl_set_menu_item_mode( curobj, k, get_pupmode_value( mode ) );
442
443 fli_safe_free( sp->cb[ i ] );
444
445 if ( item_cb && *item_cb )
446 fl_set_menu_item_callback( curobj, k,
447 ( FL_PUP_CB ) fl_strdup( item_cb ) );
448 if ( k != mval )
449 fl_set_menu_item_id( curobj, i, mval );
450
451 if ( fl_get_button( menu_attrib->auto_clear ) )
452 clear_menu_field_cb( menu_attrib->auto_clear, 0 );
453
454 redraw_the_form( 0 );
455 }
456
457
458 /***************************************
459 ***************************************/
460
461 void
delete_menu_item_cb(FL_OBJECT * obj FL_UNUSED_ARG,long data FL_UNUSED_ARG)462 delete_menu_item_cb( FL_OBJECT * obj FL_UNUSED_ARG,
463 long data FL_UNUSED_ARG )
464 {
465 FLI_MENU_SPEC *sp = curobj->spec;
466 int i = fl_get_browser( menu_attrib->content_br );
467
468 if ( i <= 0 )
469 return;
470
471 fl_delete_browser_line( menu_attrib->content_br, i );
472 fli_safe_free( sp->cb[ i ] );
473 fl_delete_menu_item( curobj, sp->mval[ i ] );
474 redraw_the_form( 0 );
475 }
476
477
478 /***************************************
479 ***************************************/
480
481 void
change_menu_item_cb(FL_OBJECT * obj FL_UNUSED_ARG,long data FL_UNUSED_ARG)482 change_menu_item_cb( FL_OBJECT * obj FL_UNUSED_ARG,
483 long data FL_UNUSED_ARG )
484 {
485 int i = fl_get_browser( menu_attrib->content_br );
486 FLI_MENU_SPEC *sp = curobj->spec;
487
488 if ( i <= 0 )
489 return;
490
491 fl_set_input( menu_attrib->input,
492 fl_get_browser_line( menu_attrib->content_br, i ) );
493
494 if ( sp->shortcut[ i ] )
495 fl_set_input( menu_attrib->shortcut, sp->shortcut[ i ] );
496
497 fl_set_choice_text( menu_attrib->mode,
498 get_pupmode_name( sp->mode[ i ] ) + 3 );
499
500 if ( sp->cb[ i ] )
501 fl_set_input( menu_attrib->item_cb, ( char * ) sp->cb[ i ] );
502 else
503 fl_set_input( menu_attrib->item_cb, "" );
504
505 fl_set_counter_value( menu_attrib->id, sp->mval[ i ] );
506 }
507
508
509 /***************************************
510 ***************************************/
511
512 void
clear_menu_field_cb(FL_OBJECT * obj FL_UNUSED_ARG,long data FL_UNUSED_ARG)513 clear_menu_field_cb( FL_OBJECT * obj FL_UNUSED_ARG,
514 long data FL_UNUSED_ARG )
515 {
516 int i;
517 FLI_MENU_SPEC *sp = curobj->spec;
518 int mval = sp->numitems + 1;
519
520 fl_set_input( menu_attrib->input, "" );
521 fl_set_input( menu_attrib->shortcut, "" );
522 fl_set_choice( menu_attrib->mode, 1 );
523 fl_set_input( menu_attrib->item_cb, "" );
524
525 for ( i = 1; i <= sp->numitems; i++ )
526 if ( sp->mval[ i ] >= mval )
527 mval = sp->mval[ i ] + 1;
528
529 fl_set_counter_value( menu_attrib->id, mval );
530 }
531
532
533 /***************************************
534 ***************************************/
535
536 void
new_menuapi_cb(FL_OBJECT * obj,long data FL_UNUSED_ARG)537 new_menuapi_cb( FL_OBJECT * obj,
538 long data FL_UNUSED_ARG )
539 {
540 SuperSPEC * ssp = curobj->u_vdata;
541
542 ssp->new_menuapi = fl_get_button( obj );
543
544 if ( ssp->new_menuapi )
545 fl_hide_object( menu_attrib->id );
546 else
547 fl_show_object( menu_attrib->id );
548 }
549
550
551 /***************************************
552 ***************************************/
553
554 void
menuentry_scope_cb(FL_OBJECT * obj,long data FL_UNUSED_ARG)555 menuentry_scope_cb( FL_OBJECT * obj,
556 long data FL_UNUSED_ARG )
557 {
558 ( ( SuperSPEC * ) curobj->u_vdata )->global_scope =
559 ( fl_get_choice( obj ) - 1 ) > 0;
560 }
561
562
563 #include "spec/menu_spec.c"
564
565
566 /*
567 * Local variables:
568 * tab-width: 4
569 * indent-tabs-mode: nil
570 * End:
571 */
572