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_main.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  * This is the main module of the Form Designer, a program that
27  * helps you to design form in a fully interactive way. It
28  * automatically generates the corresponding C-code.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include "fd_main.h"
36 #include "fd/ui_theforms.h"
37 #include "xpm/fd_logo.xpm"
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #if defined( __EMX__ ) || defined( WIN32 )
44 #define strcasecmp stricmp
45 #endif
46 
47 #if defined __VMS && __VMS_VER < 70000000
48 extern int strcasecmp( const char *, const char * );
49 #endif
50 
51 
52 /***************************************
53  * Info about the program
54  ***************************************/
55 
56 #define S( a )  #a
57 #define LIBVERSION( a, b ) S( a ) "." S( b )
58 
59 static const char *fd_version[ ] =
60 {
61     "fdesign (FORM Designer) " LIBVERSION( FL_VERSION, FL_REVISION ) "." FL_FIXLEVEL,
62     "Copyright (c) 1996-2002 by T.C. Zhao and Mark Overmars",
63     "GNU Lesser General Public License sinc 2002",
64     NULL
65 };
66 
67 
68 /***************************************
69  ***************************************/
70 
71 static void
print_version(int die)72 print_version( int die )
73 {
74     const char **p = fd_version;
75 
76     for ( ; *p; p++ )
77         fprintf( stderr, "%s\n", *p );
78 
79     if ( die )
80         exit( 0 );
81 }
82 
83 
84 char xform_header[ 128 ] = "forms.h";
85 char glcanvas_header[ 128 ] = "glcanvas.h";
86 long main_window = 0;       /* The main screen window */
87 FL_Coord winw,
88          winh;
89 
90 
91 /* Various options  of the program */
92 
93 FD_Opt fdopt;
94 Conv convertor[ MAX_CONVERTOR + 1 ];
95 
96 int fd_cntlborder;
97 int fd_bwidth;
98 int is_pasting;
99 int fd_trackgeometry = 1;
100 int fd_show_palette;
101 int fd_buttonLabelSize;
102 int fd_helpfontsize = 14;
103 int fd_align_fontsize = FL_TINY_SIZE;
104 int fd_type_fontsize = FL_TINY_SIZE;
105 int no_selection = 0;
106 
107 GC fd_gc;
108 Colormap fd_colormap;
109 unsigned long fd_red,
110               fd_black,
111               fd_white,
112               fd_col;
113 Display * fd_display;
114 int changed = FL_FALSE;             /* whether something has changed. */
115 char main_name[ MAX_VAR_LEN ];      /* name of the main calling routine */
116 char * loadedfile;
117 
118 
119 /***************************************
120  * Lets the user add some object to the form
121  ***************************************/
122 
123 static void
add_something(void)124 add_something( void )
125 {
126     FL_OBJECT *obj;
127     double xx,
128            yy,
129            ww = 0.0,
130            hh = 0.0;
131 
132     if ( ! cur_form )
133         return;
134 
135     fl_winset( main_window );
136     get_mouse_pos( &xx, &yy );
137     scale_box( &xx, &yy, &ww, &hh );
138 
139     if ( ww < 5.0 || hh < 5.0 )
140         return;
141 
142     obj = add_an_object( cur_class, -1, xx, yy, ww, hh );
143     clear_selection( );
144     addto_selection( obj );
145     changed = FL_TRUE;
146 
147     /* Reset the object type selection */
148 
149     fl_deselect_browser( fd_control->objectbrowser );
150     reset_pallette( );
151     cur_class = -1;
152 }
153 
154 
155 /***************************************
156  * Changes the main calling name.
157  ***************************************/
158 
159 void
mainname_cb(FL_OBJECT * obj FL_UNUSED_ARG,long arg FL_UNUSED_ARG)160 mainname_cb( FL_OBJECT * obj  FL_UNUSED_ARG,
161              long        arg  FL_UNUSED_ARG )
162 {
163     const char *s;
164 
165     if ( ! ( s = fl_show_input( "Main creation routine name:", main_name ) ) )
166         return;
167 
168     if ( *s )
169         strcpy( main_name, s );
170     else
171         strcpy( main_name, "create_the_forms" );
172 
173     changed = FL_TRUE;
174 }
175 
176 
177 /***************************************
178  ***************************************/
179 
180 static int
double_click(const XEvent * xev)181 double_click( const XEvent * xev )
182 {
183     static Time lasttime;
184     static unsigned int lastbut;
185     static int lastx,
186                lasty;
187     int dblclk,
188         x = xev->xbutton.x,
189         y = xev->xbutton.y;
190 
191     dblclk =    xev->xbutton.button == lastbut
192              && xev->xbutton.time - lasttime < FL_CLICK_TIMEOUT
193              && lastx == x
194              && lasty == y;
195 
196     lasttime = xev->xbutton.time;
197     lastbut = xev->xbutton.button;
198     lastx = x;
199     lasty = y;
200 
201     return dblclk;
202 }
203 
204 
205 /***************************************
206  * Handle mouse click inside the working window
207  ***************************************/
208 
209 static int
handle_click(XEvent * xev,void * p FL_UNUSED_ARG)210 handle_click( XEvent * xev,
211               void   * p  FL_UNUSED_ARG  )
212 {
213     int dblclk = double_click( xev );
214 
215     /* If no form exists yet ask the user to create it */
216 
217     if ( ! cur_form )
218     {
219         addform_cb( NULL, 0 );
220         return 0;
221     }
222 
223     if ( no_selection )
224         return 0;
225 
226     if ( dblclk )
227     {
228         if ( xev->xbutton.button == 3 )
229             cut_selection( );
230         else if ( xev->xbutton.button == 1 && cur_class < 0 )
231             change_selection( );
232 
233         redraw_the_form( 0 );
234         return 0;
235     }
236 
237     if ( xev->xbutton.button == 1 && cur_class >= 0 )
238     {
239         XEvent ev;
240 
241         XNextEvent( fl_display, &ev );
242 
243         if ( ev.type == MotionNotify )
244             add_something( );
245     }
246     else if ( xev->xbutton.button == 3 && cur_class >= 0 )
247     {
248         cur_class = -1;
249         fl_deselect_browser( fd_control->objectbrowser );
250         select_pallette_entry( cur_class );
251     }
252     else if ( is_pasting )
253         /* empty */;
254     else if (    within_selection( xev->xbutton.x, xev->xbutton.y )
255               && xev->xbutton.button != 3 )
256     {
257         XEvent ev;
258 
259         XNextEvent( fl_display, &ev );
260         if ( ev.type == MotionNotify )
261             handle_move( xev );
262         else if ( ev.type == ButtonRelease )
263             handle_select( &ev );
264     }
265     else
266         handle_select( xev );
267 
268     redraw_the_form( 0 );
269     return 0;
270 }
271 
272 
273 /***************************************
274  ***************************************/
275 
276 static void
handle_keypress(const XKeyEvent * xev)277 handle_keypress( const XKeyEvent * xev )
278 {
279     KeySym keysym;
280     char keybuf[ 128 ];
281     int stp = get_snap_size( );
282     int shift = ShiftIsDown( xev->state );
283 
284     XLookupString( ( XKeyEvent * ) xev, keybuf, sizeof keybuf, &keysym, 0 );
285 
286     if ( keysym >= XK_F1 && keysym <= XK_F12 )
287         func_cb( 0, keysym - XK_F1 + 1 );
288     else if ( IsRight( keysym ) )
289         ( shift ? resize_selection : move_selection )( stp, 0 );
290     else if ( IsLeft( keysym ) )
291         ( shift ? resize_selection : move_selection )( -stp, 0 );
292     else if ( IsUp( keysym ) )
293         ( shift ? resize_selection : move_selection )( 0, -stp );
294     else if ( IsDown( keysym ) )
295         ( shift ? resize_selection : move_selection )( 0, stp );
296     else if ( keysym == XK_Escape )
297         exit_cb( 0, 0 );
298     else if ( keysym == XK_t || keysym == XK_T )
299         ( fd_test->test->visible ? stoptest_cb : test_cb )( 0, 0 );
300     else if ( keysym == XK_s || keysym == XK_S )
301         saveforms_as_cb( 0, 0 );
302     else if ( IsTab( keysym ) )
303         ( shift ? prev_selection : next_selection )( );
304     else if ( keysym >= '0' && keysym <= '9' )
305     {
306         if ( ( stp = keysym - '0' ) == 0 )
307             stp = 10;
308         set_snap_size( stp, 1 );
309     }
310 }
311 
312 
313 /***************************************
314  * Process events on the main window. Since rubber band was implemented
315  * badly, can't use buttonpress callback
316  ***************************************/
317 
318 static void
process_xevent(void)319 process_xevent( void )
320 {
321     XEvent xev;
322 
323     fl_XNextEvent( &xev );
324     fli_xevent_name( "fd_main", &xev );
325     fl_winset( main_window );
326 
327     switch ( xev.type )
328     {
329         case KeyPress:
330             handle_keypress( ( XKeyEvent * ) & xev );
331             break;
332     }
333 }
334 
335 
336 /***************************************
337  * The main event handling loop.
338  ***************************************/
339 
340 static void
main_loop(void)341 main_loop( void )
342 {
343     FL_OBJECT *obj;
344     char str[ 3 * MAX_VAR_LEN + 20 ],
345          name[ MAX_VAR_LEN ];
346     char cbname[ MAX_VAR_LEN ],
347          argname[ MAX_VAR_LEN ];
348 
349     while ( 1 )
350     {
351         obj = fl_do_forms( );
352 
353         /* Check whether we're just testing a form */
354 
355         if ( thetestform != NULL && obj != FL_EVENT )
356         {
357             get_object_name( obj, name, cbname, argname );
358             if ( ! *name )
359                 strcpy( name, "<noname>" );
360             if ( ! *cbname )
361                 sprintf( str, "Called: %s( %s, %s );", cbname, name, argname );
362             else
363                 sprintf( str, "Returned: %s", name );
364             fl_addto_browser( fd_test->browser, str );
365         }
366 
367         if ( obj == FL_EVENT )
368             process_xevent( );
369     }
370 }
371 
372 
373 #define DEFGeom       "320x250+150+420" /* working area geometry     */
374 #define DEFcntlGeom   "+150+1"          /* control panel position    */
375 #define DEFattribGeom "+210+25"         /* Attributes panel position */
376 #define DEFtestGeom   "-275+2"          /* Test panel position       */
377 #define DEFalignGeom  "-1+1"            /* align panel position       */
378 #define DEFhelpGeom   "-1+1"            /* Help panel position       */
379 
380 static FL_CMD_OPT fd_cmdopt[ ] =
381 {
382     { "-geometry",   "*geometry",       XrmoptionSepArg, NULL     },
383     { "-border",     ".XForm.Border",   XrmoptionNoArg, "1"       },
384     { "-convert",    ".convert",        XrmoptionNoArg, "1"       },
385     { "-dir",        ".dir",            XrmoptionSepArg, NULL     },
386     { "-unit",       "*unit",           XrmoptionSepArg, NULL     },
387     { "-altformat",  "*altformat",      XrmoptionNoArg, "1"       },
388     { "-I",          "*xformHeader",    XrmoptionSepArg, NULL     },
389     { "-G",          "*glcanvasHeader", XrmoptionSepArg, NULL     },
390     { "-main",       "*main",           XrmoptionNoArg, "1"       },
391     { "-callback",   "*callback",       XrmoptionNoArg, "1"       },
392     { "-lax",        "*lax",            XrmoptionNoArg, "1"       },
393     { "-nocode",     "*nocode",         XrmoptionNoArg, "0"       },
394     { "-version",    ".fdversion",      XrmoptionNoArg, "1"       },
395     { "-compensate", ".compensate",     XrmoptionNoArg, "1"       },
396     { "-ada",        ".language",       XrmoptionNoArg, "ada95"   },
397     { "-ada95",      ".language",       XrmoptionNoArg, "ada95"   },
398     { "-perl",       ".language",       XrmoptionNoArg, "perl"    },
399     { "-python",     ".language",       XrmoptionNoArg, "python"  },
400     { "-fortran",    ".language",       XrmoptionNoArg, "fortran" },
401     { "-pascal",     ".language",       XrmoptionNoArg, "pascal"  },
402     { "-scm",        ".language",       XrmoptionNoArg, "scm"     },
403     { "-ps",         ".language",       XrmoptionNoArg, "ps"      },
404     { "-filter",     ".filter",         XrmoptionSepArg, NULL     },
405     { "-migrate",    ".migrate",        XrmoptionNoArg, "1"       },
406     { "-help",       ".help",           XrmoptionNoArg, "1"       }
407 };
408 
409 #define Ncopt ( sizeof fd_cmdopt / sizeof *fd_cmdopt )
410 
411 /* resources */
412 
413 #define NG     64
414 static char fdgeom[ NG ] = DEFGeom;
415 static char fdcntlgeom[ NG ] = DEFcntlGeom;
416 static char fdattribgeom[ NG ] = DEFattribGeom;
417 static char fdtestgeom[ NG ] = DEFtestGeom;
418 static char fdaligngeom[ NG ] = DEFalignGeom;
419 static char fdhelpgeom[ NG ] = DEFhelpGeom;
420 static char fd_attrib_col[ NG ];
421 static char fd_sunit[ 32 ];
422 static char fd_slanguage[ 32 ];
423 static char fd_sfilter[ 32 ];
424 
425 static FL_resource fdres[ ] =
426 {
427     { "formDesign.geometry", "Geometry", FL_STRING, fdgeom, 0, NG },
428     { "workingArea.geometry", "Geometry", FL_STRING, fdgeom, 0, NG },
429     { "control.geometry", "Control.Geometry", FL_STRING, fdcntlgeom, 0, NG },
430     { "attributes.geometry", "Attributes.Geometry", FL_STRING, fdattribgeom,
431       0, NG },
432     { "attributes.background", "Attributes.Background", FL_STRING,
433       fd_attrib_col, 0, NG },
434     { "test.geometry", "Test.Geometry", FL_STRING, fdtestgeom, 0, NG },
435     { "help.geometry", "Help.Geometry", FL_STRING, fdhelpgeom, 0, NG },
436     { "align.geometry", "Align.Geometry", FL_STRING, fdaligngeom, 0, NG },
437     { "control.border", "XForm.Border", FL_BOOL, &fd_cntlborder, "0", 0 },
438     { "convert", "Convert", FL_BOOL, &fdopt.conv_only, "0", 0 },
439     { "migrate", "Migrate", FL_BOOL, &fdopt.conv_only, "0", 0 },
440     { "compensate", "Compensate", FL_BOOL, &fdopt.compensate, "0", 0 },
441     { "unit", "Unit", FL_STRING, fd_sunit, "pixel", 30 },
442     { "language", "Language", FL_STRING, fd_slanguage, "C", 30 },
443     { "filter", "Filter", FL_STRING, fd_sfilter, 0, 30 },
444     { "xformHeader", "XFormHeader", FL_STRING, xform_header, "forms.h", 128 },
445     { "glcanvasHeader", "GLCanvasHeader", FL_STRING, glcanvas_header,
446       "glcanvas.h", 128 },
447     { "altformat", "AltFormat", FL_BOOL, &fdopt.altformat, "0", 0 },
448     { "helpFontSize", "HelpFontSize", FL_INT, &fd_helpfontsize, "12", 0 },
449     { "nocode", "NoCode", FL_BOOL, &fdopt.emit_code, "1", 0 },
450     { "main", "Main", FL_BOOL, &fdopt.emit_main, "0", 0 },
451     { "callback", "Callback", FL_BOOL, &fdopt.emit_cb, "0", 0 },
452     { "lax", "Lax", FL_BOOL, &fdopt.lax, "0", 0 },
453 };
454 
455 #define Nropt  ( sizeof fdres / sizeof *fdres )
456 
457 char *helps[ ] =
458 {
459     "-help                     this message",
460     "-display host:dpy         display name",
461     "-name appname             change app name",
462     "-border                   add border to control panel",
463     "-unit {mm|point|pixel|cp|cmm} unit of measure. Default pixel",
464     "-nocode                   supress code generation",
465     "-main                     emit main program template",
466     "-callback                 emit callback stubs",
467     "-altformat                select alternative output format",
468     "-compensate               emit font/server compensation code",
469     "-lax                      go easy on syntax checking",
470     "-I headername             alternate header file (forms.h default)",
471     "-G glcanvas headername    alternate glcanvas header file (glcanvas.h default)",
472     "-convert file-list        convert .fd to code non-interactively",
473     "-migrate file-list        convert & migrate .fd list non-interactively",
474     "-dir destdir              output any generated files in destdir",
475     "-geometry geom            initial working area geometry",
476     0,
477 };
478 
479 
480 /***************************************
481  ***************************************/
482 
483 static void
usage(char * s,int die)484 usage( char * s,
485        int    die )
486 {
487     char **q = helps;
488     Conv *cv = convertor;
489 
490     fprintf( stderr, "usage: %s: [options] [file.fd]\n", s );
491     fprintf( stderr, "  where options are\n" );
492     for ( ; *q; q++ )
493         fprintf( stderr, "   %s\n", *q );
494 
495     fprintf( stderr, "  Language Options\n   " );
496     for ( cv += 2; cv->lang_name; cv++ )
497         fprintf( stderr, "-%s ", cv->lang_name );
498 
499     fprintf( stderr, "\n   -filter f       filter name" );
500     fprintf( stderr, "\n\n See also the online Help for resources info\n" );
501 
502     if ( die )
503         exit( 1 );
504 }
505 
506 
507 /***************************************
508  ***************************************/
509 
510 static int
lang_val(const char * s)511 lang_val( const char *s )
512 {
513     int i;
514 
515     for ( i = 1; i < MAX_CONVERTOR; i++ )
516         if (    strcasecmp( s, convertor[ i ].lang_name ) == 0
517              || strncmp( s, convertor[ i ].lang_name, 3 ) == 0 )
518             return i;
519 
520     return FD_C;
521 }
522 
523 
524 static int ignored_fake_configure;
525 
526 /***************************************
527  ***************************************/
528 
529 static int
handle_configure(XEvent * xev,void * p FL_UNUSED_ARG)530 handle_configure( XEvent * xev,
531                   void   * p  FL_UNUSED_ARG )
532 {
533     /* Some window managers sends bogus configure events. Make a note of it */
534 
535     if ( xev->xconfigure.send_event )
536         ignored_fake_configure =    winw != xev->xconfigure.width
537                                  && winh != xev->xconfigure.height;
538     else
539     {
540         winw = xev->xconfigure.width;
541         winh = xev->xconfigure.height;
542 
543         if ( cur_form && ( cur_form->w > winw || cur_form->h > winh ) )
544         {
545             reshape_form_background( winw, winh );
546             redraw_the_form( 1 );
547         }
548 
549         if ( fd_resize->resize->visible )
550         {
551             fl_set_spinner_value( fd_resize->width,  winw );
552             fl_set_spinner_value( fd_resize->height, winh );
553         }
554 
555         changed = FL_TRUE;
556     }
557 
558     return 1;
559 }
560 
561 
562 /***************************************
563  ***************************************/
564 
565 static int
handle_expose(XEvent * xev,void * p FL_UNUSED_ARG)566 handle_expose( XEvent * xev,
567                void   * p  FL_UNUSED_ARG )
568 {
569     if ( xev->xexpose.count == 0 )
570     {
571         M_warn( "FD_Expose", "" );
572 
573         /* If we have ignored a previous configure event, need the window
574            size might not be correct. Re-read */
575 
576         if ( ignored_fake_configure )
577             fl_get_winsize( main_window, &winw, &winh );
578 
579         /* Change form background size */
580 
581         if ( cur_form && ( cur_form->w != winw || cur_form->h != winh ) )
582             reshape_form_background( winw, winh );
583 
584         redraw_the_form( 1 );
585         ignored_fake_configure = 0;
586         return 1;
587     }
588 
589     return 0;
590 }
591 
592 
593 /***************************************
594  * Need the ability to convert/help without requiring an X connection.
595  ***************************************/
596 
597 static void
pre_connect(int argc,char * argv[])598 pre_connect( int    argc,
599              char * argv[ ] )
600 {
601     int i,
602         s;
603     static char filter[ 128 ];
604 
605     for ( i = 1; i < argc && *argv[ i ] == '-'; i++ )
606     {
607         if ( strncmp( argv[ i ] + 1, "help", 1 ) == 0 )
608             usage( argv[ 0 ], 1 );
609         else if ( strncmp( argv[ i ] + 1, "version", 4 ) == 0 )
610             print_version( 1 );
611         else if ( strncmp( argv[ i ] + 1, "altformat", 3 ) == 0 )
612             fdopt.altformat = 1;
613         else if ( strncmp( argv[ i ] + 1, "callback", 3 ) == 0 )
614             fdopt.emit_cb = 1;
615         else if ( strncmp( argv[ i ] + 1, "compensate", 4 ) == 0 )
616             fdopt.compensate = 1;
617         else if ( strncmp( argv[ i ] + 1, "main", 3 ) == 0 )
618             fdopt.emit_main = 1;
619         else if ( strncmp( argv[ i ] + 1, "noc", 3 ) == 0 )
620             fdopt.emit_code = 0;
621         else if ( strncmp( argv[ i ] + 1, "unit", 4 ) == 0 && i + 1 < argc )
622             fdopt.unit = unit_val( argv[ ++i ] );
623         else if ( strncmp( argv[ i ] + 1, "filter", 4 ) == 0 && i + 1 < argc )
624             strcpy( filter, argv[ ++i ] );
625         else if ( strncmp( argv[ i ], "-I", 2 ) == 0 )
626         {
627             if ( argv[ i ][ 2 ] != '\0' )
628                 strcpy( xform_header, argv[ i ] + 2 );
629             else if ( i + 1 < argc )
630                 strcpy( xform_header, argv[ ++i ] );
631         }
632         else if ( strcmp( argv[ i ], "-G" ) == 0 && i + 1 < argc )
633             strcpy( glcanvas_header, argv[ ++i ] );
634         else if ( strcmp( argv[ i ], "-bw" ) == 0 && i + 1 < argc )
635             fd_bwidth = atoi( argv[ ++i ] );
636         else if ( strncmp( argv[ i ] + 1, "convert", 1 ) == 0 )
637         {
638             fli_no_connection = 1;
639             fli_internal_init( );
640             fdopt.conv_only = 1;
641         }
642         else if ( strncmp( argv[ i ] + 1, "migrate", 1 ) == 0 )
643         {
644             fli_no_connection = 1;
645             fli_internal_init( );
646             fdopt.conv_only = 2;
647         }
648         else if ( strncmp( argv[ i ] + 1, "dir", 3 ) == 0 && i + 1 < argc )
649         {
650             fdopt.output_dir = malloc( strlen( argv[ ++i ] ) + 1 );
651             strcpy( fdopt.output_dir, argv[ i ] );
652         }
653         else if ( strncmp( argv[ i ] + 1, "lang", 4 ) == 0 && i + 1 < argc )
654             fdopt.language = lang_val( argv[ ++i ] );
655         else
656             fdopt.language = lang_val( argv[ i ] + 1 );
657     }
658 
659     if ( fdopt.language < FD_C || fdopt.language > FD_EXP )
660         fdopt.language = FD_C;
661 
662     if ( filter[ 0 ] )
663         convertor[ fdopt.language ].extern_convertor = filter;
664 
665     if ( convertor[ fdopt.language ].init )
666         convertor[ fdopt.language ].init( );
667 
668     /* No need to check for C syntax if not C program */
669 
670     if ( fdopt.language != FD_C )
671         fdopt.lax = 1;
672 
673     if ( ! fdopt.conv_only )
674         return;
675 
676     fli_set_app_name( argv[ 0 ], "Fdesign" );   /* resource routine needs it */
677     fli_init_context( );
678     create_the_forms( );
679     init_classes( );
680 
681     fl_dpi = 96;
682 
683     if ( i > argc - 1 )
684     {
685         if ( fdopt.conv_only == 1 )
686             fprintf( stderr, "'-convert' requires argument(s)\n" );
687         else
688             fprintf( stderr, "'-migrate' requires argument(s)\n" );
689 
690         usage( argv[ 0 ], 1 );
691     }
692 
693     for ( s = i; s < argc; s++ )
694     {
695         reset_object_list( );
696 
697         if ( load_forms( FL_FALSE, argv[ s ] ) < 0 )
698         {
699             fprintf( stderr, "Unable to load '%s'\n", argv[ s ] );
700             exit( 1 );
701         }
702 
703         if ( ! save_forms( argv[ s ] ) )
704         {
705             fprintf( stderr, "Unable to convert '%s'\n", argv[ s ] );
706             exit( 1 );
707         }
708     }
709 
710     exit( 0 );
711 }
712 
713 
714 /***************************************
715  ***************************************/
716 
717 static int
parse_geometry(const char * gstr,int * x,int * y,unsigned int * w,unsigned int * h)718 parse_geometry( const char   * gstr,
719                 int          * x,
720                 int          * y,
721                 unsigned int * w,
722                 unsigned int * h )
723 {
724     int s;
725 
726     s = XParseGeometry( ( char * ) gstr, x, y, w, h );
727     if ( s & XValue && s & XNegative )
728         *x = fl_scrw - FL_abs( *x );
729     if ( s & YValue && s & YNegative )
730         *y = fl_scrh - FL_abs( *y );
731     return s;
732 }
733 
734 #include <signal.h>
735 
736 /***************************************
737  ***************************************/
738 
739 static void
interrupted(int s FL_UNUSED_ARG,void * data FL_UNUSED_ARG)740 interrupted( int    s     FL_UNUSED_ARG,
741              void * data  FL_UNUSED_ARG )
742 {
743     exit_cb( 0, 0 );
744 }
745 
746 
747 /***************************************
748  * Default action for delete window client message
749  ***************************************/
750 
751 static int
delete_handler(FL_FORM * form FL_UNUSED_ARG,void * data FL_UNUSED_ARG)752 delete_handler( FL_FORM * form  FL_UNUSED_ARG,
753                 void    * data  FL_UNUSED_ARG )
754 {
755     if (    changed
756          && fl_show_question( "Changes have not been saved\n"
757                               "Save them now ?", 1 )
758          && ! save_forms( NULL ) )
759         return FL_IGNORE;
760 
761     exit( 0 );
762     return 0;           /* shut up compiler */
763 }
764 
765 
766 /***************************************
767  * Always output perl code in altformat
768  ***************************************/
769 
770 static void
perl_init(void)771 perl_init( void )
772 {
773     fdopt.altformat = 1;
774 }
775 
776 
777 /***************************************
778  ***************************************/
779 
780 static void
initialize(void)781 initialize( void )
782 {
783     fdopt.conv_only = 0;
784     fdopt.language = FD_C;
785     fdopt.emit_code = 1;
786 
787     convertor[ FD_EXP ].lang_name = "exp";
788     convertor[ MAX_CONVERTOR ].lang_name = NULL;
789 
790     convertor[ FD_C ].lang_name = "C";
791     convertor[ FD_C ].convert = C_output;
792 
793     convertor[ FD_ADA95 ].lang_name = "ada";
794     convertor[ FD_ADA95 ].extern_convertor = "flc2ada";
795     convertor[ FD_ADA95 ].need_c_code = 1;
796 
797     convertor[ FD_PASCAL ].lang_name = "pascal";
798     convertor[ FD_PASCAL ].extern_convertor = "fd2pascal";
799 
800     convertor[ FD_PS ].lang_name = "ps";
801     convertor[ FD_PS ].extern_convertor = "fd2ps";
802 
803     convertor[ FD_PERL ].lang_name = "perl";
804     convertor[ FD_PERL ].need_c_code = 1;
805     convertor[ FD_PERL ].extern_convertor = "fd2perl";
806     convertor[ FD_PERL ].init = perl_init;
807 
808     convertor[ FD_PYTHON ].lang_name = "python";
809     convertor[ FD_PYTHON ].extern_convertor = "fd2python";
810 
811     convertor[ FD_FORTRAN ].lang_name = "fortran";
812     convertor[ FD_FORTRAN ].extern_convertor = "fd2fortran";
813 
814     convertor[ FD_SCM ].lang_name = "scm";
815     convertor[ FD_SCM ].extern_convertor = "fd2scm";
816 }
817 
818 
819 /***************************************
820  ***************************************/
821 
822 static int
ignore_close(FL_FORM * a FL_UNUSED_ARG,void * b FL_UNUSED_ARG)823 ignore_close( FL_FORM *a  FL_UNUSED_ARG,
824               void    *b  FL_UNUSED_ARG )
825 {
826     return FL_IGNORE;
827 }
828 
829 
830 /***************************************
831  ***************************************/
832 
833 int
main(int argc,char * argv[])834 main( int    argc,
835       char * argv[ ] )
836 {
837     unsigned int w = 0,
838                  h = 0;
839     int x = 0,
840         y = 0,
841         s,
842         version,
843         revision;
844     FL_IOPT cntl;
845     unsigned int mask;
846     char *tmp = NULL;
847 
848     /* Before doing anything, check to make sure the library is made
849        correctly */
850 
851     if ( FL_INCLUDE_VERSION != fl_library_version( &version, &revision ) )
852     {
853         fprintf( stderr, "Library and header mismatch\n" );
854         fprintf( stderr, "  Header Version:%d.%d.%s\n",
855                  FL_VERSION, FL_REVISION, FL_FIXLEVEL );
856         fprintf( stderr, " Library version:%d.%d\n", version, revision );
857     }
858 
859     initialize( );
860 
861     /* For conversion, version and usage help, we don't need a connection.
862        pre_connect will exit in such circumstances. */
863 
864     pre_connect( argc, argv );
865 
866     /* Force fdesign to come up in default visual */
867 
868     cntl.vclass = FL_DefaultVisual;
869     cntl.doubleBuffer = 0;
870     cntl.browserFontSize = FL_NORMAL_FONT;
871     mask = FL_PDVisual | FL_PDDouble | FL_PDBrowserFontSize;
872 
873     cntl.sharedColormap = 1;
874     mask |= FL_PDSharedMap;
875 
876     fl_set_defaults( mask, &cntl );
877 
878     if ( ! ( fd_display = fl_initialize( &argc, argv, 0, fd_cmdopt, Ncopt ) ) )
879         exit( 1 );
880 
881     fl_get_app_resources( fdres, Nropt );
882     fl_add_signal_callback( SIGINT, interrupted, 0 );
883 
884     if ( argv[ 1 ] && argv[ 1 ][ 0 ] == '-' )
885     {
886         fprintf( stderr, " Unknown option: %s\n", argv[ 1 ] );
887         usage( argv[ 0 ], 1 );
888     }
889 
890     fli_cntl.coordUnit = FL_COORD_PIXEL;
891     fdopt.unit = unit_val( fd_sunit );
892     fdopt.language = lang_val( fd_slanguage );
893 
894     if ( *fd_sfilter )
895         convertor[ fdopt.language ].extern_convertor = fd_sfilter;
896 
897     /* No need to check for C syntax if not C program */
898 
899     if ( fdopt.language != FD_C )
900         fdopt.lax = 1;
901 
902     if ( convertor[ fdopt.language ].init )
903         convertor[ fdopt.language ].init( );
904 
905     fd_bwidth = fli_cntl.borderWidth;
906     M_warn( "fdesign", "UNIT=%s BW=%d", unit_name( fdopt.unit ), fd_bwidth );
907 
908     create_the_forms( );
909     fl_set_atclose( delete_handler, 0 );
910 
911     /* Must suspend user requested button label font throughout fdesign and
912        enable it only when testing */
913 
914     fd_buttonLabelSize = fli_cntl.buttonFontSize;
915     fli_cntl.buttonFontSize = 0;
916 
917     /* Initialize stuff */
918 
919     init_classes( );
920 
921     fl_set_counter_bounds( fd_align->snapobj, 1.0, 500.0 );
922     fl_set_counter_step( fd_align->snapobj, 1.0, 5.0 );
923     fl_set_counter_value( fd_align->snapobj, 10.0 );
924     fl_set_counter_precision( fd_align->snapobj, 0 );
925     fl_set_form_atclose( fd_align->align, ignore_close, NULL );
926 
927     fl_set_spinner_bounds( fd_resize->width,  1, SHRT_MAX );
928     fl_set_spinner_bounds( fd_resize->height, 1, SHRT_MAX );
929     fl_set_form_atclose( fd_resize->resize, ignore_close, NULL );
930 
931     fl_set_form_atclose( fd_attrib->attrib, ignore_close, NULL );
932     fl_set_form_atclose( fd_attrib->attrib, ignore_close, NULL );
933     fl_set_form_atclose( fd_test->test, ignore_close, NULL );
934     fl_set_form_atclose( fd_help->helpform, ignore_close, NULL );
935 
936     thetestform = NULL;
937     strcpy( main_name, "create_the_forms" );
938 
939     /* Load files */
940 
941     /* If only one argument is given and the file does not exist, we can
942        assume that the intention is to create a new file so we don't bother
943        to try to load it */
944 
945     if (    argc >= 2
946          && access( tmp = append_fd_suffix( argv[ argc - 1 ] ), R_OK ) == 0 )
947     {
948         for ( s = 1; s < argc; s++ )
949             if ( load_forms( s == 1 ? FL_FALSE : FL_TRUE, argv[ s ] ) < 0 )
950                 break;
951     }
952     else
953     {
954         select_object_by_class( FL_BUTTON );
955         select_pallette_entry( FL_BUTTON );
956     }
957 
958     fli_safe_free( tmp );
959 
960     /* Do auto-naming for single file only */
961 
962     if ( argc == 2 )
963         loadedfile = rel2abs( argv[ 1 ] );
964 
965     /* See if color change */
966 
967     if ( fd_attrib_col[ 0 ] )
968     {
969         long c = FL_FREE_COL1 - 10;
970 
971         fl_mapcolor_name( c, fd_attrib_col );
972         modify_attrib_basic_color( c, c );
973     }
974 
975     parse_geometry( fdcntlgeom, &x, &y, &w, &h );
976     fl_set_form_position( fd_control->control, x, y );
977 
978     fl_set_app_mainform( fd_control->control );
979     fli_set_form_icon_data( fd_control->control, fd_logo_pixels );
980     fl_show_form( fd_control->control, FL_PLACE_GEOMETRY,
981                  ( 1 || fd_cntlborder ) ? FL_FULLBORDER : FL_TRANSIENT,
982                  "Control" );
983 
984     /* Other geometries */
985 
986     parse_geometry( fdattribgeom, &x, &y, &w, &h );
987     fl_set_form_position( fd_attrib->attrib, x, y );
988 
989     parse_geometry( fdtestgeom, &x, &y, &w, &h );
990     fl_set_form_position( fd_test->test, x, y );
991 
992     parse_geometry( fdaligngeom, &x, &y, &w, &h );
993     fl_set_form_position( fd_align->align, x, y );
994 
995     parse_geometry( fdhelpgeom, &x, &y, &w, &h );
996     fl_set_form_position( fd_help->helpform, x, y );
997 
998     s = parse_geometry( fdgeom, &x, &y, &w, &h );
999     if ( s & XValue || s & YValue )
1000         fl_winposition( x, y );
1001     if ( s & WidthValue && s & HeightValue )
1002         fl_initial_winsize( w, h );
1003 
1004     /* If a form is already loaded, use that size */
1005 
1006     if ( cur_form )
1007     {
1008         y -= cur_form->h - h;
1009         w = cur_form->w;
1010         h = cur_form->h;
1011         fl_initial_wingeometry( x, y, w, h );
1012     }
1013 
1014     winw = w;
1015     winh = h;
1016 
1017     fd_colormap = fl_state[ fl_vmode ].colormap;
1018     fd_white = fl_get_flcolor( FL_WHITE );
1019     fd_red   = fl_get_flcolor( FL_RED );
1020     fd_black = fl_get_flcolor( FL_BLACK );
1021     fd_col   = fl_get_flcolor( FL_COL1 );
1022 
1023     main_window = fli_cmap_winopen( fl_root, fd_colormap, "Form Design" );
1024 
1025     fl_set_fselector_transient( 1 );
1026 
1027     fl_add_event_callback( main_window, Expose, handle_expose, 0 );
1028     fl_add_event_callback( main_window, ConfigureNotify, handle_configure, 0 );
1029     fl_add_event_callback( main_window, ButtonPress, handle_click, 0 );
1030     fl_addto_selected_xevent( main_window,
1031                               ButtonMotionMask | PointerMotionHintMask );
1032     fl_addto_selected_xevent( main_window, ButtonReleaseMask );
1033 
1034     redraw_the_form( 1 );
1035 
1036     /* GC is valid only after at least one window is created */
1037 
1038     fd_gc = fl_state[ fl_vmode ].gc[ 8 ];
1039 
1040     main_loop( );
1041 
1042     return 0;
1043 }
1044 
1045 
1046 /***************************************
1047  ***************************************/
1048 
1049 void
set_snap_size(int n,int cb)1050 set_snap_size( int n,
1051                int cb )
1052 {
1053     fl_set_counter_value( fd_align->snapobj, n > 0 ? n : 5 );
1054     if ( cb )
1055         fl_call_object_callback( fd_align->snapobj );
1056 }
1057 
1058 
1059 /***************************************
1060  ***************************************/
1061 
1062 int
get_snap_size(void)1063 get_snap_size( void )
1064 {
1065     return 0.01 + fl_get_counter_value( fd_align->snapobj );
1066 }
1067 
1068 
1069 /*
1070  * Local variables:
1071  * tab-width: 4
1072  * indent-tabs-mode: nil
1073  * End:
1074  */
1075