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_forms.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 file is part of the Forms Designer.
27 *
28 * It contains the routines that maintain the collection of
29 * forms on which the program is working. It contains the callback
30 * routines to add forms, change their name, remove them ,etc.
31 * It also contains the routine to draw them and the basic routines
32 * for loading and saving forms.
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <string.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <ctype.h>
43
44 #include "fd_main.h"
45
46 static FRM *forms = NULL; /* The list of forms */
47 static int fnumb = 0; /* number of forms */
48
49 FL_FORM *cur_form = NULL; /* The current form */
50
51
52 /***************************************
53 * Returns the number of the form
54 ***************************************/
55
56 static int
get_form_numb(FL_FORM * form)57 get_form_numb( FL_FORM * form )
58 {
59 int i;
60
61 for ( i = 0; i < fnumb; i++ )
62 if ( forms[ i ].form == form )
63 return i;
64 return -1;
65 }
66
67
68 /***************************************
69 ***************************************/
70
71 const char *
get_form_name(FL_FORM * form)72 get_form_name( FL_FORM * form )
73 {
74 int i;
75
76 for ( i = 0; i < fnumb; i++ )
77 if ( forms[ i ].form == form )
78 return *forms[ i ].fname ? forms[ i ].fname : NULL;
79
80 return NULL;
81 }
82
83
84 /***************************************
85 * Sets the current form to 'numb' or to NULL when 'numb' is -1
86 ***************************************/
87
88 static void
set_form(int numb)89 set_form( int numb )
90 {
91 if ( numb == -1 )
92 {
93 cur_form = NULL;
94 fl_deselect_browser( fd_control->formbrowser );
95 }
96 else
97 {
98 cur_form = forms[ numb ].form;
99 set_bounding_box( 0, 0, cur_form->w, cur_form->h );
100 fl_select_browser_line( fd_control->formbrowser, numb + 1 );
101 fl_winstepsize( main_window, 1, 1 );
102 fl_winresize( main_window, cur_form->w, cur_form->h );
103 if ( fl_display )
104 XSync( fl_display, 0 );
105 }
106
107 fl_deselect_browser( fd_control->objectbrowser );
108 reset_pallette( );
109 cur_class = -1;
110
111 clear_selection( );
112 fillin_groups( );
113 redraw_the_form( 1 );
114 }
115
116
117 /***************************************
118 * Change the current forms background. Called when the main window is resized
119 ***************************************/
120
121 void
reshape_form_background(FL_Coord neww,FL_Coord newh)122 reshape_form_background( FL_Coord neww,
123 FL_Coord newh )
124 {
125 if ( cur_form && cur_form->first )
126 {
127 cur_form->w_hr = cur_form->w =
128 cur_form->first->next->w = cur_form->first->next->fr1 =
129 cur_form->first->next->fl2 = neww;
130 cur_form->h_hr = cur_form->h =
131 cur_form->first->next->h = cur_form->first->next->fb1 =
132 cur_form->first->next->ft2 = newh;
133
134 set_bounding_box( 0, 0, neww, newh );
135 }
136 }
137
138
139 /****
140 CALLBACK ROUTINES
141 ****/
142
143 /***************************************
144 * Callback routine that is called when the user selects another form
145 * to work on.
146 ***************************************/
147
148 void
form_cb(FL_OBJECT * obj FL_UNUSED_ARG,long arg FL_UNUSED_ARG)149 form_cb( FL_OBJECT * obj FL_UNUSED_ARG,
150 long arg FL_UNUSED_ARG )
151 {
152 set_form( fl_get_browser( fd_control->formbrowser ) - 1 );
153 }
154
155
156 /***************************************
157 * Callback routine called when the user adds a form.
158 ***************************************/
159
160 void
addform_cb(FL_OBJECT * obj FL_UNUSED_ARG,long arg FL_UNUSED_ARG)161 addform_cb( FL_OBJECT * obj FL_UNUSED_ARG,
162 long arg FL_UNUSED_ARG )
163 {
164 double w = 0,
165 h = 0;
166 FL_Coord xx,
167 yy;
168 static int form_seq;
169 const char *s;
170 const char *sp;
171 FRM *new_forms;
172 int cc = cur_class;
173 static int busy = 0;
174
175 if ( busy )
176 return;
177 else
178 busy = 1;
179
180 new_forms = fl_realloc( forms, ( fnumb + 1 ) * sizeof *forms );
181
182 if ( ! new_forms )
183 {
184 fl_show_alert( "Too many forms", "Running out of memory for forms",
185 NULL, 0 );
186 busy = 0;
187 return;
188 }
189 else
190 forms = new_forms;
191
192 /* Make old form invisible */
193
194 set_form( -1 );
195
196 /* Get boundary */
197
198 fl_get_win_size( main_window, &xx, &yy );
199 set_bounding_box( 0, 0, xx, yy );
200
201 w = xx;
202 h = yy;
203
204 get_new_form_name:
205
206 if ( ! ( s = fl_show_input( "Enter form name (must be usable as "
207 "a C variable):", "" ) )
208 || ! *s )
209 {
210 busy = 0;
211 return;
212 }
213
214 if ( ! isascii( ( unsigned char ) *s )
215 || ! ( isalpha( ( unsigned char ) *s ) || *s == '_' ) )
216 {
217 fl_show_alert( "Error", "Invalid C identifier for form name:", s, 0 );
218 goto get_new_form_name;
219 }
220
221 for ( sp = s + 1; *sp; sp++ )
222 if ( ! isascii( ( unsigned char ) *sp )
223 || ! ( isalnum( ( unsigned char ) *sp ) || *sp == '_' ) )
224 {
225 fl_show_alert( "Error", "Invalid C identifier for form name:",
226 s, 0 );
227 goto get_new_form_name;
228 }
229
230 /* Create the form */
231
232 cur_form = forms[ fnumb ].form = fl_bgn_form( FL_NO_BOX, w, h );
233 fl_end_form( );
234
235 add_an_object( FL_BOX, FL_FLAT_BOX, 0, 0, w, h );
236 fl_set_form_dblbuffer( cur_form, 1 );
237
238 /* Get form name and add it */
239
240 strcpy( forms[ fnumb ].fname, s );
241
242 if ( ! forms[ fnumb ].fname[ 0 ] )
243 sprintf( forms[ fnumb ].fname, "form%d", form_seq++ );
244 fl_add_browser_line( fd_control->formbrowser, forms[ fnumb ].fname );
245
246 /* Finish off */
247
248 set_form( fnumb++ );
249 changed = FL_TRUE;
250
251 if ( cc >= 0 )
252 select_object_by_class( cc );
253
254 busy = 0;
255 }
256
257
258 /***************************************
259 * Callback routine invoked when the user wants to change the name
260 * of the current form
261 ***************************************/
262
263 void
changename_cb(FL_OBJECT * obj FL_UNUSED_ARG,long arg FL_UNUSED_ARG)264 changename_cb( FL_OBJECT * obj FL_UNUSED_ARG,
265 long arg FL_UNUSED_ARG )
266 {
267 int fn = get_form_numb( cur_form );
268 const char *s, *cn;
269 int i;
270 FL_OBJECT *o;
271
272 if ( cur_form == NULL || fn == -1 )
273 return;
274
275 get_changed_form_name:
276
277 if ( ! ( s = fl_show_input( "Enter form name (must be usable as "
278 "a C variable):", forms[ fn ].fname ) )
279 || ! *s )
280 return;
281
282 if ( ! is_valid_c_name( s ) )
283 {
284 fl_show_alert( "Error", "Invalid C identifier for form name:", s, 0 );
285 goto get_changed_form_name;
286 }
287
288 for ( i = 0; i < fnumb; i++ )
289 {
290 if ( i == fn )
291 continue;
292
293 if ( ! strcmp( forms[ i ].fname, s ) )
294 {
295 fl_show_alert( "Error", "New name is already in use for another "
296 "form", NULL, 0 );
297 goto get_changed_form_name;
298 }
299 }
300
301 for ( o = forms[ fn ].form->first; o; o = o->next )
302 if ( ( cn = get_object_c_name( o ) ) && ! strcmp( s, cn ) )
303 {
304 fl_show_alert( "Error", "New name is already used for one of the ",
305 "forms objects", 0 );
306 goto get_changed_form_name;
307 }
308
309 fli_sstrcpy( forms[ fn ].fname, s, MAX_VAR_LEN );
310
311 fl_replace_browser_line( fd_control->formbrowser, fn + 1,
312 forms[ fn ].fname );
313 changed = FL_TRUE;
314 }
315
316
317 /***************************************
318 * Callback routine invoked when the user wants to change the forms size
319 ***************************************/
320
321 void
changesize_cb(FL_OBJECT * obj FL_UNUSED_ARG,long arg FL_UNUSED_ARG)322 changesize_cb( FL_OBJECT * obj FL_UNUSED_ARG,
323 long arg FL_UNUSED_ARG )
324 {
325 FL_OBJECT *retobj;
326 int fn = get_form_numb( cur_form );
327
328 if ( cur_form == NULL || fn == -1 )
329 return;
330
331 /* While this form is shown no other should be operational (the user
332 still can resize the forms window, that will automatically set the
333 width and height spinners) */
334
335 fl_deactivate_all_forms( );
336
337 /* Set up the width and height spinner objects to show the sizes of
338 the current form */
339
340 fl_set_spinner_value( fd_resize->width, cur_form->w );
341 fl_set_spinner_value( fd_resize->height, cur_form->h );
342
343 fl_show_form( fd_resize->resize, FL_PLACE_HOTSPOT, FL_TRANSIENT,
344 "Form size" );
345
346 fl_update_display( 0 );
347 fl_winfocus( fd_resize->resize->window );
348
349 /* Loop until user clicks the "Dismiss" button */
350
351 while ( ( retobj = fl_do_only_forms( ) ) != fd_resize->quit )
352 {
353 int w;
354 int h;
355
356 if ( retobj != fd_resize->set_size )
357 continue;
358
359 /* User has clicked on the "Set new size" button */
360
361 w = FL_nint( fl_get_spinner_value( fd_resize->width ) );
362 h = FL_nint( fl_get_spinner_value( fd_resize->height ) );
363 fl_set_spinner_value( fd_resize->width, w );
364 fl_set_spinner_value( fd_resize->height, h );
365
366 if ( w == cur_form->w && h == cur_form->h )
367 continue;
368
369 XResizeWindow( flx->display, main_window, w, h );
370
371 if ( cur_form && ( cur_form->w > w || cur_form->h > h ) )
372 {
373 reshape_form_background( w, h );
374 redraw_the_form( 1 );
375 }
376
377 changed = FL_TRUE;
378 }
379
380 fl_hide_form( fd_resize->resize );
381 fl_activate_all_forms( );
382 }
383
384
385 /***************************************
386 * Callback routine for deleting a form
387 ***************************************/
388
389 void
deleteform_cb(FL_OBJECT * obj FL_UNUSED_ARG,long arg FL_UNUSED_ARG)390 deleteform_cb( FL_OBJECT * obj FL_UNUSED_ARG,
391 long arg FL_UNUSED_ARG )
392 {
393 int i,
394 fn = get_form_numb( cur_form );
395
396 if ( cur_form == NULL || fn == -1 )
397 return;
398
399 if ( ! fl_show_question( "Delete current form?", 1 ) )
400 return;
401
402 fl_delete_browser_line( fd_control->formbrowser, fn + 1 );
403
404 for ( i = fn; i < fnumb - 1; i++ )
405 forms[ i ] = forms[ i + 1 ];
406
407 fnumb--;
408 set_form( -1 );
409 changed = FL_TRUE;
410 }
411
412
413 /****
414 DRAWING FORMS
415 ****/
416
417 /***************************************
418 * Redraws the form in main window. 'back' indicates whether the background
419 * should be redrawn (when not double-buffering). This avoids flashing.
420 ***************************************/
421
422 void
redraw_the_form(int back)423 redraw_the_form( int back )
424 {
425 if ( main_window == 0 )
426 return;
427
428 fl_winset( main_window );
429
430 /* It's possible to have a NULL cur_form, e.g. when adding */
431
432 if ( back && ! cur_form )
433 fd_clear( 0, 0, winw + 1, winh + 1 );
434
435 if ( cur_form != NULL )
436 {
437 cur_form->window = main_window;
438 cur_form->visible = 1;
439 fl_set_form_dblbuffer( cur_form, 1 );
440 fl_redraw_form( cur_form );
441 cur_form->window = 0;
442 cur_form->visible = 0;
443 draw_selbox( );
444 }
445 }
446
447
448 /****
449 LOADING AND SAVING
450 ****/
451
452 int fd_magic;
453
454 /***************************************
455 ***************************************/
456
457 char *
append_fd_suffix(const char * fn)458 append_fd_suffix( const char * fn )
459 {
460 size_t l = strlen( fn );
461 char *fname = fl_malloc( l + 4 );
462
463 strcpy( fname, fn );
464 if ( l < 3 || strcmp( fname + l - 3, ".fd" ) )
465 strcat( fname, ".fd" );
466 return fname;
467 }
468
469
470 /***************************************
471 * Reads in the very first part of a .fd file
472 ***************************************/
473
474 static int
load_fd_header(void)475 load_fd_header( void )
476 {
477 char *p;
478 int nforms = -1;
479
480 /* Line with "magic" number must come first, followed by some
481 boilerplate text */
482
483 if ( ff_read( "%k", &p ) <= 0
484 || strcmp( p, "Magic" )
485 || ff_read( "%d", &fd_magic ) <= 0
486 || ( fd_magic != MAGIC2 && fd_magic != MAGIC3
487 && fd_magic != MAGIC4 && fd_magic != MAGIC5
488 && fd_magic != MAGIC6 ) )
489 return ff_err( "Wrong type of file" );
490
491 if ( fd_magic < MAGIC6 )
492 {
493 char *tmp = ff_get_filename_copy( );
494
495 if ( ! fdopt.conv_only )
496 fl_show_alert_f( 0, "Warning:\fFile %s\nwas created with an older "
497 "fdesign version,\nthe new output file may not be "
498 "compatible.", tmp );
499 else
500 M_warn( "", "Warning: File %s was created with an older fdesign "
501 "version, the new output file may not be compatible",
502 tmp );
503
504 fli_safe_free( tmp );
505 }
506
507 if ( ff_read( "Internal Form Definition File" ) < 0
508 || ff_read( "(do not change)" ) < 0 )
509 return ff_err( "Invalid format of file" );
510
511 /* Now follows a set of keyword/value pairs. The key "Name" marks
512 the end of the header and the start of the first form definition */
513
514 while ( 1 )
515 {
516 if ( ff_read( "%k", &p ) <= 0 )
517 return ff_err( "Invalid format of file" );
518
519 if ( ! strcmp( p, "Number of forms" ) )
520 {
521 if ( ff_read( "%d", &nforms ) <= 0 )
522 return ff_err( "Expected number of forms" );
523
524 if ( nforms <= 0 )
525 return ff_err( "Invalid number of forms" );
526 }
527 else if ( ! strcmp( p, "Unit of measure" ) )
528 {
529 if ( ff_read( "%x", &fdopt.unit ) < 0 )
530 return ff_err( "Expected valid unit of measure" );
531
532 fli_cntl.coordUnit = fdopt.unit; /* make_obj uses this */
533 }
534 else if ( ! strcmp( p, "SnapGrid" ) || ! strcmp( p, "Snap" ) )
535 {
536 int snap_size;
537
538 if ( ff_read( "%d", &snap_size ) < 0 )
539 return ff_err( "Expected snap size" );
540
541 if ( snap_size < 0 )
542 return ff_err( "Invalid snap size" );
543
544 set_snap_size( snap_size, 1 );
545 }
546 else if ( ! strcmp( p, "Border Width" ) )
547 {
548 int bw;
549
550 if ( ff_read( "%d", &bw ) < 0 )
551 return ff_err( "Expected border width" );
552
553 if ( bw != FL_BOUND_WIDTH )
554 fl_set_border_width( fd_bwidth = bw );
555 }
556 else if ( ! strcmp( p, "Name" ) )
557 {
558 if ( nforms < 0 )
559 return ff_err( "Number of forms is missing" );
560
561 return nforms;
562 }
563 else
564 return ff_err( "Invalid format of file" );
565 }
566
567 return ff_err( "Invalid format of file" );
568 }
569
570
571 /***************************************
572 * Loads or merges a file with form definitions
573 ***************************************/
574
575 int
load_forms(int merge,const char * str)576 load_forms( int merge,
577 const char * str )
578 {
579 int i,
580 saved_unit = fdopt.unit,
581 r,
582 nforms;
583 FRM *new_forms;
584 char *fname;
585
586 /* Try to open the .fd file */
587
588 if ( ff_get_fd_file( str, merge ) < 0 )
589 return -1;
590
591 if ( ! merge )
592 {
593 fnumb = 0;
594 fl_clear_browser( fd_control->formbrowser );
595 }
596
597 /* Try to read the header of the file (must indicate that there's at
598 least one form */
599
600 if ( ( nforms = load_fd_header( ) ) <= 0 )
601 return -1;
602
603 if ( ! ( new_forms = fl_realloc( forms,
604 ( fnumb + nforms ) * sizeof *forms ) ) )
605 return ff_err( "Can't load file, running out of memory" );
606
607 forms = new_forms;
608
609 fname = ff_get_filename_copy( );
610
611 /* Now read in all forms - we have already read in the "Name:" key that
612 starts a new form */
613
614 r = FF_AT_START_OF_FORM;
615
616 for ( i = 0; i < nforms && r == FF_AT_START_OF_FORM; i++ )
617 {
618 char *p;
619
620 /* First thing to read is the name of the form (which must not be an
621 empty string) */
622
623 if ( ff_read( "%v", &p ) < 1 )
624 {
625 fl_free( fname );
626 return ff_err( "Failed to read expected form name" );
627 }
628
629 if ( ! p || ! *p )
630 {
631 fli_safe_free( p );
632 return ff_err( "Expected name of the form" );
633 }
634
635 fli_sstrcpy( forms[ fnumb ].fname, p, sizeof forms[ fnumb ].fname );
636 fli_safe_free( p );
637
638 /* Having gotten the name read all the remaining information. We then
639 should either end up at the start of a new form or at the end of
640 the file */
641
642 if ( ( r = read_form( ) ) == FF_AT_START_OF_FORM
643 || r == FF_AT_END_OF_FILE )
644 {
645 forms[ fnumb ].form = cur_form;
646 fl_add_browser_line( fd_control->formbrowser,
647 forms[ fnumb ].fname );
648 fnumb++;
649 }
650 }
651
652 /* Check if we're really at the end of the file and as many forms have
653 been found as we were led to expect */
654
655 if ( r == FF_AT_START_OF_FORM )
656 {
657 fl_free( fname );
658 return ff_err( "More forms found than expected" );
659 }
660 else if ( r != FF_READ_FAILURE && i < nforms )
661 {
662 ff_err( "Less forms found than expected" );
663 fl_free( fname );
664 return -1;
665 }
666
667 /* Everything's dandy and we're done with the file */
668
669 ff_close( );
670
671 set_form( fnumb > 0 ? 0 : -1 );
672
673 fli_safe_free( loadedfile );
674
675 if ( ! merge )
676 {
677 loadedfile = rel2abs( fname );
678 changed = FL_FALSE;
679 }
680 else
681 changed = FL_TRUE;
682
683 fl_free( fname );
684
685 /* Reset active coordinate system to pixel */
686
687 fli_cntl.coordUnit = FL_COORD_PIXEL;
688
689 /* Force output to use the same unit as used in the input when converting
690 directly. The reason is that we don't know the screen DPI. */
691
692 if ( ! fdopt.conv_only )
693 fdopt.unit = saved_unit;
694
695 fd_magic = 0;
696 return 0;
697 }
698
699
700 /***************************************
701 * Saves the form definitions, returns whether saved
702 ***************************************/
703
704 int
save_forms(const char * str)705 save_forms( const char *str )
706 {
707 int i,
708 snap;
709 FILE *fp;
710 char fname[ 1024 ],
711 filename[ 1024 ];
712 Conv *conv;
713
714 fl_use_fselector( SAVE_FSELECTOR );
715
716 /* Get the filename if necessary */
717
718 if ( ! str || ! * str )
719 {
720 char *dir = NULL;
721
722 if ( loadedfile && strchr( loadedfile, '/' ) )
723 {
724 dir = fl_strdup( loadedfile );
725 *strrchr( dir, '/' ) = '\0';
726 }
727 else
728 dir = fl_strdup( "" );
729
730 str = fl_show_fselector( "Filename to save forms to", dir, "*.fd", "" );
731
732 fl_free( dir );
733 }
734
735 if ( ! str )
736 return 0; /* cancel */
737
738 if ( ! *str )
739 {
740 fl_show_alert( "Warning", "No forms were saved.", "", 0 );
741 return 0;
742 }
743
744 /* Remove .fd if required */
745
746 strcpy( filename, str );
747 i = strlen( filename ) - 1;
748 if ( ! strcmp( filename + i - 2, ".fd" ) )
749 filename[ i - 2 ] = '\0';
750
751 strcpy( fname, filename );
752
753 /* In simple convert mode (i.e. not migrate) there's no need to (re)save
754 the .fd file */
755
756 if ( fdopt.conv_only == 1 )
757 goto emit_code;
758
759 /* Make the .fd file */
760
761 strcat( fname, ".fd" );
762 make_backup( fname );
763
764 if ( ( fp = fopen( fname, "w" ) ) == 0 )
765 {
766 fl_show_alert_f( 1, "Error\fCannot open file\n%s\nfor writing",
767 fname );
768 return 0;
769 }
770
771 snap = get_step_size( ) + 0.1;
772 fprintf( fp, "Magic: %d\n\n"
773 "Internal Form Definition File\n"
774 " (do not change)\n\n"
775 "Number of forms: %d\n"
776 "Unit of measure: %s\n",
777 MAGIC6, fnumb, unit_name( fdopt.unit ) );
778
779 if ( fd_bwidth != FL_BOUND_WIDTH && fd_bwidth )
780 fprintf( fp, "Border Width: %d\n", fd_bwidth );
781
782 if ( snap != 10 )
783 fprintf( fp, "SnapGrid: %d\n", snap );
784
785 for ( i = 0; i < fnumb; i++ )
786 write_form( fp, forms[ i ].form, forms[ i ].fname );
787
788 fprintf( fp, "\n==============================\n%s\n", main_name );
789 fclose( fp );
790
791 emit_code:
792
793 /* If no code is desired, return */
794
795 if ( ! fdopt.emit_code )
796 return 1;
797
798 conv = convertor + fdopt.language;
799
800 /* Some converter works on the c code */
801
802 if ( conv->need_c_code )
803 convertor[ FD_C ].convert( filename, forms, fnumb );
804
805 if ( conv->convert )
806 return conv->convert( filename, forms, fnumb );
807 else if ( conv->extern_convertor )
808 {
809 char cmdbuf[ 1024 ];
810 char optbuf[ 512 ];
811 int status;
812
813 *optbuf = '\0';
814
815 if ( fdopt.emit_main )
816 strcat( optbuf, "-main " );
817 if ( fdopt.emit_cb )
818 strcat( optbuf, "-callback " );
819 if ( fdopt.altformat )
820 strcat( optbuf, "-altformat " );
821 if ( fdopt.compensate )
822 strcat( optbuf, "-compensate " );
823 if ( fdopt.output_dir ) {
824 strcat( optbuf, "-dir " );
825 strcat( optbuf, fdopt.output_dir );
826 }
827
828 sprintf( cmdbuf, "%s %s%s", conv->extern_convertor, optbuf, filename );
829 M_warn( "Convert", "Executing %s", cmdbuf );
830
831 if ( fdopt.conv_only )
832 {
833 if ( ( status = system( cmdbuf ) ) )
834 M_err( "Output", "Error executing %s\n", cmdbuf );
835 }
836 else
837 {
838 fl_clear_command_log( );
839 if ( ( status = fl_exe_command( cmdbuf, 1 ) ) )
840 {
841 fl_addto_command_log( "\nerror executing " );
842 fl_addto_command_log( cmdbuf );
843 fl_show_command_log( FL_FULLBORDER );
844 }
845 }
846
847 return status == 0;
848 }
849 else
850 {
851 fprintf( stderr, "Convertor %s for %s not found\n",
852 conv->extern_convertor, conv->lang_name );
853 return 0;
854 }
855
856 return 1;
857 }
858
859
860 /*
861 * Local variables:
862 * tab-width: 4
863 * indent-tabs-mode: nil
864 * End:
865 */
866