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 fd_spec.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  * Driver for setting object specific info
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <string.h>
34 #include <ctype.h>
35 
36 #include "fd_main.h"
37 #include "fd_spec.h"
38 #include "fd_iconinfo.h"
39 
40 #include "sp_slider.h"
41 #include "sp_counter.h"
42 #include "sp_spinner.h"
43 #include "sp_dial.h"
44 #include "sp_positioner.h"
45 #include "sp_twheel.h"
46 #include "sp_button.h"
47 #include "sp_pixmap.h"
48 #include "sp_scrollbar.h"
49 #include "sp_browser.h"
50 #include "sp_choice.h"
51 #include "sp_menu.h"
52 #include "sp_xyplot.h"
53 #include "sp_freeobj.h"
54 
55 
56 #define MAXOBJCLASS 9
57 
58 typedef struct
59 {
60 	/* List of object classes this entry is for */
61 
62     int objclass[ MAXOBJCLASS ];
63 
64     /* Function to be called for changing the objects type */
65 
66     void ( * change_type )( FL_OBJECT *, int );
67 
68 	/* Function for creating the form for editing the specific object
69 	   attributes */
70 
71 	FL_FORM * ( * create_spec_form  )( void                );
72 
73 	/* Function for adjustments of the form for e.g. the objects type */
74 
75 	void ( * adjust_spec_form  )( FL_OBJECT *         );
76 
77 	/* Function for setting up the form with the objects attributes */
78 
79 	void ( * fill_in_spec_form )( FL_OBJECT *         );
80 
81 	/* Function for setting up the object attributes according to the forms
82 	   data */
83 
84 	void ( * reread_spec_form  )( FL_OBJECT *         );
85 
86     /* Object specific code to be run when object got restored */
87 
88     void ( * restore_spec )( FL_OBJECT * );
89 
90 	/* Function for emitting code for the fd file for the object */
91 
92 	void ( * emit_spec_fd_code )( FILE *, FL_OBJECT * );
93 
94 	/* Function for emitting C code for the object */
95 
96 	void ( * emit_spec_c_code  )( FILE *, FL_OBJECT * );
97 
98 	/* Function for emitting header code for the object */
99 
100 	void ( * emit_spec_header  )( FILE *, FL_OBJECT * );
101 
102     /* */
103 
104     void ( * emit_spec_global_header )( FILE *, FL_OBJECT * );
105 
106 } ObjSPEC;
107 
108 static ObjSPEC objspec[ ] =
109 {
110     {
111         { FL_SLIDER,
112 		  FL_VALSLIDER },
113         NULL,
114         slider_create_spec_form,
115         slider_adjust_spec_form,
116         slider_fill_in_spec_form,
117         slider_reread_spec_form,
118         NULL,
119         slider_emit_spec_fd_code,
120         slider_emit_spec_c_code,
121         NULL,
122         NULL
123     },
124 
125     {
126         { FL_COUNTER },
127         NULL,
128         counter_create_spec_form,
129         counter_adjust_spec_form,
130         counter_fill_in_spec_form,
131         counter_reread_spec_form,
132         NULL,
133         counter_emit_spec_fd_code,
134         counter_emit_spec_c_code,
135         NULL,
136         NULL
137     },
138 
139     {
140         { FL_SPINNER },
141         spinner_change_type,
142         spinner_create_spec_form,
143         spinner_adjust_spec_form,
144         spinner_fill_in_spec_form,
145         spinner_reread_spec_form,
146         NULL,
147         spinner_emit_spec_fd_code,
148         spinner_emit_spec_c_code,
149         NULL,
150         NULL
151     },
152 
153     {
154         { FL_DIAL },
155         NULL,
156         dial_create_spec_form,
157         NULL,
158         dial_fill_in_spec_form,
159         dial_reread_spec_form,
160         NULL,
161         dial_emit_spec_fd_code,
162         dial_emit_spec_c_code,
163         NULL,
164         NULL
165     },
166 
167     {
168         { FL_POSITIONER },
169         NULL,
170         positioner_create_spec_form,
171         NULL,
172         positioner_fill_in_spec_form,
173         positioner_reread_spec_form,
174         NULL,
175         positioner_emit_spec_fd_code,
176         positioner_emit_spec_c_code,
177         NULL,
178         NULL
179     },
180 
181     {
182         { FL_THUMBWHEEL },
183         NULL,
184         thwheel_create_spec_form,
185         NULL,
186         twheel_fill_in_spec_form,
187         twheel_reread_spec_form,
188         NULL,
189         twheel_emit_spec_fd_code,
190         twheel_emit_spec_c_code,
191         NULL,
192         NULL
193     },
194 
195     {
196         { FL_PIXMAPBUTTON,
197 		  FL_BITMAPBUTTON,
198 		  FL_BUTTON,
199 		  FL_CHECKBUTTON,
200 		  FL_SCROLLBUTTON,
201           FL_ROUNDBUTTON,
202 		  FL_LIGHTBUTTON,
203 		  FL_ROUND3DBUTTON,
204 		  FL_LABELBUTTON },
205         NULL,
206         button_create_spec_form,
207         button_adjust_spec_form,
208         button_fill_in_spec_form,
209         button_reread_spec_form,
210         button_restore_spec,
211         button_emit_spec_fd_code,
212         button_emit_spec_c_code,
213         button_emit_spec_header,
214         NULL
215     },
216 
217     {
218         { FL_PIXMAP,
219 		  FL_BITMAP },
220         NULL,
221         pixmap_create_spec_form,
222         pixmap_adjust_spec_form,
223         pixmap_fill_in_spec_form,
224         pixmap_reread_spec_form,
225         pixmap_restore_spec,
226         pixmap_emit_spec_fd_code,
227         pixmap_emit_spec_c_code,
228         pixmap_emit_spec_header,
229         NULL
230     },
231 
232     {
233         { FL_SCROLLBAR },
234         NULL,
235         scrollbar_create_spec_form,
236         scrollbar_adjust_spec_form,
237         scrollbar_fill_in_spec_form,
238         scrollbar_reread_spec_form,
239         NULL,
240         scrollbar_emit_spec_fd_code,
241         scrollbar_emit_spec_c_code,
242         NULL,
243         NULL
244     },
245 
246     {
247         { FL_BROWSER },
248         NULL,
249         browser_create_spec_form,
250         NULL,
251         browser_fill_in_spec_form,
252         NULL,
253         NULL,
254         browser_emit_spec_fd_code,
255         browser_emit_spec_c_code,
256         NULL,
257         NULL
258     },
259 
260     {
261         { FL_CHOICE },
262         NULL,
263         choice_create_spec_form,
264         NULL,
265         choice_fill_in_spec_form,
266         NULL,
267         NULL,
268         choice_emit_spec_fd_code,
269         choice_emit_spec_c_code,
270         NULL,
271         NULL
272     },
273 
274     {
275         { FL_MENU },
276         NULL,
277         menu_create_spec_form,
278         NULL,
279         menu_fill_in_spec_form,
280         NULL,
281         NULL,
282         menu_emit_spec_fd_code,
283         menu_emit_spec_c_code,
284         menu_emit_spec_header,
285         menu_emit_spec_global_header
286     },
287 
288     {
289         { FL_XYPLOT },
290         NULL,
291         xyplot_create_spec_form,
292         xyplot_adjust_spec_form,
293         xyplot_fill_in_spec_form,
294         NULL,
295         NULL,
296         xyplot_emit_spec_fd_code,
297         xyplot_emit_spec_c_code,
298         NULL,
299         NULL
300     },
301 
302     {
303         { FL_FREE },
304         NULL,
305         freeobj_create_spec_form,
306         freeobj_adjust_spec_form,
307         freeobj_fill_in_spec_form,
308         freeobj_reread_spec_form,
309         freeobj_restore_spec,
310         freeobj_emit_spec_fd_code,
311         NULL,
312         NULL,
313         NULL
314     }
315 };
316 
317 
318 /***************************************
319  * Find the entry in the list of classes for the objects class
320  ***************************************/
321 
322 static ObjSPEC *
find_entry(FL_OBJECT * ob)323 find_entry( FL_OBJECT * ob )
324 {
325     size_t i;
326 
327     for ( i = 0; i < sizeof objspec / sizeof *objspec; i++ )
328     {
329         int *cls = objspec[ i ].objclass;
330 
331         for ( ; *cls > 0; cls++ )
332             if ( *cls == ob->objclass )
333                 return objspec + i;
334     }
335 
336     return NULL;
337 }
338 
339 
340 /***************************************
341  ***************************************/
342 
343 /***************************************
344  * Returns the form to be shown for the "Spec" tab folder
345  ***************************************/
346 
347 void
spec_change_type(FL_OBJECT * obj,int new_type)348 spec_change_type( FL_OBJECT * obj,
349                   int         new_type )
350 {
351     ObjSPEC *spec = find_entry( obj );
352     FL_OBJECT * defobj;
353 
354     if ( obj->type == new_type )
355         return;
356 
357 	/* Different types may have different default box types. If the user
358 	   obviously didn't change the box type (i.e. expects the default) make
359 	   sure that the box type is the default for the object type we switch
360 	   to. */
361 
362     defobj = find_class_default( obj->objclass, new_type );
363 
364     if ( defobj && defobj->boxtype == obj->boxtype )
365         obj->boxtype = defobj->boxtype;
366 
367     if ( spec && spec->change_type )
368         spec->change_type( obj, new_type );
369     else
370         obj->type = new_type;
371 }
372 
373 
374 /***************************************
375  * Returns the form to be shown for the "Spec" tab folder (or NULL If none
376  * exists)
377  ***************************************/
378 
379 FL_FORM *
create_spec_form(FL_OBJECT * obj)380 create_spec_form( FL_OBJECT * obj )
381 {
382     ObjSPEC *spec = find_entry( obj );
383 
384     return ( spec && spec->create_spec_form ) ?
385            spec->create_spec_form( ) : NULL;
386 }
387 
388 
389 /***************************************
390  * Prepare the form for the object specific attributes for becoming shown
391  * - the form may need adjustments because e.g. the objects type has been
392  * changed and then the form content also have to be modified. Then fill
393  * in all the objects attributes.
394  ***************************************/
395 
396 void
prepare_spec_form(FL_OBJECT * obj)397 prepare_spec_form( FL_OBJECT * obj )
398 {
399     ObjSPEC *spec = find_entry( obj );
400 
401 	if ( ! spec )
402 		return;
403 
404 	/* The form may need some modification,. e.g because the objects type
405 	   has been changed */
406 
407 	if ( spec->adjust_spec_form )
408 		spec->adjust_spec_form( obj );
409 
410 	/* Fill in the current settings of the objects attributes into the form */
411 
412 	if ( spec->fill_in_spec_form )
413 		spec->fill_in_spec_form( obj );
414 }
415 
416 
417 /***************************************
418  * When switching back to the "Generic" form or on end of editing
419  * an input field may not have been processed yet, thus reread all
420  * input fields in the form for the object specific attributes (and
421  * make sure the object gets shown with the potentially modified
422  * attributes).
423  ***************************************/
424 
425 void
reread_spec_form(FL_OBJECT * obj)426 reread_spec_form( FL_OBJECT * obj )
427 {
428     ObjSPEC *spec = find_entry( obj );
429 
430     if ( spec && spec->reread_spec_form )
431 	{
432 		spec->reread_spec_form( obj );
433 		redraw_the_form( 0 );
434 	}
435 }
436 
437 
438 /***************************************
439  ***************************************/
440 
441 void
restore_spec(FL_OBJECT * obj)442 restore_spec( FL_OBJECT * obj )
443 {
444     ObjSPEC *spec = find_entry( obj );
445 
446     if ( spec && spec->restore_spec )
447 	{
448 		spec->restore_spec( obj );
449 		redraw_the_form( 0 );
450 	}
451 }
452 
453 
454 /***************************************
455  * Function called for writing out object class specific
456  * information for an object to an .fd file
457  ***************************************/
458 
459 void
save_objclass_spec_info(FILE * fp,FL_OBJECT * obj)460 save_objclass_spec_info( FILE      * fp,
461                          FL_OBJECT * obj )
462 {
463     ObjSPEC *spec = find_entry( obj );
464 
465     if ( spec && spec->emit_spec_fd_code )
466         spec->emit_spec_fd_code( fp, obj );
467 }
468 
469 
470 /***************************************
471  * Function called for writing out object class specific
472  * information for an object to a .c file
473  ***************************************/
474 
475 void
emit_objclass_spec_info(FILE * fp,FL_OBJECT * obj)476 emit_objclass_spec_info( FILE      * fp,
477                          FL_OBJECT * obj )
478 {
479     ObjSPEC *spec = find_entry( obj );
480 
481     if ( spec && spec->emit_spec_c_code )
482         spec->emit_spec_c_code( fp, obj );
483 }
484 
485 
486 /***************************************
487  * Emit (file scope) variable code
488  ***************************************/
489 
490 void
emit_objclass_spec_header(FILE * fp,FL_OBJECT * obj)491 emit_objclass_spec_header( FILE      * fp,
492                            FL_OBJECT * obj )
493 {
494     ObjSPEC *spec = find_entry( obj );
495 
496     if ( spec && spec->emit_spec_header )
497         spec->emit_spec_header( fp, obj );
498 }
499 
500 
501 /***************************************
502  * Emit global variable declarations
503  ***************************************/
504 
505 void
emit_objclass_spec_global(FILE * fp,FL_OBJECT * obj)506 emit_objclass_spec_global( FILE      * fp,
507                            FL_OBJECT * obj )
508 {
509     ObjSPEC *spec = find_entry( obj );
510 
511     if ( spec && spec->emit_spec_global_header )
512         spec->emit_spec_global_header( fp, obj );
513 }
514 
515 
516 /***************************************
517  ***************************************/
518 
519 static int
ff_read_sp_bounds(FL_OBJECT * obj,SuperSPEC * sp)520 ff_read_sp_bounds( FL_OBJECT * obj,
521                    SuperSPEC * sp )
522 {
523     int r;
524 
525     if (    (    obj->objclass == FL_SPINNER
526               && ( r = ff_read( "%F%F", &sp->dmin, &sp->dmax ) ) < 0 )
527          || (    obj->objclass != FL_SPINNER
528               && ( r = ff_read( "%F%F", &sp->min, &sp->max ) ) < 0 )  )
529         return ff_err( "Can't read expected object bounds" );
530 
531     if ( r == 0 )
532         return ff_err( "\"bounds\" key with no or invalid values" );
533     else if ( r == 1 )
534         return ff_err( "\"bounds\" key with only one (valid) value" );
535 
536     return 0;
537 }
538 
539 
540 /***************************************
541  ***************************************/
542 
543 static int
ff_read_sp_precision(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)544 ff_read_sp_precision( FL_OBJECT * obj  FL_UNUSED_ARG,
545                       SuperSPEC * sp )
546 {
547     int r;
548 
549     if ( ( r = ff_read( "%d", &sp->prec ) ) < 0 )
550         return ff_err( "Can't read expected object precision" );
551 
552     if ( r == 0 )
553         return ff_err( "\"precision\" key with no or invalid value" );
554 
555     return 0;
556 }
557 
558 
559 /***************************************
560  ***************************************/
561 
562 static int
ff_read_sp_increment(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)563 ff_read_sp_increment( FL_OBJECT * obj  FL_UNUSED_ARG,
564                       SuperSPEC * sp )
565 {
566     int r;
567 
568     if ( ( r = ff_read( "%F%F", &sp->ldelta, &sp->rdelta) ) < 0 )
569         return ff_err( "Can't read expected object increment values" );
570 
571     if ( r == 0 )
572         return ff_err( "\"increment\" key with no or invalid values" );
573     else if ( r == 1 )
574         return ff_err( "\"increment\" key with only one valid value" );
575 
576     return 0;
577 }
578 
579 
580 /***************************************
581  ***************************************/
582 
583 static int
ff_read_sp_value(FL_OBJECT * obj,SuperSPEC * sp)584 ff_read_sp_value( FL_OBJECT * obj,
585                   SuperSPEC * sp )
586 {
587     int r;
588 
589     if ( ISBUTTON( obj->objclass ) || ISCHOICE( obj->objclass ) )
590     {
591         if ( ( r = ff_read( "%d", &sp->int_val ) ) < 0 )
592             return ff_err( "Can't read expected object value" );
593 
594         if ( ISBUTTON( obj->objclass ) )
595             fl_set_button( obj, sp->int_val );
596     }
597     else if ( obj->objclass == FL_SPINNER )
598     {
599         if ( ( r = ff_read( "%F", &sp->dval ) ) < 0 )
600             return ff_err( "Can't read expected object value" );
601     }
602     else if ( ( r = ff_read( "%F", &sp->val ) ) < 0 )
603         return ff_err( "Can't read expected object value" );
604 
605     if ( r == 0 )
606         return ff_err( "\"value\" key with no or invalid value" );
607 
608     return 0;
609 }
610 
611 
612 /***************************************
613  ***************************************/
614 
615 static int
ff_read_sp_slsize(FL_OBJECT * ob FL_UNUSED_ARG,SuperSPEC * sp)616 ff_read_sp_slsize( FL_OBJECT * ob  FL_UNUSED_ARG,
617                    SuperSPEC * sp )
618 {
619     int r;
620     if ( ( r = ff_read( "%F", &sp->slsize ) ) < 0 )
621         return ff_err( "Can't read expected object slider size" );
622 
623     if ( r == 0 )
624         return ff_err( "\"slsize\" key with no or invalid value" );
625 
626     return 0;
627 }
628 
629 
630 /***************************************
631  ***************************************/
632 
633 static int
ff_read_sp_step(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)634 ff_read_sp_step( FL_OBJECT * obj  FL_UNUSED_ARG,
635                  SuperSPEC * sp )
636 {
637     int r;
638 
639     if (    (    obj->objclass == FL_SPINNER
640               && ( r = ff_read( "%F", &sp->dstep ) ) < 0 )
641          || (    obj->objclass != FL_SPINNER
642               && ( r = ff_read( "%F", &sp->step ) ) < 0 ) )
643         return ff_err( "Can't read expected object step" );
644 
645     if ( r == 0 )
646         return ff_err( "\"step\" key with no or invalid value" );
647 
648     return 0;
649 }
650 
651 
652 /***************************************
653  ***************************************/
654 
655 static int
ff_read_sp_h_pref(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)656 ff_read_sp_h_pref( FL_OBJECT * obj  FL_UNUSED_ARG,
657                    SuperSPEC * sp )
658 {
659     int r;
660     char *p;
661     int i;
662 
663     if ( ( r = ff_read( "%v", &p ) ) < 0 )
664         return ff_err( "Can't read expected object h_pref" );
665 
666     if ( r == 0 )
667         return ff_err( "\"h_pref\" key with no or invalid value" );
668 
669     i = get_scrollbar_pref_value( p );
670 
671     fli_safe_free( p );
672 
673     if ( i < 0 )
674         return ff_err( "Invalid value for \"h_pref\" key" );
675 
676     sp->h_pref = i;
677 
678     return 0;
679 }
680 
681 
682 /***************************************
683  ***************************************/
684 
685 static int
ff_read_sp_v_pref(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)686 ff_read_sp_v_pref( FL_OBJECT * obj  FL_UNUSED_ARG,
687                    SuperSPEC * sp )
688 {
689     int r;
690     char *p;
691     int i;
692 
693     if ( ( r = ff_read( "%v", &p ) ) < 0 )
694         return ff_err( "Can't read expected object v_pref" );
695 
696     if ( r == 0 )
697         return ff_err( "\"v_pref\" key with no or invalid value" );
698 
699     i = get_scrollbar_pref_value( p );
700 
701     fli_safe_free( p );
702 
703     if ( i < 0 )
704         return ff_err( "Invalid value for \"v_pref\" key" );
705 
706     sp->v_pref = i;
707 
708     return 0;
709 }
710 
711 
712 /***************************************
713  ***************************************/
714 
715 static int
ff_read_sp_sstep(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)716 ff_read_sp_sstep( FL_OBJECT * obj  FL_UNUSED_ARG,
717                   SuperSPEC * sp )
718 {
719     int r;
720 
721     if ( ( r = ff_read( "%F", &sp->sstep ) ) < 0 )
722         return ff_err( "Can't read expected object small step" );
723 
724     if ( r == 0 )
725         return ff_err( "\"sstep\" key with no or invalid value" );
726 
727     return 0;
728 }
729 
730 
731 /***************************************
732  ***************************************/
733 
734 static int
ff_read_sp_lstep(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)735 ff_read_sp_lstep( FL_OBJECT * obj  FL_UNUSED_ARG,
736                   SuperSPEC * sp )
737 {
738     int r;
739 
740     if ( ( r = ff_read( "%F", &sp->lstep ) ) < 0 )
741         return ff_err( "Can't read expected object large step" );
742 
743     if ( r == 0 )
744         return ff_err( "\"lstep\" key with no or invalid value" );
745 
746     return 0;
747 }
748 
749 
750 /***************************************
751  ***************************************/
752 
753 static int
ff_read_sp_xbounds(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)754 ff_read_sp_xbounds( FL_OBJECT * obj  FL_UNUSED_ARG,
755                     SuperSPEC * sp )
756 {
757     int r;
758 
759     if ( ( r = ff_read( "%F%F", &sp->xmin, &sp->xmax ) ) < 0 )
760         return ff_err( "Can't read expected object xbounds" );
761 
762     if ( r == 0 )
763         return ff_err( "\"xbounds\" key with no or invalid values" );
764     else if ( r == 1 )
765         return ff_err( "\"xbounds\" key with only one valid value" );
766 
767     return 0;
768 }
769 
770 
771 /***************************************
772  ***************************************/
773 
774 static int
ff_read_sp_ybounds(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)775 ff_read_sp_ybounds( FL_OBJECT * obj  FL_UNUSED_ARG,
776                     SuperSPEC * sp )
777 {
778     int r;
779 
780     if ( ( r = ff_read( "%F%F", &sp->ymin, &sp->ymax ) ) < 0 )
781         return ff_err( "Can't read expected object ybounds" );
782 
783     if ( r == 0 )
784         return ff_err( "\"ybounds\" key with no or invalid values" );
785     else if ( r == 1 )
786         return ff_err( "\"ybounds\" key with only one valid value" );
787 
788     return 0;
789 }
790 
791 
792 /***************************************
793  ***************************************/
794 
795 static int
ff_read_sp_xvalue(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)796 ff_read_sp_xvalue( FL_OBJECT * obj  FL_UNUSED_ARG,
797                    SuperSPEC * sp )
798 {
799     int r;
800 
801     if ( ( r = ff_read( "%F", &sp->xval ) ) < 0 )
802         return ff_err( "Can't read expected object xvalue" );
803 
804     if ( r == 0 )
805         return ff_err( "\"xvalue\" key with no or invalid value" );
806 
807     return 0;
808 }
809 
810 
811 /***************************************
812  ***************************************/
813 
814 static int
ff_read_sp_yvalue(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)815 ff_read_sp_yvalue( FL_OBJECT * obj  FL_UNUSED_ARG,
816                    SuperSPEC * sp )
817 {
818     int r;
819 
820     if ( ( r = ff_read( "%F", &sp->yval ) ) < 0 )
821         return ff_err( "Can't read expected object yvalue" );
822 
823     if ( r == 0 )
824         return ff_err( "\"yvalue\" key with no or invalid value" );
825 
826     return 0;
827 }
828 
829 
830 /***************************************
831  ***************************************/
832 
833 static int
ff_read_sp_xstep(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)834 ff_read_sp_xstep( FL_OBJECT * obj  FL_UNUSED_ARG,
835                   SuperSPEC * sp )
836 {
837     int r;
838 
839     if ( ( r = ff_read( "%F", &sp->xstep ) ) < 0 )
840         return ff_err( "Can't read expected object xstep" );
841 
842     if ( r == 0 )
843         return ff_err( "\"xstep\" key with no or invalid value" );
844 
845     return 0;
846 }
847 
848 
849 /***************************************
850  ***************************************/
851 
852 static int
ff_read_sp_ystep(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)853 ff_read_sp_ystep( FL_OBJECT * obj  FL_UNUSED_ARG,
854                   SuperSPEC * sp )
855 {
856     int r;
857 
858     if ( ( r = ff_read( "%F", &sp->ystep ) ) < 0 )
859         return ff_err( "Can't read expected object ystep" );
860 
861     if ( r == 0 )
862         return ff_err( "\"ystep\" key with no or invalid value" );
863 
864     return 0;
865 }
866 
867 
868 /***************************************
869  ***************************************/
870 
871 static int
ff_read_sp_angles(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)872 ff_read_sp_angles( FL_OBJECT * obj  FL_UNUSED_ARG,
873                    SuperSPEC * sp )
874 {
875     int r;
876 
877     if ( ( r = ff_read( "%F%F", &sp->thetai, &sp->thetaf ) ) < 0 )
878         return ff_err( "Can't read expected object angles" );
879 
880     if ( r == 0 )
881         return ff_err( "\"angles\" key with no or invalid values" );
882     else if ( r == 1 )
883         return ff_err( "\"angles\" key with only one valid value" );
884 
885     return 0;
886 }
887 
888 
889 /***************************************
890  ***************************************/
891 
892 static int
ff_read_sp_mbuttons(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)893 ff_read_sp_mbuttons( FL_OBJECT * obj  FL_UNUSED_ARG,
894                      SuperSPEC * sp )
895 {
896     int r;
897 
898     if ( ( r = ff_read( "%d", &sp->mbuttons ) ) < 0 )
899         return ff_err( "Can't read expected object mbuttons setting" );
900 
901     if ( r == 0 )
902         return ff_err( "\"mbuttons\" key with no or invalid value" );
903 
904     return 0;
905 }
906 
907 
908 /***************************************
909  ***************************************/
910 
911 static int
ff_read_sp_initial_val(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)912 ff_read_sp_initial_val( FL_OBJECT * obj  FL_UNUSED_ARG,
913                         SuperSPEC * sp )
914 {
915     int r;
916 
917     if ( ( r = ff_read( "%F", &sp->val ) ) < 0 )
918         return ff_err( "Can't read expected object initial value" );
919 
920     if ( r == 0 )
921         return ff_err( "\"initial_val\" key with no or invalid value" );
922 
923     return 0;
924 }
925 
926 
927 /***************************************
928  ***************************************/
929 
930 static int
ff_read_sp_content(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)931 ff_read_sp_content( FL_OBJECT * obj  FL_UNUSED_ARG,
932                     SuperSPEC * sp )
933 {
934     char *p;
935 
936     if ( ff_read( "%S", &p ) < 0 )
937         return ff_err( "Can't read expected object content" );
938 
939     ++sp->nlines;
940     sp->content  = fl_realloc( sp->content,
941                                ( sp->nlines + 1 ) * sizeof *sp->content );
942     sp->shortcut = fl_realloc( sp->shortcut,
943                                ( sp->nlines + 1 ) * sizeof *sp->shortcut );
944     sp->callback = fl_realloc( sp->callback,
945                                ( sp->nlines + 1 ) * sizeof *sp->callback );
946     sp->mode     = fl_realloc( sp->mode,
947                                ( sp->nlines + 1 ) * sizeof *sp->mode );
948     sp->mval     = fl_realloc( sp->mval,
949                                ( sp->nlines + 1 ) * sizeof *sp->mval );
950 
951     sp->content[ sp->nlines ]  = p;
952     sp->shortcut[ sp->nlines ] = NULL;
953     sp->callback[ sp->nlines ] = NULL;
954     sp->mode[ sp->nlines ]     = 0;
955     sp->mval[ sp->nlines ]     = sp->nlines;
956 
957     return 0;
958 }
959 
960 
961 /***************************************
962  ***************************************/
963 
964 static int
ff_read_sp_mode(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)965 ff_read_sp_mode( FL_OBJECT * obj  FL_UNUSED_ARG,
966                  SuperSPEC * sp )
967 {
968     int r;
969     char *p;
970     int i;
971 
972     if ( ( r = ff_read( "%v", &p ) ) < 0 )
973         return ff_err( "Can't read expected object mode" );
974 
975     if ( r == 0 )
976         return ff_err( "\"mode\" key with no or invalid value" );
977 
978     i = get_pupmode_value( p );
979 
980     fli_safe_free( p );
981 
982     if ( i < 0 )
983         return ff_err( "Invalid value for \"mode\" key" );
984 
985     sp->mode[ sp->nlines ] = i;
986 
987     return 0;
988 }
989 
990 
991 /***************************************
992  ***************************************/
993 
994 static int
ff_read_sp_shortcut(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)995 ff_read_sp_shortcut( FL_OBJECT * obj  FL_UNUSED_ARG,
996                      SuperSPEC * sp )
997 {
998     char *p;
999 
1000     if ( ff_read( "%s", &p) < 0 )
1001         return ff_err( "Can't read expected object shortcut" );
1002 
1003     sp->shortcut[ sp->nlines ] = p;
1004 
1005     return 0;
1006 }
1007 
1008 
1009 /***************************************
1010  ***************************************/
1011 
1012 static int
ff_read_sp_callback(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1013 ff_read_sp_callback( FL_OBJECT * obj  FL_UNUSED_ARG,
1014                      SuperSPEC * sp )
1015 {
1016     char *p;
1017 
1018     if ( ff_read( "%v", &p) < 0 )
1019         return ff_err( "Can't read expected object callback" );
1020 
1021     sp->callback[ sp->nlines ] = p;
1022 
1023     return 0;
1024 }
1025 
1026 
1027 /***************************************
1028  ***************************************/
1029 
1030 static int
ff_read_sp_id(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1031 ff_read_sp_id( FL_OBJECT * obj  FL_UNUSED_ARG,
1032                SuperSPEC * sp )
1033 {
1034     int r;
1035 
1036     if ( ( r = ff_read( "%d", sp->mval + sp->nlines ) ) < 0 )
1037         return ff_err( "Can't read expected object id" );
1038 
1039     if ( r == 0 )
1040         return ff_err( "\"id\" key with no or invalid value" );
1041 
1042     return 0;
1043 }
1044 
1045 
1046 /***************************************
1047  ***************************************/
1048 
1049 static int
ff_read_sp_file(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1050 ff_read_sp_file( FL_OBJECT * obj,
1051                  SuperSPEC * sp  FL_UNUSED_ARG )
1052 {
1053     char *p;
1054     IconInfo *info = get_iconinfo( obj );
1055 
1056     if ( ! info )
1057         return ff_err( "Invalid \"file\" attribute for object type found" );
1058 
1059     if ( ff_read( "%S", &p ) < 0 )
1060         return ff_err( "Can't read expected object \"file\" attribute" );
1061 
1062     if ( strlen( p ) >= sizeof info->filename )
1063         return ff_err( "Filename for \"file\" key too long" );
1064 
1065     strcpy( info->filename, p );
1066 
1067     fli_safe_free( p );
1068 
1069     return 0;
1070 }
1071 
1072 
1073 /***************************************
1074  ***************************************/
1075 
1076 static int
ff_read_sp_focus_file(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1077 ff_read_sp_focus_file( FL_OBJECT * obj,
1078                        SuperSPEC * sp  FL_UNUSED_ARG )
1079 {
1080     char *p;
1081     IconInfo *info = get_iconinfo( obj );
1082 
1083     if ( ! info )
1084         return ff_err( "Invalid \"focus\" attribute for object type found" );
1085 
1086     if ( ff_read( "%S", &p ) < 0 )
1087         return ff_err( "Can't read expected object \"focus\" attribute" );
1088 
1089     if ( strlen( p ) >= sizeof info->focus_filename )
1090         return ff_err( "Filename for \"focus_file\" key too long" );
1091 
1092     strcpy( info->focus_filename, p );
1093 
1094     fli_safe_free( p );
1095 
1096     return 0;
1097 }
1098 
1099 
1100 /***************************************
1101  ***************************************/
1102 
1103 static int
ff_read_sp_handler(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1104 ff_read_sp_handler( FL_OBJECT * obj,
1105                     SuperSPEC * sp  FL_UNUSED_ARG )
1106 {
1107     int r;
1108     char *p;
1109 
1110     if ( ( r = ff_read( "%v", &p ) ) < 0 )
1111         return ff_err( "Can't read expected object handler" );
1112 
1113     if ( r == 0 )
1114         return ff_err( "\"handler\" key with no or invalid value" );
1115 
1116     obj->c_vdata = p;
1117 
1118     return 0;
1119 }
1120 
1121 
1122 /***************************************
1123  ***************************************/
1124 
1125 static int
ff_read_sp_data(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1126 ff_read_sp_data( FL_OBJECT * obj,
1127                  SuperSPEC * sp  FL_UNUSED_ARG )
1128 {
1129     char *p;
1130     IconInfo *info = get_iconinfo( obj );
1131 
1132     if ( ! info )
1133         return ff_err( "Invalid data structrure for object type found" );
1134 
1135     if ( ff_read( "%v", &p ) < 0 )
1136         return ff_err( "Can't read expected object data attribute" );
1137 
1138     strcpy( info->data, p );
1139 
1140     fli_safe_free( p );
1141 
1142     if ( *info->data )
1143         info->use_data = 1;
1144 
1145     return 0;
1146 }
1147 
1148 
1149 /***************************************
1150  ***************************************/
1151 
1152 static int
ff_read_sp_focus_data(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1153 ff_read_sp_focus_data( FL_OBJECT * obj,
1154                        SuperSPEC * sp  FL_UNUSED_ARG )
1155 {
1156     char *p;
1157     IconInfo *info = get_iconinfo( obj );
1158 
1159     if ( ! info )
1160         return ff_err( "Invalid \"focus_data\" attribute for object type "
1161                        "found" );
1162 
1163     if ( ff_read( "%v", &p ) < 0 )
1164         return ff_err( "Can't read expected object \"focus_data\" attribute" );
1165 
1166     strcpy( info->focus_data, p );
1167 
1168     fli_safe_free( p );
1169 
1170     return 0;
1171 }
1172 
1173 
1174 /***************************************
1175  ***************************************/
1176 
1177 static int
ff_read_sp_fullpath(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1178 ff_read_sp_fullpath( FL_OBJECT * obj,
1179                      SuperSPEC * sp  FL_UNUSED_ARG )
1180 {
1181     int r;
1182     IconInfo *info = get_iconinfo( obj );
1183 
1184     if ( ! info )
1185         return ff_err( "Invalid \"fullpath\" attribute for object type found" );
1186 
1187     if ( ( r = ff_read( "%d", &info->fullpath) ) < 0 )
1188         return ff_err( "Can't read expected object \"fullpath\" attribute" );
1189 
1190     if ( r == 0 )
1191         return ff_err( "\"fullpath\" key with no or invalid value" );
1192 
1193     return 0;
1194 }
1195 
1196 
1197 /***************************************
1198  ***************************************/
1199 
1200 static int
ff_read_sp_width(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1201 ff_read_sp_width( FL_OBJECT * obj,
1202                   SuperSPEC * sp  FL_UNUSED_ARG )
1203 {
1204     char *p;
1205     IconInfo *info = get_iconinfo( obj );
1206 
1207     if ( ! info )
1208         return ff_err( "Invalid \"width\" attribute for object type found" );
1209 
1210     if ( ff_read( "%v", &p ) < 0 )
1211         return ff_err( "Can't read expected object \"width\" attribute" );
1212 
1213     strcpy( info->width, p );
1214 
1215     fli_safe_free( p );
1216 
1217     return 0;
1218 }
1219 
1220 
1221 /***************************************
1222  ***************************************/
1223 
1224 static int
ff_read_sp_height(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1225 ff_read_sp_height( FL_OBJECT * obj,
1226                    SuperSPEC * sp  FL_UNUSED_ARG )
1227 {
1228     char *p;
1229     IconInfo *info = get_iconinfo( obj );
1230 
1231     if ( ! info )
1232         return ff_err( "Invalid \"height\" attribute for object type found" );
1233 
1234     if ( ff_read( "%v", &p ) < 0 )
1235         return ff_err( "Can't read expected object \"height\" attribute" );
1236 
1237     strcpy( info->height, p );
1238 
1239     fli_safe_free( p );
1240 
1241     return 0;
1242 }
1243 
1244 
1245 /***************************************
1246  ***************************************/
1247 
1248 static int
ff_read_sp_align(FL_OBJECT * obj,SuperSPEC * sp)1249 ff_read_sp_align( FL_OBJECT * obj,
1250                   SuperSPEC * sp )
1251 {
1252     int r;
1253     IconInfo *info = get_iconinfo( obj );
1254     int align;
1255 
1256     if ( ( r = ff_read( "%a", &align ) ) < 0 )
1257         return ff_err( "Can't read expected object align attribute" );
1258 
1259     align &= ~FL_ALIGN_INSIDE;
1260 
1261     if ( r == 0 )
1262         return ff_err( "Invalid value for \"align\" attribute" );
1263 
1264     if ( info )
1265         info->align = align;
1266     else
1267         sp->align = align;
1268 
1269     return 0;
1270 }
1271 
1272 
1273 /***************************************
1274  ***************************************/
1275 
1276 static int
ff_read_sp_struct(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1277 ff_read_sp_struct( FL_OBJECT * obj  FL_UNUSED_ARG,
1278                    SuperSPEC * sp )
1279 {
1280     int r;
1281 
1282     if ( ( r = ff_read( "%d", &sp->new_menuapi ) ) < 0 )
1283         return ff_err( "Can't read expected object struct attribute" );
1284 
1285     if ( r == 0 )
1286         return ff_err( "\"struct\" key with no or invalid value" );
1287 
1288     return 0;
1289 }
1290 
1291 
1292 /***************************************
1293  ***************************************/
1294 
1295 static int
ff_read_sp_global(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1296 ff_read_sp_global( FL_OBJECT * obj  FL_UNUSED_ARG,
1297                    SuperSPEC * sp )
1298 {
1299     int r;
1300 
1301     if ( ( r = ff_read( "%d", &sp->global_scope ) ) < 0 )
1302         return ff_err( "Can't read expected object global attribute" );
1303 
1304     if ( r == 0 )
1305         return ff_err( "\"global\" key with no or invalid value" );
1306 
1307     return 0;
1308 }
1309 
1310 
1311 /***************************************
1312  ***************************************/
1313 
1314 static int
ff_read_sp_focus(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1315 ff_read_sp_focus( FL_OBJECT * obj  FL_UNUSED_ARG,
1316                   SuperSPEC * sp )
1317 {
1318     int r;
1319 
1320     if ( ( r = ff_read( "%d", &sp->show_focus ) ) < 0 )
1321         return ff_err( "Can't read expected object focus attribute" );
1322 
1323     if ( r == 0 )
1324         return ff_err( "\"focus\" key with no or invalid value" );
1325 
1326     return 0;
1327 }
1328 
1329 
1330 /***************************************
1331  ***************************************/
1332 
1333 static int
ff_read_sp_xtics(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1334 ff_read_sp_xtics( FL_OBJECT * obj  FL_UNUSED_ARG,
1335                   SuperSPEC * sp )
1336 {
1337     int r;
1338 
1339     if ( ( r = ff_read( "%d%d", &sp->xmajor, &sp->xminor ) ) < 0 )
1340         return ff_err( "Can't read expected object xtics values" );
1341 
1342     if ( r == 0 )
1343         return ff_err( "\"xtics\" key with no or invalid values" );
1344     else if ( r == 1 )
1345         return ff_err( "\"xtics\" key with only one valid value" );
1346 
1347     return 0;
1348 }
1349 
1350 
1351 /***************************************
1352  ***************************************/
1353 
1354 static int
ff_read_sp_ytics(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1355 ff_read_sp_ytics( FL_OBJECT * obj  FL_UNUSED_ARG,
1356                   SuperSPEC * sp )
1357 {
1358     int r;
1359 
1360     if ( ( r = ff_read( "%d%d", &sp->ymajor, &sp->yminor ) ) < 0 )
1361         return ff_err( "Can't read expected object ytics values" );
1362 
1363     if ( r == 0 )
1364         return ff_err( "\"ytics\" key with no or invalid values" );
1365     else if ( r == 1 )
1366         return ff_err( "\"ytics\" key with only one valid value" );
1367 
1368     return 0;
1369 }
1370 
1371 
1372 /***************************************
1373  ***************************************/
1374 
1375 static int
ff_read_sp_xscale(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1376 ff_read_sp_xscale( FL_OBJECT * obj  FL_UNUSED_ARG,
1377                    SuperSPEC * sp )
1378 {
1379     int r;
1380     char *p;
1381     int xscale;
1382 
1383     if ( ( r = ff_read( "%h%f", &p, &sp->xbase ) ) < 0 )
1384         return ff_err( "Can't read expected object xscale values" );
1385 
1386     if ( r == 0 )
1387         return ff_err( "\"xscale\" key with no or invalid values" );
1388 
1389     xscale = get_scale_value( p );
1390 
1391     fli_safe_free( p );
1392 
1393     if ( xscale < 0 )
1394         return ff_err( "Invalid value for first value for \"xscale\" key" );
1395 
1396     sp->xscale = xscale;
1397 
1398     if ( r == 1 )
1399         return ff_err( "\"xscale\" key with only one valid value" );
1400 
1401     return 0;
1402 }
1403 
1404 
1405 /***************************************
1406  ***************************************/
1407 
1408 static int
ff_read_sp_yscale(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1409 ff_read_sp_yscale( FL_OBJECT * obj  FL_UNUSED_ARG,
1410                    SuperSPEC * sp )
1411 {
1412     int r;
1413     char *p;
1414     int yscale;
1415 
1416     if ( ( r = ff_read( "%h%f", &p, &sp->ybase ) ) < 0 )
1417         return ff_err( "Can't read expected object yscale values" );
1418 
1419     if ( r == 0 )
1420         return ff_err( "\"yscale\" key with no or invalid values" );
1421 
1422     yscale = get_scale_value( p );
1423 
1424     fli_safe_free( p );
1425 
1426     if ( yscale < 0 )
1427         return ff_err( "Invalid value for first value for \"yscale\" key" );
1428 
1429     sp->yscale = yscale;
1430 
1431     if ( r == 1 )
1432         return ff_err( "\"yscale\" key with only one valid value" );
1433 
1434     return 0;
1435 }
1436 
1437 
1438 /***************************************
1439  ***************************************/
1440 
1441 static int
ff_read_sp_grid(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1442 ff_read_sp_grid( FL_OBJECT * obj  FL_UNUSED_ARG,
1443                  SuperSPEC * sp )
1444 {
1445     int r;
1446     char *p1, *p2;
1447     int g;
1448 
1449     if ( ( r = ff_read( "%v%v", &p1, &p2) ) < 0 )
1450         return ff_err( "Can't read expected object grid attribute" );
1451 
1452     if ( r == 0 )
1453         return ff_err( "\"grid\" key with no or invalid values" );
1454 
1455     g = get_grid_value( p1 );
1456 
1457     fli_safe_free( p1 );
1458 
1459     if ( g < 0 )
1460         return ff_err( "Invalid first value for \"grid\" key" );
1461 
1462     sp->xgrid = g;
1463 
1464     if ( r != 2 )
1465         return ff_err( "\"grid\" key with only one valid value" );
1466 
1467     g = get_grid_value( p2 );
1468 
1469     fli_safe_free( p2 );
1470 
1471     if ( g < 0 )
1472         return ff_err( "Invalid second value for \"grid\" key" );
1473 
1474     sp->ygrid = g;
1475 
1476     return 0;
1477 }
1478 
1479 
1480 /***************************************
1481  ***************************************/
1482 
1483 static int
ff_read_sp_gridstyle(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1484 ff_read_sp_gridstyle( FL_OBJECT * obj  FL_UNUSED_ARG,
1485                       SuperSPEC * sp )
1486 {
1487     int r;
1488     char *p;
1489     int g;
1490 
1491     if ( ( r = ff_read( "%v", &p ) ) < 0 )
1492         return ff_err( "Can't read expected object gridstyle attribute" );
1493 
1494     if ( r == 0 )
1495         return ff_err( "\"gridstyle\" key with no or invalid value" );
1496 
1497     g = get_linestyle_value( p );
1498 
1499     fli_safe_free( p );
1500 
1501     if ( g < 0 )
1502         return ff_err( "Invalid value for \"gridstyle\" key" );
1503 
1504     sp->grid_linestyle = g;
1505 
1506     return 0;
1507 }
1508 
1509 
1510 /***************************************
1511  ***************************************/
1512 
1513 static int
ff_read_sp_markactive(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1514 ff_read_sp_markactive( FL_OBJECT * obj  FL_UNUSED_ARG,
1515                        SuperSPEC * sp )
1516 {
1517     int r;
1518 
1519     if ( ( r = ff_read( "%d", &sp->mark_active ) ) < 0 )
1520         return ff_err( "Can't read expected object markactive attribute" );
1521 
1522     if ( r == 0 )
1523         return ff_err( "\"markactive\" key with no or invalid value" );
1524 
1525     return 0;
1526 }
1527 
1528 
1529 /***************************************
1530  ***************************************/
1531 
1532 static int
ff_read_sp_dir(FL_OBJECT * obj FL_UNUSED_ARG,SuperSPEC * sp)1533 ff_read_sp_dir( FL_OBJECT * obj  FL_UNUSED_ARG,
1534                 SuperSPEC * sp )
1535 {
1536     int r;
1537     char *p;
1538     int dir;
1539 
1540     if ( ( r = ff_read( "%v", &p ) ) < 0 )
1541         return ff_err( "Can't read expected object dir attribute" );
1542 
1543     if ( r == 0 )
1544         return ff_err( "\"dir\" key with no or invalid value" );
1545 
1546     dir = get_direction_value( p );
1547 
1548     fli_safe_free( p );
1549 
1550     if ( dir < 0 )
1551         return ff_err( "Invalid value for \"dir\" key" );
1552 
1553     sp->direction = dir;
1554 
1555     return 0;
1556 }
1557 
1558 
1559 /***************************************
1560  * Duplication of code in fd_file.c since in older versions
1561  * the return setting was considered an object specific
1562  * attribute while now all objects have it
1563  ***************************************/
1564 
1565 static int
ff_read_sp_return(FL_OBJECT * obj,SuperSPEC * sp FL_UNUSED_ARG)1566 ff_read_sp_return( FL_OBJECT * obj,
1567                    SuperSPEC * sp  FL_UNUSED_ARG )
1568 {
1569     int r;
1570     char *return_name;
1571     int ret;
1572 
1573     if ( ( r = ff_read( "%s", &return_name ) ) < 0 )
1574         return ff_err( "Can't read expected object return" );
1575 
1576     if ( r == 0 )
1577         return ff_err( "\"return\" key with no or invalid value" );
1578 
1579     ret = get_how_return_val( return_name );
1580 
1581     fli_safe_free( return_name );
1582 
1583     if ( ret == -1 )
1584         return ff_err( "Invalid value for \"return\" key" );
1585 
1586     fl_set_object_return( obj, ret );
1587 
1588     return 0;
1589 }
1590 
1591 
1592 /***************************************
1593  ***************************************/
1594 
1595 typedef int ( * spec_attr_func )( FL_OBJECT *, SuperSPEC * );
1596 
1597 typedef struct {
1598     const char     * name;
1599     spec_attr_func   func;
1600 } spec_attr_handlers;
1601 
1602 
1603 static spec_attr_handlers attr_array[ ] =
1604 {
1605     { "bounds",      ff_read_sp_bounds      },
1606     { "precision",   ff_read_sp_precision   },
1607     { "increment",   ff_read_sp_increment   },
1608     { "value",       ff_read_sp_value       },
1609     { "slsize",      ff_read_sp_slsize      },
1610     { "step",        ff_read_sp_step        },
1611     { "h_pref",      ff_read_sp_h_pref      },
1612     { "v_pref",      ff_read_sp_v_pref      },
1613     { "sstep",       ff_read_sp_sstep       },
1614     { "lstep",       ff_read_sp_lstep       },
1615     { "xbounds",     ff_read_sp_xbounds     },
1616     { "ybounds",     ff_read_sp_ybounds     },
1617     { "xvalue",      ff_read_sp_xvalue      },
1618     { "yvalue",      ff_read_sp_yvalue      },
1619     { "xstep",       ff_read_sp_xstep       },
1620     { "ystep",       ff_read_sp_ystep       },
1621     { "angles",      ff_read_sp_angles      },
1622     { "mbuttons",    ff_read_sp_mbuttons    },
1623     { "initial_val", ff_read_sp_initial_val },
1624     { "content",     ff_read_sp_content     },
1625     { "mode",        ff_read_sp_mode        },
1626     { "shortcut",    ff_read_sp_shortcut    },
1627     { "callback",    ff_read_sp_callback    },
1628     { "id",          ff_read_sp_id          },
1629     { "file",        ff_read_sp_file        },
1630     { "focus_file",  ff_read_sp_focus_file  },
1631     { "handler",     ff_read_sp_handler     },
1632     { "data",        ff_read_sp_data        },
1633     { "focus_data",  ff_read_sp_focus_data  },
1634     { "fullpath",    ff_read_sp_fullpath    },
1635     { "width",       ff_read_sp_width       },
1636     { "height",      ff_read_sp_height      },
1637     { "align",       ff_read_sp_align       },
1638     { "struct",      ff_read_sp_struct      },
1639     { "global",      ff_read_sp_global      },
1640     { "focus",       ff_read_sp_focus       },
1641     { "xtics",       ff_read_sp_xtics       },
1642     { "ytics",       ff_read_sp_ytics       },
1643     { "xscale",      ff_read_sp_xscale      },
1644     { "yscale",      ff_read_sp_yscale      },
1645     { "grid",        ff_read_sp_grid        },
1646     { "gridstyle",   ff_read_sp_gridstyle   },
1647     { "markactive",  ff_read_sp_markactive  },
1648     { "dir",         ff_read_sp_dir         },
1649     { "return",      ff_read_sp_return      }
1650 };
1651 
1652 
1653 /***************************************
1654  * If we don't know what to do with object specific informations skip them.
1655  * This way we (hopefully) remain compatible with later versions
1656  ***************************************/
1657 
1658 static int
skip_spec_info(char * key)1659 skip_spec_info( char * key )
1660 {
1661     char *rest,
1662          *p;
1663     int r;
1664 
1665     /* Skip everything up to either the start of the next form or object or
1666        the end of the file */
1667 
1668     do
1669     {
1670         fli_safe_free( key );
1671 
1672         if ( ff_read( "%s", &rest ) < 0 )
1673             return ff_err( "Failed to read from file" );
1674 
1675         fli_safe_free( rest );
1676 
1677         if ( ( r = ff_read( "%k", &key ) ) < 0 )
1678             return ff_err( "Failed to read from file" );
1679 
1680     } while ( r != 0 && strcmp( key, "Name" ) && strcmp( key, "class" ) );
1681 
1682     /* Check if we arrived at the start of a form or class */
1683 
1684     if (  ! strcmp( key, "Name" ) )
1685     {
1686         fli_safe_free( key );
1687         return FF_AT_START_OF_FORM;
1688     }
1689     else if ( ! strcmp( key, "class" ) )
1690     {
1691         fli_safe_free( key );
1692         return FF_AT_START_OF_OBJECT;
1693     }
1694 
1695     /* Otherwise we now have to look for the name of the main function */
1696 
1697     if ( ff_read( "%v", &p ) < 1 )
1698         return ff_err( "Expected main function name, not found here" );
1699     else
1700     {
1701         fli_sstrcpy( main_name, p, MAX_VAR_LEN );
1702         fli_safe_free( p );
1703     }
1704 
1705     return FF_AT_END_OF_FILE;
1706 }
1707 
1708 
1709 /***************************************
1710  * Function for reading in object specific information
1711  ***************************************/
1712 
1713 int
load_objclass_spec_info(FL_OBJECT * obj,char * key)1714 load_objclass_spec_info( FL_OBJECT * obj,
1715                          char *      key )
1716 {
1717     int r;
1718     size_t i;
1719     char *p;
1720     SuperSPEC *sp = get_superspec( obj );
1721 
1722     if ( ! find_entry( obj ) )
1723         return skip_spec_info( key );
1724 
1725     /* Loop until no more object specific key is found. Note: when we
1726        arrive here the first key already has been read in! */
1727 
1728     do
1729     {
1730         for ( i = 0; i < sizeof attr_array / sizeof *attr_array; i++ )
1731             if ( ! strcmp( key, attr_array[ i ].name ) )
1732             {
1733                 fli_safe_free( key );
1734 
1735                 if ( attr_array[ i ].func( obj, sp ) == FF_READ_FAILURE )
1736                     return FF_READ_FAILURE;
1737                 break;
1738             }
1739 
1740         /* An unexpected key has read, give up */
1741 
1742         if ( i >= sizeof attr_array / sizeof *attr_array )
1743         {
1744             char *tmp = fl_malloc(   strlen( "Read invalid object specific "
1745                                              "key: " )
1746                                    + strlen( key ) + 1 );
1747 
1748             if ( tmp )
1749             {
1750                 sprintf( tmp, "Read invalid object specific key: %s", key );
1751                 ff_err( tmp );
1752                 fl_free( tmp );
1753             }
1754 
1755             fli_safe_free( key );
1756             return FF_READ_FAILURE;
1757         }
1758 
1759         fli_safe_free( key );
1760 
1761         if ( ( r = ff_read( "%k", &key ) ) < 0 )
1762             return ff_err( "Failed to read from file" );
1763 
1764     } while ( r != 0 && strcmp( key, "Name" ) && strcmp( key, "class" ) );
1765 
1766     superspec_to_spec( obj );
1767     restore_spec( obj );
1768 
1769     /* Check if we should be at the last line of the file and then read
1770        name of main function */
1771 
1772     if ( r == 0 )
1773     {
1774         if ( ff_read( "%v", &p ) < 1 )
1775             return ff_err( "Expected main function name, not found here" );
1776         else
1777         {
1778             fli_sstrcpy( main_name, p, MAX_VAR_LEN );
1779             fli_safe_free( p );
1780         }
1781 
1782         return FF_AT_END_OF_FILE;
1783     }
1784 
1785     /* Otherwise we should be at start of new object... */
1786 
1787     if ( ! strcmp( key, "class" ) )
1788     {
1789         fli_safe_free( key );
1790         return FF_AT_START_OF_OBJECT;
1791     }
1792 
1793     /* ...or start of new form */
1794 
1795     fli_safe_free( key );
1796     return FF_AT_START_OF_FORM;
1797 }
1798 
1799 
1800 /* Utilities */
1801 
1802 /***************************************
1803  ***************************************/
1804 
1805 void
set_finput_value(FL_OBJECT * ob,double f,int prec)1806 set_finput_value( FL_OBJECT * ob,
1807                   double      f,
1808                   int         prec)
1809 {
1810     char buf[ 64 ];
1811 
1812     if ( prec > 20 )
1813         prec = 20;
1814 
1815     if ( prec >= 0 )
1816     {
1817         if ( fabs( f ) < 1.0e38 && fabs( f ) > 1.0e-38 )
1818             sprintf( buf, "%.*f", prec, f );
1819         else
1820             sprintf( buf, "%.*g", prec, f );
1821     }
1822     else
1823         sprintf( buf, "%g", f );
1824 
1825     fl_set_input( ob, buf );
1826 }
1827 
1828 
1829 /***************************************
1830  ***************************************/
1831 
1832 int
get_checked_float(const char * str,double * r)1833 get_checked_float( const char * str,
1834                    double     * r )
1835 {
1836     char *eptr;
1837 
1838     if ( ! str || ! r || ! *str )
1839         return 0;
1840 
1841     *r = strtod( str, &eptr );
1842 
1843     return    ! *eptr
1844            && ! ( ( *r == HUGE_VAL || *r == -HUGE_VAL ) && errno == ERANGE );
1845 }
1846 
1847 
1848 /***************************************
1849  ***************************************/
1850 
1851 int
get_checked_int(const char * str,int * r)1852 get_checked_int( const char * str,
1853                  int        * r )
1854 {
1855     char *eptr;
1856 
1857     if ( ! str || ! r || ! *str )
1858         return 0;
1859 
1860     *r = strtol( str, &eptr, 10 );
1861 
1862     return ! *eptr && *r <= INT_MAX && *r >= INT_MIN;
1863 }
1864 
1865 
1866 /***************************************
1867  ***************************************/
1868 
1869 double
get_finput_value(FL_OBJECT * ob)1870 get_finput_value( FL_OBJECT * ob )
1871 {
1872     double f = 0;
1873     const char *s = fl_get_input( ob );
1874 
1875     if ( s && *s )
1876         sscanf( s, "%lf", &f );
1877 
1878     return f;
1879 }
1880 
1881 
1882 /*  scrollbar preference settings */
1883 
1884 #define VN( v )  { v, #v }
1885 
1886 static FLI_VN_PAIR scrbpref[ ] =
1887 {
1888     VN( FL_OFF  ),
1889     VN( FL_ON   ),
1890     VN( FL_AUTO ),
1891     { -1, NULL }
1892 };
1893 
1894 
1895 /* must be in the same order as the above */
1896 
1897 
1898 /***************************************
1899  ***************************************/
1900 
1901 const char *
get_scrollbar_pref_string(void)1902 get_scrollbar_pref_string( void )
1903 {
1904     return "Off|On|Auto ";
1905 }
1906 
1907 
1908 /***************************************
1909  ***************************************/
1910 
1911 const char *
get_scrollbar_pref_name(int a)1912 get_scrollbar_pref_name( int a )
1913 {
1914     return fli_get_vn_name( scrbpref, a );
1915 }
1916 
1917 
1918 /***************************************
1919  ***************************************/
1920 
1921 int
get_scrollbar_pref_value(const char * s)1922 get_scrollbar_pref_value( const char * s )
1923 {
1924     return fli_get_vn_value( scrbpref, s );
1925 }
1926 
1927 /* xyplot scale */
1928 
1929 static FLI_VN_PAIR scale_vn[ ] =
1930 {
1931     VN( FL_LINEAR ),
1932     VN( FL_LOG ),
1933     { -1, NULL }
1934 };
1935 
1936 
1937 /***************************************
1938  ***************************************/
1939 
1940 const char *
get_scale_name(int a)1941 get_scale_name( int a )
1942 {
1943     return fli_get_vn_name( scale_vn, a );
1944 }
1945 
1946 
1947 /***************************************
1948  ***************************************/
1949 
1950 int
get_scale_value(const char * s)1951 get_scale_value( const char * s )
1952 {
1953     return fli_get_vn_value( scale_vn, s );
1954 }
1955 
1956 
1957 /***************************************
1958  ***************************************/
1959 
1960 const char *
get_scale_string(void)1961 get_scale_string( void )
1962 {
1963     return "Linear|Log";
1964 }
1965 
1966 
1967 /* xyplot grid */
1968 
1969 static FLI_VN_PAIR grid_vn[ ] =
1970 {
1971     VN( FL_GRID_NONE ),
1972     VN( FL_GRID_MAJOR ),
1973     VN( FL_GRID_MINOR ),
1974     { -1, NULL }
1975 };
1976 
1977 
1978 /***************************************
1979  ***************************************/
1980 
1981 const char *
get_grid_name(int a)1982 get_grid_name( int a )
1983 {
1984     return fli_get_vn_name( grid_vn, a );
1985 }
1986 
1987 
1988 /***************************************
1989  ***************************************/
1990 
1991 int
get_grid_value(const char * s)1992 get_grid_value( const char * s )
1993 {
1994     return fli_get_vn_value( grid_vn, s );
1995 }
1996 
1997 
1998 /***************************************
1999  ***************************************/
2000 
2001 const char *
get_grid_string(void)2002 get_grid_string( void )
2003 {
2004     return "None|Major|Minor";
2005 }
2006 
2007 
2008 /* Line style string stuff */
2009 
2010 static FLI_VN_PAIR linestyle[ ] =
2011 {
2012     VN( FL_SOLID ),
2013     VN( FL_USERDASH ),
2014     VN( FL_USERDOUBLEDASH ),
2015     VN( FL_DOT ),
2016     VN( FL_DOTDASH ),
2017     VN( FL_DASH ),
2018     VN( FL_LONGDASH ),
2019     { -1, NULL }
2020 };
2021 
2022 
2023 /***************************************
2024  ***************************************/
2025 
2026 const char *
get_linestyle_string(void)2027 get_linestyle_string( void )
2028 {
2029     return "Solid|UserDash|DoubleDash|Dot|DotDash|Dash|LongDash";
2030 }
2031 
2032 
2033 /***************************************
2034  ***************************************/
2035 
2036 const char *
get_linestyle_name(int a)2037 get_linestyle_name( int a )
2038 {
2039     return fli_get_vn_name( linestyle, a );
2040 }
2041 
2042 
2043 /***************************************
2044  ***************************************/
2045 
2046 int
get_linestyle_value(const char * s)2047 get_linestyle_value( const char * s )
2048 {
2049     return fli_get_vn_value( linestyle, s );
2050 }
2051 
2052 
2053 /* popup mode */
2054 
2055 static FLI_VN_PAIR pupmode[ ] =
2056 {
2057     VN( FL_PUP_NONE ),
2058     VN( FL_PUP_GRAY ),
2059     VN( FL_PUP_BOX ),
2060     VN( FL_PUP_CHECK ),
2061     VN( FL_PUP_RADIO ),
2062     { -1, NULL }
2063 };
2064 
2065 
2066 /***************************************
2067  ***************************************/
2068 
2069 const char *
get_pupmode_string(void)2070 get_pupmode_string( void )
2071 {
2072     return "PUP_NONE|PUP_GRAY|PUP_BOX|PUP_CHECK|PUP_RADIO";
2073 }
2074 
2075 
2076 /***************************************
2077  ***************************************/
2078 
2079 const char *
get_pupmode_name(int a)2080 get_pupmode_name( int a )
2081 {
2082     return fli_get_vn_name( pupmode, a );
2083 }
2084 
2085 
2086 /***************************************
2087  ***************************************/
2088 
2089 int
get_pupmode_value(const char * s)2090 get_pupmode_value( const char * s )
2091 {
2092     char buf[ 32 ];
2093 
2094     strcpy( buf, s );
2095     if ( *buf != 'F' )
2096         strcat( strcpy( buf, "FL_" ), s );
2097     return fli_get_vn_value( pupmode, buf );
2098 }
2099 
2100 
2101 /*
2102  * Local variables:
2103  * tab-width: 4
2104  * indent-tabs-mode: nil
2105  * End:
2106  */
2107