2 // "$Id: demo.cxx 8252 2011-01-11 10:36:44Z manolo $"
4 // Main demo program for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
31 #if defined(WIN32) && !defined(__CYGWIN__)
34 // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
35 // on Windows, which is supposed to be POSIX compliant...
37 # define putenv _putenv
38 # endif // !__WATCOMC__
39 #elif defined USING_XCODE
40 #include <ApplicationServices/ApplicationServices.h>
41 #include <unistd.h> // for chdir()
43 #include <stdlib.h> // for system()
49 #include <FL/Fl_Double_Window.H>
50 #include <FL/Fl_Box.H>
51 #include <FL/Fl_Button.H>
52 #include <FL/Fl_Choice.H>
53 #include <FL/filename.H>
56 /* The form description */
58 void doexit(Fl_Widget
*, void *);
59 void doback(Fl_Widget
*, void *);
60 void dobut(Fl_Widget
*, long);
61 void doscheme(Fl_Choice
*c
, void *) {
62 Fl::scheme(c
->text(c
->value()));
65 Fl_Double_Window
*form
;
68 void create_the_forms() {
70 form
= new Fl_Double_Window(350, 440);
71 obj
= new Fl_Box(FL_FRAME_BOX
,10,15,330,40,"FLTK Demonstration");
72 obj
->color(FL_GRAY
-4);
74 obj
->labelfont(FL_BOLD
);
75 obj
->labeltype(FL_ENGRAVED_LABEL
);
76 obj
= new Fl_Box(FL_FRAME_BOX
,10,65,330,330,0);
77 obj
->color(FL_GRAY
-8);
78 obj
= new Fl_Button(280,405,60,25,"Exit");
79 obj
->callback(doexit
);
80 Fl_Choice
*choice
= new Fl_Choice(75, 405, 100, 25, "Scheme:");
81 choice
->labelfont(FL_HELVETICA_BOLD
);
84 choice
->add("plastic");
85 choice
->callback((Fl_Callback
*)doscheme
);
87 if (!Fl::scheme()) choice
->value(0);
88 else if (!strcmp(Fl::scheme(), "gtk+")) choice
->value(1);
89 else choice
->value(2);
90 obj
= new Fl_Button(10,15,330,380); obj
->type(FL_HIDDEN_BUTTON
);
91 obj
->callback(doback
);
92 obj
= but
[0] = new Fl_Button( 30, 85,90,90);
93 obj
= but
[1] = new Fl_Button(130, 85,90,90);
94 obj
= but
[2] = new Fl_Button(230, 85,90,90);
95 obj
= but
[3] = new Fl_Button( 30,185,90,90);
96 obj
= but
[4] = new Fl_Button(130,185,90,90);
97 obj
= but
[5] = new Fl_Button(230,185,90,90);
98 obj
= but
[6] = new Fl_Button( 30,285,90,90);
99 obj
= but
[7] = new Fl_Button(130,285,90,90);
100 obj
= but
[8] = new Fl_Button(230,285,90,90);
101 for (int i
=0; i
<9; i
++) {
102 but
[i
]->align(FL_ALIGN_WRAP
);
103 but
[i
]->callback(dobut
, i
);
108 /* Maintaining and building up the menus. */
114 char icommand
[9][64];
122 int find_menu(const char* nnn
)
123 /* Returns the number of a given menu name. */
126 for (i
=0; i
<mennumb
; i
++)
127 if (strcmp(menus
[i
].name
,nnn
) == 0) return i
;
131 void create_menu(const char* nnn
)
132 /* Creates a new menu with name nnn */
134 if (mennumb
== MAXMENU
-1) return;
135 strcpy(menus
[mennumb
].name
,nnn
);
136 menus
[mennumb
].numb
= 0;
140 void addto_menu(const char* men
, const char* item
, const char* comm
)
141 /* Adds an item to a menu */
143 int n
= find_menu(men
);
144 if (n
<0) { create_menu(men
); n
= find_menu(men
); }
145 if (menus
[n
].numb
== 9) return;
146 strcpy(menus
[n
].iname
[menus
[n
].numb
],item
);
147 strcpy(menus
[n
].icommand
[menus
[n
].numb
],comm
);
151 /* Button to Item conversion and back. */
154 { -1, -1, -1, -1, 0, -1, -1, -1, -1},
155 { -1, -1, -1, 0, -1, 1, -1, -1, -1},
156 { 0, -1, -1, -1, 1, -1, -1, -1, 2},
157 { 0, -1, 1, -1, -1, -1, 2, -1, 3},
158 { 0, -1, 1, -1, 2, -1, 3, -1, 4},
159 { 0, -1, 1, 2, -1, 3, 4, -1, 5},
160 { 0, -1, 1, 2, 3, 4, 5, -1, 6},
161 { 0, 1, 2, 3, -1, 4, 5, 6, 7},
162 { 0, 1, 2, 3, 4, 5, 6, 7, 8}
165 { 4, -1, -1, -1, -1, -1, -1, -1, -1},
166 { 3, 5, -1, -1, -1, -1, -1, -1, -1},
167 { 0, 4, 8, -1, -1, -1, -1, -1, -1},
168 { 0, 2, 6, 8, -1, -1, -1, -1, -1},
169 { 0, 2, 4, 6, 8, -1, -1, -1, -1},
170 { 0, 2, 3, 5, 6, 8, -1, -1, -1},
171 { 0, 2, 3, 4, 5, 6, 8, -1, -1},
172 { 0, 1, 2, 3, 5, 6, 7, 8, -1},
173 { 0, 1, 2, 3, 4, 5, 6, 7, 8}
176 int but2numb(int bnumb
, int maxnumb
)
177 /* Transforms a button number to an item number when there are
178 maxnumb items in total. -1 if the button should not exist. */
179 { return b2n
[maxnumb
][bnumb
]; }
181 int numb2but(int inumb
, int maxnumb
)
182 /* Transforms an item number to a button number when there are
183 maxnumb items in total. -1 if the item should not exist. */
184 { return n2b
[maxnumb
][inumb
]; }
186 /* Pushing and Popping menus */
191 void push_menu(const char* nnn
)
192 /* Pushes a menu to be visible */
195 int men
= find_menu(nnn
);
198 for (i
=0; i
<9; i
++) but
[i
]->hide();
201 bn
= numb2but(i
,n
-1);
203 but
[bn
]->label(menus
[men
].iname
[i
]);
204 if (menus
[men
].icommand
[i
][0] != '@') but
[bn
]->tooltip(menus
[men
].icommand
[i
]);
205 else but
[bn
]->tooltip(0);
207 if (stack
[stsize
]!=nnn
)
208 strcpy(stack
[stsize
],nnn
);
215 if (stsize
<=1) return;
217 push_menu(stack
[stsize
]);
220 /* The callback Routines */
222 void dobut(Fl_Widget
*, long arg
)
223 /* handles a button push */
225 int men
= find_menu(stack
[stsize
-1]);
226 int n
= menus
[men
].numb
;
227 int bn
= but2numb( (int) arg
, n
-1);
228 if (menus
[men
].icommand
[bn
][0] == '@')
229 push_menu(menus
[men
].icommand
[bn
]);
233 STARTUPINFO suInfo
; // Process startup information
234 PROCESS_INFORMATION prInfo
; // Process information
236 memset(&suInfo
, 0, sizeof(suInfo
));
237 suInfo
.cb
= sizeof(suInfo
);
239 int icommand_length
= strlen(menus
[men
].icommand
[bn
]);
241 char* copy_of_icommand
= new char[icommand_length
+1];
242 strcpy(copy_of_icommand
,menus
[men
].icommand
[bn
]);
244 // On WIN32 the .exe suffix needs to be appended to the command
245 // whilst leaving any additional parameters unchanged - this
246 // is required to handle the correct conversion of cases such as :
247 // `../fluid/fluid valuators.fl' to '../fluid/fluid.exe valuators.fl'.
249 // skip leading spaces.
250 char* start_command
= copy_of_icommand
;
251 while(*start_command
== ' ') ++start_command
;
253 // find the space between the command and parameters if one exists.
254 char* start_parameters
= strchr(start_command
,' ');
256 char* command
= new char[icommand_length
+6]; // 6 for extra 'd.exe\0'
258 if (start_parameters
==NULL
) { // no parameters required.
260 sprintf(command
, "%sd.exe", start_command
);
262 sprintf(command
, "%s.exe", start_command
);
264 } else { // parameters required.
265 // break the start_command at the intermediate space between
266 // start_command and start_parameters.
267 *start_parameters
= 0;
268 // move start_paremeters to skip over the intermediate space.
272 sprintf(command
, "%sd.exe %s", start_command
, start_parameters
);
274 sprintf(command
, "%s.exe %s", start_command
, start_parameters
);
278 CreateProcess(NULL
, command
, NULL
, NULL
, FALSE
,
279 NORMAL_PRIORITY_CLASS
, NULL
, NULL
, &suInfo
, &prInfo
);
282 delete[] copy_of_icommand
;
284 #elif defined USING_XCODE
285 char *cmd
= strdup(menus
[men
].icommand
[bn
]);
286 char *arg
= strchr(cmd
, ' ');
288 char command
[2048], path
[2048], app_path
[2048];
290 // this neat litle block of code ensures that the current directory is set
291 // to the location of the Demo application.
292 CFBundleRef app
= CFBundleGetMainBundle();
293 CFURLRef url
= CFBundleCopyBundleURL(app
);
294 CFStringRef cc_app_path
= CFURLCopyFileSystemPath(url
, kCFURLPOSIXPathStyle
);
295 CFStringGetCString(cc_app_path
, app_path
, 2048, kCFStringEncodingUTF8
);
297 char *n
= strrchr(app_path
, '/');
306 if (strcmp(cmd
, "../fluid/fluid")==0) {
307 fl_filename_absolute(path
, 2048, "../../../../test/");
308 sprintf(command
, "open Fluid.app --args %s%s", path
, arg
+1);
310 fl_filename_absolute(path
, 2048, "../../../../test/");
311 sprintf(command
, "open %s.app --args %s%s", cmd
, path
, arg
+1);
314 sprintf(command
, "open %s.app", cmd
);
320 #else // NON WIN32 systems.
322 int icommand_length
= strlen(menus
[men
].icommand
[bn
]);
323 char* command
= new char[icommand_length
+5]; // 5 for extra './' and ' &\0'
325 sprintf(command
, "./%s &", menus
[men
].icommand
[bn
]);
326 if (system(command
)==-1) { /* ignore */ }
333 void doback(Fl_Widget
*, void *) {pop_menu();}
335 void doexit(Fl_Widget
*, void *) {exit(0);}
337 int load_the_menu(const char* fname
)
338 /* Loads the menu file. Returns whether successful. */
341 char line
[256], mname
[64],iname
[64],cname
[64];
343 fin
= fl_fopen(fname
,"r");
344 #if defined ( USING_XCODE )
346 // mac os bundle menu detection:
347 char* pos
= strrchr(fname
,'/');
350 pos
= strrchr(fname
,'/');
352 strcpy(pos
,"/Resources/demo.menu");
353 fin
= fl_fopen(fname
,"r");
360 if (fgets(line
,256,fin
) == NULL
) break;
361 // remove all carriage returns that Cygwin may have inserted
362 char *s
= line
, *d
= line
;
364 while (*s
=='\r') s
++;
368 // interprete the line
370 while (line
[i
] == ' ' || line
[i
] == '\t') i
++;
371 if (line
[i
] == '\n') continue;
372 if (line
[i
] == '#') continue;
373 while (line
[i
] != ':' && line
[i
] != '\n') mname
[j
++] = line
[i
++];
375 if (line
[i
] == ':') i
++;
377 while (line
[i
] != ':' && line
[i
] != '\n')
379 if (line
[i
] == '\\') {
381 if (line
[i
] == 'n') iname
[j
++] = '\n';
382 else iname
[j
++] = line
[i
];
385 iname
[j
++] = line
[i
++];
388 if (line
[i
] == ':') i
++;
390 while (line
[i
] != ':' && line
[i
] != '\n') cname
[j
++] = line
[i
++];
392 addto_menu(mname
,iname
,cname
);
398 int main(int argc
, char **argv
) {
399 putenv((char *)"FLTK_DOCDIR=../documentation/html");
400 char buf
[FL_PATH_MAX
];
401 strcpy(buf
, argv
[0]);
402 #if ( defined _MSC_VER || defined __MWERKS__ ) && defined _DEBUG
403 // MS_VisualC appends a 'd' to debugging executables. remove it.
404 fl_filename_setext( buf
, "" );
405 buf
[ strlen(buf
)-1 ] = 0;
407 fl_filename_setext(buf
,".menu");
408 const char *fname
= buf
;
410 if (!Fl::args(argc
,argv
,i
) || i
< argc
-1)
411 Fl::fatal("Usage: %s <switches> <menufile>\n%s",argv
[0],Fl::help
);
412 if (i
< argc
) fname
= argv
[i
];
416 if (!load_the_menu(fname
)) Fl::fatal("Can't open %s",fname
);
419 const char *c
= fl_filename_name(buf
);
422 if (chdir(buf
)==-1) { /* ignore */ }
425 form
->show(argc
,argv
);
431 // End of "$Id: demo.cxx 8252 2011-01-11 10:36:44Z manolo $".