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_super.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  * translation between superspec and spec
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include "fd_main.h"
34 #include "fd_spec.h"
35 
36 #include "private/pslider.h"
37 #include "private/pbrowser.h"
38 #include "private/ppositioner.h"
39 #include "private/pcounter.h"
40 #include "private/pspinner.h"
41 #include "private/pscrollbar.h"
42 #include "private/pdial.h"
43 #include "private/pxyplot.h"
44 #include "private/pchoice.h"
45 #include "private/pmenu.h"
46 #include "private/pinput.h"
47 
48 
49 /***************************************
50  ***************************************/
51 
52 SuperSPEC *
get_superspec(FL_OBJECT * ob)53 get_superspec( FL_OBJECT * ob )
54 {
55     SuperSPEC *sp = ob->u_vdata;
56 
57     return sp ? sp : spec_to_superspec( ob );
58 }
59 
60 
61 /***************************************
62  ***************************************/
63 
64 SuperSPEC *
spec_to_superspec(FL_OBJECT * obj)65 spec_to_superspec( FL_OBJECT * obj )
66 {
67     SuperSPEC *ssp;
68     int i;
69     int n;
70 
71     if ( ! obj->u_vdata )
72     {
73         obj->u_vdata = ssp = fl_calloc( 1, sizeof *ssp );
74 
75         ssp->content    = NULL;
76         ssp->shortcut   = NULL;
77         ssp->callback   = NULL;
78         ssp->mode       = NULL;
79         ssp->mval       = NULL;
80         ssp->misc_char  = NULL;
81 
82         ssp->new_menuapi = 0;
83         ssp->nlines      = 0;
84     }
85     else
86         ssp = obj->u_vdata;
87 
88     if ( obj->objclass == FL_BROWSER )
89     {
90         FLI_BROWSER_SPEC *sp = obj->spec;
91 
92         ssp->h_pref = sp->h_pref;
93         ssp->v_pref = sp->v_pref;
94 
95         for ( i = 1; i <= ssp->nlines; i++ )
96             fl_free( ssp->content[ i ] );
97 
98         n = ssp->nlines = fl_get_browser_maxline( obj );
99 
100         ssp->content  = fl_realloc( ssp->content,
101                                     ( n + 1 ) * sizeof *ssp->content );
102 
103         for ( i = 1; i <= n; i++ )
104             ssp->content[ i ] = fl_strdup( fl_get_browser_line( obj, i ) );
105     }
106     else if ( obj->objclass == FL_CHOICE )
107     {
108         FLI_CHOICE_SPEC *sp = obj->spec;
109 
110         for ( i = 1; i <= ssp->nlines; i++ )
111         {
112             fl_free( ssp->content[ i ] );
113             fl_free( ssp->shortcut[ i ] );
114         }
115 
116         n = ssp->nlines = sp->numitems;
117 
118         ssp->content  = fl_realloc( ssp->content,
119                                     ( n + 1 ) * sizeof *ssp->content );
120         ssp->shortcut = fl_realloc( ssp->shortcut,
121                                     ( n + 1 ) * sizeof *ssp->shortcut );
122         ssp->mode     = fl_realloc( ssp->mode,
123                                     ( n + 1 ) * sizeof *ssp->mode );
124 
125         ssp->align   = sp->align;
126         ssp->int_val = sp->val;
127 
128         for ( i = 1; i <= n; i++ )
129         {
130             ssp->content[ i ] = fl_strdup( fl_get_choice_item_text( obj, i ) );
131 
132             if ( sp->shortcut[ i ] )
133                 ssp->shortcut[ i ] = fl_strdup( sp->shortcut[ i ] );
134             else
135                 ssp->shortcut[ i ] = NULL;
136         }
137 
138         memcpy( ssp->mode, sp->mode, ( n + 1 ) * sizeof *ssp->mode );
139 
140     }
141     else if ( obj->objclass == FL_MENU )
142     {
143         FLI_MENU_SPEC *sp = obj->spec;
144 
145         for ( i = 1; i <= ssp->nlines; i++ )
146         {
147             fl_free( ssp->content[ i ] );
148             fl_free( ssp->shortcut[ i ] );
149             fl_free( ssp->callback[ i ] );
150         }
151 
152         n = ssp->nlines = sp->numitems;
153 
154         ssp->content  = fl_realloc( ssp->content,
155                                     ( n + 1 ) * sizeof *ssp->content );
156         ssp->shortcut = fl_realloc( ssp->shortcut,
157                                     ( n + 1 ) * sizeof *ssp->shortcut );
158         ssp->callback = fl_realloc( ssp->callback,
159                                     ( n + 1 ) * sizeof *ssp->callback );
160         ssp->mode     = fl_realloc( ssp->mode,
161                                     ( n + 1 ) * sizeof *ssp->mode );
162         ssp->mval     = fl_realloc( ssp->mval,
163                                     ( n + 1 ) * sizeof *ssp->mval );
164 
165         for ( i = 1; i <= n; i++ )
166         {
167             ssp->content[ i ] =
168                       fl_strdup( fl_get_menu_item_text( obj, sp->mval[ i ] ) );
169 
170             if ( sp->shortcut[ i ] )
171                 ssp->shortcut[ i ] = fl_strdup( sp->shortcut[ i ] );
172             else
173                 ssp->shortcut[ i ] = NULL;
174 
175             if ( sp->cb[ i ] )
176                 ssp->callback[ i ] = fl_strdup( ( char * ) sp->cb[ i ] );
177             else
178                 ssp->callback[ i ] = NULL;
179         }
180 
181         memcpy( ssp->mode, sp->mode, ( n + 1 ) * sizeof *ssp->mode );
182         memcpy( ssp->mval, sp->mval, ( n + 1 ) * sizeof *ssp->mval );
183 
184     }
185     else if (    obj->objclass == FL_SLIDER
186               || obj->objclass == FL_VALSLIDER
187               || obj->objclass == FL_THUMBWHEEL )
188     {
189         FLI_SLIDER_SPEC *sp = obj->spec;
190 
191         ssp->val        = sp->val;
192         ssp->min        = sp->min;
193         ssp->max        = sp->max;
194         ssp->step       = sp->step;
195         ssp->prec       = sp->prec;
196         ssp->ldelta     = sp->ldelta;
197         ssp->rdelta     = sp->rdelta;
198         ssp->slsize     = sp->slsize;
199     }
200     else if (    ISBUTTON( obj->objclass )
201               || obj->objclass == FL_PIXMAP
202               || obj->objclass == FL_BITMAP )
203     {
204         FL_BUTTON_SPEC *sp = obj->spec;
205 
206         ssp->mbuttons = 0;
207         for ( i = 0; i < 5; i++ )
208             if ( sp->react_to[ i ] )
209                 ssp->mbuttons |= 1 << i;
210 
211         ssp->int_val = sp->val;
212     }
213     else if ( obj->objclass == FL_POSITIONER )
214     {
215         FLI_POSITIONER_SPEC *sp = obj->spec;
216 
217         ssp->xstep      = sp->xstep;
218         ssp->ystep      = sp->ystep;
219         ssp->xmin       = sp->xmin;
220         ssp->xmax       = sp->xmax;
221         ssp->xval       = sp->xval;
222         ssp->ymin       = sp->ymin;
223         ssp->ymax       = sp->ymax;
224         ssp->yval       = sp->yval;
225     }
226     else if ( obj->objclass == FL_COUNTER )
227     {
228         FLI_COUNTER_SPEC *sp = obj->spec;
229 
230         ssp->val        = sp->val;
231         ssp->lstep      = sp->lstep;
232         ssp->sstep      = sp->sstep;
233         ssp->min        = sp->min;
234         ssp->max        = sp->max;
235         ssp->prec       = sp->prec;
236     }
237     else if ( obj->objclass == FL_DIAL )
238     {
239         FLI_DIAL_SPEC *sp = obj->spec;
240 
241         ssp->min        = sp->min;
242         ssp->max        = sp->max;
243         ssp->val        = sp->val;
244         ssp->step       = sp->step;
245         ssp->thetai     = sp->thetai;
246         ssp->thetaf     = sp->thetaf;
247         ssp->direction  = sp->direction;
248     }
249     else if ( obj->objclass == FL_XYPLOT )
250     {
251         FLI_XYPLOT_SPEC *sp = obj->spec;
252 
253         ssp->xmajor         = sp->xmajor;
254         ssp->xminor         = sp->xminor;
255         ssp->ymajor         = sp->ymajor;
256         ssp->yminor         = sp->yminor;
257         ssp->xscale         = sp->xscale;
258         ssp->yscale         = sp->yscale;
259         ssp->xgrid          = sp->xgrid;
260         ssp->ygrid          = sp->ygrid;
261         ssp->grid_linestyle = sp->grid_linestyle;
262         ssp->xbase          = sp->xbase;
263         ssp->ybase          = sp->ybase;
264         ssp->mark_active    = sp->mark_active;
265     }
266     else if ( obj->objclass == FL_SCROLLBAR )
267     {
268         FLI_SCROLLBAR_SPEC *scbsp = obj->spec;
269         FLI_SLIDER_SPEC *sp = scbsp->slider->spec;
270 
271         ssp->val    = sp->val;
272         ssp->min    = sp->min;
273         ssp->max    = sp->max;
274         ssp->prec   = sp->prec;
275         ssp->step   = sp->step;
276         ssp->slsize = sp->slsize;
277         ssp->ldelta = sp->ldelta;
278         ssp->rdelta = sp->rdelta;
279     }
280     else if ( obj->objclass == FL_SPINNER )
281     {
282         FLI_SPINNER_SPEC *sp = obj->spec;
283 
284         ssp->val = fl_get_spinner_value( obj );
285         fl_get_spinner_bounds( obj, &ssp->min, &ssp->max );
286         ssp->step = fl_get_spinner_step( obj );
287         ssp->prec = fl_get_spinner_precision( obj );
288         ssp->orient = sp->orient;
289     }
290 
291     return ssp;
292 }
293 
294 
295 /***************************************
296  ***************************************/
297 
298 void *
superspec_to_spec(FL_OBJECT * obj)299 superspec_to_spec( FL_OBJECT * obj )
300 {
301     void *v = obj->spec;
302     SuperSPEC *ssp = obj->u_vdata;
303     int i = 0;
304 
305     if ( ! ssp )
306         return v;
307 
308     if ( obj->objclass == FL_BROWSER )
309     {
310         FLI_BROWSER_SPEC *sp = obj->spec;
311 
312         fl_clear_browser( obj );
313 
314         sp->h_pref = ssp->h_pref;
315         sp->v_pref = ssp->v_pref;
316 
317         for ( i = 1; i <= ssp->nlines; i++ )
318             fl_addto_browser( obj, ssp->content[ i ] );
319     }
320     else if ( obj->objclass == FL_CHOICE )
321     {
322         fl_clear_choice( obj );
323 
324         ( ( FLI_CHOICE_SPEC * ) obj->spec)->align = ssp->align;
325 
326         for ( i = 1; i <= ssp->nlines; i++ )
327         {
328             fl_addto_choice( obj, ssp->content[ i ] );
329             if ( ssp->shortcut[ i ] )
330                 fl_set_choice_item_shortcut( obj, i, ssp->shortcut[ i ] );
331             fl_set_choice_item_mode( obj, i, ssp->mode[ i ] );
332         }
333 
334         if ( ssp->nlines >= ssp->int_val )
335             fl_set_choice( obj, ssp->int_val );
336     }
337     else if ( obj->objclass == FL_MENU )
338     {
339         fl_clear_menu( obj );
340 
341         for ( i = 1; i <= ssp->nlines; i++ )
342         {
343             fl_addto_menu( obj, ssp->content[ i ] );
344             if ( ssp->shortcut[ i ] )
345                 fl_set_menu_item_shortcut( obj, i, ssp->shortcut[ i ] );
346             if ( ssp->callback[ i ] )
347                 fl_set_menu_item_callback( obj, i,
348                                ( FL_PUP_CB ) fl_strdup( ssp->callback[ i ] ) );
349             fl_set_menu_item_mode( obj, i, ssp->mode[ i ] );
350             if ( ssp->mval[ i ] != i )
351                 fl_set_menu_item_id( obj, i, ssp->mval[ i ] );
352         }
353     }
354     else if (    obj->objclass == FL_SLIDER
355               || obj->objclass == FL_VALSLIDER
356               || obj->objclass == FL_THUMBWHEEL)
357     {
358         FLI_SLIDER_SPEC *sp = obj->spec;
359 
360         sp->val    = ssp->val;
361         sp->min    = ssp->min;
362         sp->max    = ssp->max;
363         sp->step   = ssp->step;
364         sp->prec   = ssp->prec;
365         sp->ldelta = ssp->ldelta;
366         sp->rdelta = ssp->rdelta;
367         sp->slsize = ssp->slsize;
368     }
369     else if (    ISBUTTON( obj->objclass )
370               || obj->objclass == FL_PIXMAP
371               || obj->objclass == FL_BITMAP )
372     {
373         FL_BUTTON_SPEC *sp = obj->spec;
374 
375         for ( i = 0; i < 5; i++ )
376             sp->react_to[ i ] = ( ssp->mbuttons & ( 1 << i ) ) != 0;
377         if ( ISBUTTON( obj->objclass ) )
378             fl_set_button_mouse_buttons( obj, ssp->mbuttons );
379 
380         sp->val = ssp->int_val;
381 
382         if ( ISBUTTON( obj->objclass ) )
383             fl_set_button( obj, sp->val );
384     }
385     else if ( obj->objclass == FL_POSITIONER )
386     {
387         FLI_POSITIONER_SPEC *sp = obj->spec;
388 
389         sp->xstep      = ssp->xstep;
390         sp->ystep      = ssp->ystep;
391         sp->xmin       = ssp->xmin;
392         sp->xmax       = ssp->xmax;
393         sp->xval       = ssp->xval;
394         sp->ymin       = ssp->ymin;
395         sp->ymax       = ssp->ymax;
396         sp->yval       = ssp->yval;
397     }
398     else if ( obj->objclass == FL_COUNTER )
399     {
400         FLI_COUNTER_SPEC *sp = obj->spec;
401 
402         sp->val        = ssp->val;
403         sp->sstep      = ssp->sstep;
404         sp->lstep      = ssp->lstep;
405         sp->min        = ssp->min;
406         sp->max        = ssp->max;
407         sp->prec       = ssp->prec;
408     }
409     else if ( obj->objclass == FL_SPINNER )
410     {
411         FLI_SPINNER_SPEC *sp = obj->spec;
412 
413         fl_set_spinner_value( obj, ssp->val );
414         fl_set_spinner_bounds( obj, ssp->min, ssp->max );
415         fl_set_spinner_step( obj, ssp->step );
416         fl_set_spinner_precision( obj, ssp->prec );
417         sp->orient = ssp->orient;
418     }
419     else if ( obj->objclass == FL_DIAL )
420     {
421         FLI_DIAL_SPEC *sp = obj->spec;
422 
423         sp->min       = ssp->min;
424         sp->max       = ssp->max;
425         sp->val       = ssp->val;
426         sp->step      = ssp->step;
427         sp->thetai    = ssp->thetai;
428         sp->thetaf    = ssp->thetaf;
429         sp->direction = ssp->direction;
430     }
431     else if ( obj->objclass == FL_XYPLOT )
432     {
433         FLI_XYPLOT_SPEC *sp = obj->spec;
434 
435         sp->xmajor         = ssp->xmajor;
436         sp->xminor         = ssp->xminor;
437         sp->ymajor         = ssp->ymajor;
438         sp->yminor         = ssp->yminor;
439         sp->xscale         = ssp->xscale;
440         sp->yscale         = ssp->yscale;
441         sp->xgrid          = ssp->xgrid;
442         sp->ygrid          = ssp->ygrid;
443         sp->xbase          = ssp->xbase;
444         sp->ybase          = ssp->ybase;
445         sp->grid_linestyle = ssp->grid_linestyle;
446         sp->mark_active    = ssp->mark_active;
447     }
448     else if ( obj->objclass == FL_SCROLLBAR )
449     {
450         FLI_SCROLLBAR_SPEC *scbsp = obj->spec;
451         FLI_SLIDER_SPEC *sp = scbsp->slider->spec;
452 
453         sp->val    = ssp->val;
454         sp->min    = ssp->min;
455         sp->max    = ssp->max;
456         sp->prec   = ssp->prec;
457         sp->step   = ssp->step;
458         sp->slsize = ssp->slsize;
459         sp->ldelta = ssp->ldelta;
460         sp->rdelta = ssp->rdelta;
461     }
462     else if ( obj->objclass == FL_SLIDER )
463     {
464         FLI_SPINNER_SPEC *sp = obj->spec;
465 
466         ssp->val = fl_get_spinner_value( obj );
467         fl_get_spinner_bounds( obj, &ssp->min, &ssp->max );
468         ssp->step = fl_get_spinner_step( obj );
469         ssp->prec = fl_get_spinner_precision( obj );
470         ssp->orient = sp->orient;
471     }
472     else if ( obj->objclass == FL_INPUT )
473     {
474         /* Simply reset some attributes of the object to the defaults -
475            this makes only sense when, during testing, text was entered
476            into the input field and new we need to get rid of it */
477 
478         FLI_INPUT_SPEC *sp = obj->spec;
479 
480         sp->position = -1;
481         sp->endrange = -1;
482         sp->lines    = sp->ypos = 1;
483         *sp->str     = '\0';
484     }
485 
486     return v;
487 }
488 
489 
490 /***************************************
491  ***************************************/
492 
493 void
copy_superspec(FL_OBJECT * target,FL_OBJECT * src)494 copy_superspec( FL_OBJECT * target,
495                 FL_OBJECT * src )
496 {
497     SuperSPEC *t = fl_malloc( sizeof *t ),
498               *s = get_superspec( src );
499     int i;
500 
501     t->mode      = NULL;
502     t->content   = NULL;;
503     t->shortcut  = NULL;
504     t->callback  = NULL;
505     t->misc_char = NULL;
506 
507     *t = *s;
508 
509     t->content = NULL;
510     t->shortcut = NULL;
511     t->callback = NULL;
512     t->mode = NULL;
513     t->mval = NULL;
514 
515     /* Take care of pointers in the SuperSPEC */
516 
517     if ( s->nlines )
518     {
519         int cnt = s->nlines + 1;
520 
521         t->content = s->content ?
522                      fl_malloc( cnt * sizeof * t->content) : NULL;
523 
524         t->shortcut = s->shortcut ?
525                       fl_malloc( cnt * sizeof *t->shortcut ) : NULL;
526 
527         t->callback = s->callback ?
528                       fl_malloc( cnt * sizeof *t->callback ) : NULL;
529 
530         t->mode = s->mode ? fl_malloc( cnt * sizeof *t->mode ) : NULL;
531 
532         t->mval = s->mval ?
533                   fl_malloc( cnt * sizeof *t->mval ) : NULL;
534     }
535 
536     for ( i = 1; i <= s->nlines; i++ )
537     {
538         if ( t->content )
539             t->content[ i ] = s->content[ i ] ?
540                               fl_strdup( s->content[ i ] ) : NULL;
541 
542         if ( t->shortcut )
543             t->shortcut[ i ] = s->shortcut[ i ] ?
544                                fl_strdup( s->shortcut[ i ] ) : NULL;
545 
546         if ( t->callback )
547             t->callback[ i ] = s->callback[ i ] ?
548                                fl_strdup( s->callback[ i ] ) : NULL;
549     }
550 
551     if ( t->mode )
552         memcpy( t->mode, s->mode, ( s->nlines + 1 ) * sizeof *t->mode );
553 
554     if ( t->mval )
555         memcpy( t->mval, s->mval, ( s->nlines + 1 ) * sizeof *t->mval );
556 
557     if ( t->misc_char )
558         t->misc_char = fl_strdup( s->misc_char );
559 
560     free_superspec( target );
561     target->u_vdata = t;
562 }
563 
564 
565 /***************************************
566  ***************************************/
567 
568 void
free_superspec(FL_OBJECT * obj)569 free_superspec( FL_OBJECT * obj )
570 {
571     SuperSPEC *ssp = obj->u_vdata;
572     int i;
573 
574     if ( ! ssp )
575         return;
576 
577     for ( i = 1; i <= ssp->nlines; ++i )
578     {
579         if ( ssp->content )
580             fl_free( ssp->content[ i ] );
581         if ( ssp->shortcut )
582             fl_free( ssp->shortcut[ i ] );
583         if ( ssp->callback )
584             fl_free( ssp->callback[ i ] );
585     }
586 
587     fl_free( ssp->misc_char );
588     fl_free( ssp->mode );
589     fl_free( ssp->mval );
590     fl_free( ssp->content );
591     fl_free( ssp->shortcut );
592     fl_free( ssp->callback );
593 }
594 
595 
596 /*
597  * Local variables:
598  * tab-width: 4
599  * indent-tabs-mode: nil
600  * End:
601  */
602