|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: fluid.cxx 8202 2011-01-06 21:36:04Z matt $" 00003 // 00004 // FLUID main entry for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 #include <FL/Fl.H> 00029 #include <FL/Fl_Double_Window.H> 00030 #include <FL/Fl_Box.H> 00031 #include <FL/Fl_Button.H> 00032 #include <FL/Fl_File_Icon.H> 00033 #include <FL/Fl_Help_Dialog.H> 00034 #include <FL/Fl_Hold_Browser.H> 00035 #include <FL/Fl_Menu_Bar.H> 00036 #include <FL/Fl_Input.H> 00037 #include <FL/Fl_Plugin.H> 00038 #include <FL/fl_ask.H> 00039 #include <FL/fl_draw.H> 00040 #include <FL/Fl_File_Chooser.H> 00041 #include <FL/fl_message.H> 00042 #include <FL/filename.H> 00043 #include <stdio.h> 00044 #include <stdlib.h> 00045 #include <errno.h> 00046 #include <sys/stat.h> 00047 #include <time.h> // time(), localtime(), etc. 00048 00049 #include "../src/flstring.h" 00050 #include "alignment_panel.h" 00051 #include "function_panel.h" 00052 #include "template_panel.h" 00053 #if !defined(WIN32) || defined(__CYGWIN__) 00054 # include "print_panel.cxx" 00055 #endif // !WIN32 || __CYGWIN__ 00056 00057 #if defined(WIN32) && !defined(__CYGWIN__) 00058 # include <direct.h> 00059 # include <windows.h> 00060 # include <io.h> 00061 # include <fcntl.h> 00062 # include <commdlg.h> 00063 # include <FL/x.H> 00064 # ifndef __WATCOMC__ 00065 // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs 00066 // on Windows, which is supposed to be POSIX compliant... 00067 # define access _access 00068 # define chdir _chdir 00069 # define getcwd _getcwd 00070 # endif // !__WATCOMC__ 00071 #else 00072 # include <unistd.h> 00073 #endif 00074 #ifdef __EMX__ 00075 # include <X11/Xlibint.h> 00076 #endif 00077 00078 #include "about_panel.h" 00079 #include "undo.h" 00080 00081 #include "Fl_Type.h" 00082 00083 extern "C" 00084 { 00085 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) 00086 # include <zlib.h> 00087 # ifdef HAVE_PNG_H 00088 # include <png.h> 00089 # else 00090 # include <libpng/png.h> 00091 # endif // HAVE_PNG_H 00092 #endif // HAVE_LIBPNG && HAVE_LIBZ 00093 } 00094 00095 static Fl_Help_Dialog *help_dialog = 0; 00096 00097 Fl_Preferences fluid_prefs(Fl_Preferences::USER, "fltk.org", "fluid"); 00098 int gridx = 5; 00099 int gridy = 5; 00100 int snap = 1; 00101 int show_guides = 1; 00102 int show_comments = 1; 00103 int show_coredevmenus = 1; 00104 00105 // File history info... 00106 char absolute_history[10][FL_PATH_MAX]; 00107 char relative_history[10][FL_PATH_MAX]; 00108 00109 void load_history(); 00110 void update_history(const char *); 00111 00112 // Shell command support... 00113 void show_shell_window(); 00114 00115 Fl_Menu_Item *save_item = 0L; 00116 Fl_Menu_Item *history_item = 0L; 00117 Fl_Menu_Item *widgetbin_item = 0L; 00118 Fl_Menu_Item *sourceview_item = 0L; 00119 00121 00122 static const char *filename; 00123 void set_filename(const char *c); 00124 void set_modflag(int mf); 00125 int modflag; 00126 00127 static char* pwd; 00128 static char in_source_dir; 00129 void goto_source_dir() { 00130 if (in_source_dir) return; 00131 if (!filename || !*filename) return; 00132 const char *p = fl_filename_name(filename); 00133 if (p <= filename) return; // it is in the current directory 00134 char buffer[FL_PATH_MAX]; 00135 strlcpy(buffer, filename, sizeof(buffer)); 00136 int n = p-filename; if (n>1) n--; buffer[n] = 0; 00137 if (!pwd) { 00138 pwd = getcwd(0,FL_PATH_MAX); 00139 if (!pwd) {fprintf(stderr,"getwd : %s\n",strerror(errno)); return;} 00140 } 00141 if (chdir(buffer)<0) {fprintf(stderr, "Can't chdir to %s : %s\n", 00142 buffer, strerror(errno)); return;} 00143 in_source_dir = 1; 00144 } 00145 00146 void leave_source_dir() { 00147 if (!in_source_dir) return; 00148 if (chdir(pwd)<0) {fprintf(stderr, "Can't chdir to %s : %s\n", 00149 pwd, strerror(errno));} 00150 in_source_dir = 0; 00151 } 00152 00153 char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0 ) { 00154 Fl_Preferences pos(fluid_prefs, prefsName); 00155 if (prevpos_button->value()) { 00156 pos.get("x", X, X); 00157 pos.get("y", Y, Y); 00158 if ( W!=0 ) { 00159 pos.get("w", W, W); 00160 pos.get("h", H, H); 00161 w->resize( X, Y, W, H ); 00162 } 00163 else 00164 w->position( X, Y ); 00165 } 00166 pos.get("visible", Visible, Visible); 00167 return Visible; 00168 } 00169 00170 void save_position(Fl_Window *w, const char *prefsName) { 00171 Fl_Preferences pos(fluid_prefs, prefsName); 00172 pos.set("x", w->x()); 00173 pos.set("y", w->y()); 00174 pos.set("w", w->w()); 00175 pos.set("h", w->h()); 00176 pos.set("visible", (int)(w->shown() && w->visible())); 00177 } 00178 00179 Fl_Window *main_window; 00180 Fl_Menu_Bar *main_menubar; 00181 00182 static char* cutfname(int which = 0) { 00183 static char name[2][FL_PATH_MAX]; 00184 static char beenhere = 0; 00185 00186 if (!beenhere) { 00187 beenhere = 1; 00188 fluid_prefs.getUserdataPath(name[0], sizeof(name[0])); 00189 strlcat(name[0], "cut_buffer", sizeof(name[0])); 00190 fluid_prefs.getUserdataPath(name[1], sizeof(name[1])); 00191 strlcat(name[1], "dup_buffer", sizeof(name[1])); 00192 } 00193 00194 return name[which]; 00195 } 00196 00197 void save_cb(Fl_Widget *, void *v) { 00198 const char *c = filename; 00199 if (v || !c || !*c) { 00200 fl_file_chooser_ok_label("Save"); 00201 c=fl_file_chooser("Save To:", "FLUID Files (*.f[ld])", c); 00202 fl_file_chooser_ok_label(NULL); 00203 if (!c) return; 00204 00205 if (!access(c, 0)) { 00206 const char *basename; 00207 if ((basename = strrchr(c, '/')) != NULL) 00208 basename ++; 00209 #if defined(WIN32) || defined(__EMX__) 00210 if ((basename = strrchr(c, '\\')) != NULL) 00211 basename ++; 00212 #endif // WIN32 || __EMX__ 00213 else 00214 basename = c; 00215 00216 if (fl_choice("The file \"%s\" already exists.\n" 00217 "Do you want to replace it?", "Cancel", 00218 "Replace", NULL, basename) == 0) return; 00219 } 00220 00221 if (v != (void *)2) set_filename(c); 00222 } 00223 if (!write_file(c)) { 00224 fl_alert("Error writing %s: %s", c, strerror(errno)); 00225 return; 00226 } 00227 00228 if (v != (void *)2) { 00229 set_modflag(0); 00230 undo_save = undo_current; 00231 } 00232 } 00233 00234 void save_template_cb(Fl_Widget *, void *) { 00235 // Setup the template panel... 00236 if (!template_panel) make_template_panel(); 00237 00238 template_clear(); 00239 template_browser->add("New Template"); 00240 template_load(); 00241 00242 template_name->show(); 00243 template_name->value(""); 00244 00245 template_instance->hide(); 00246 00247 template_delete->show(); 00248 template_delete->deactivate(); 00249 00250 template_submit->label("Save"); 00251 template_submit->deactivate(); 00252 00253 template_panel->label("Save Template"); 00254 00255 // Show the panel and wait for the user to do something... 00256 template_panel->show(); 00257 while (template_panel->shown()) Fl::wait(); 00258 00259 // Get the template name, return if it is empty... 00260 const char *c = template_name->value(); 00261 if (!c || !*c) return; 00262 00263 // Convert template name to filename_with_underscores 00264 char safename[FL_PATH_MAX], *safeptr; 00265 strlcpy(safename, c, sizeof(safename)); 00266 for (safeptr = safename; *safeptr; safeptr ++) { 00267 if (isspace(*safeptr)) *safeptr = '_'; 00268 } 00269 00270 // Find the templates directory... 00271 char filename[FL_PATH_MAX]; 00272 fluid_prefs.getUserdataPath(filename, sizeof(filename)); 00273 00274 strlcat(filename, "templates", sizeof(filename)); 00275 #if defined(WIN32) && !defined(__CYGWIN__) 00276 if (access(filename, 0)) mkdir(filename); 00277 #else 00278 if (access(filename, 0)) mkdir(filename, 0777); 00279 #endif // WIN32 && !__CYGWIN__ 00280 00281 strlcat(filename, "/", sizeof(filename)); 00282 strlcat(filename, safename, sizeof(filename)); 00283 00284 char *ext = filename + strlen(filename); 00285 if (ext >= (filename + sizeof(filename) - 5)) { 00286 fl_alert("The template name \"%s\" is too long!", c); 00287 return; 00288 } 00289 00290 // Save the .fl file... 00291 strcpy(ext, ".fl"); 00292 00293 if (!access(filename, 0)) { 00294 if (fl_choice("The template \"%s\" already exists.\n" 00295 "Do you want to replace it?", "Cancel", 00296 "Replace", NULL, c) == 0) return; 00297 } 00298 00299 if (!write_file(filename)) { 00300 fl_alert("Error writing %s: %s", filename, strerror(errno)); 00301 return; 00302 } 00303 00304 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) 00305 // Get the screenshot, if any... 00306 Fl_Type *t; 00307 00308 for (t = Fl_Type::first; t; t = t->next) { 00309 // Find the first window... 00310 if (t->is_window()) break; 00311 } 00312 00313 if (!t) return; 00314 00315 // Grab a screenshot... 00316 Fl_Window_Type *wt = (Fl_Window_Type *)t; 00317 uchar *pixels; 00318 int w, h; 00319 00320 if ((pixels = wt->read_image(w, h)) == NULL) return; 00321 00322 // Save to a PNG file... 00323 strcpy(ext, ".png"); 00324 00325 FILE *fp; 00326 00327 if ((fp = fl_fopen(filename, "wb")) == NULL) { 00328 delete[] pixels; 00329 fl_alert("Error writing %s: %s", filename, strerror(errno)); 00330 return; 00331 } 00332 00333 png_structp pptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); 00334 png_infop iptr = png_create_info_struct(pptr); 00335 png_bytep ptr = (png_bytep)pixels; 00336 00337 png_init_io(pptr, fp); 00338 png_set_IHDR(pptr, iptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 00339 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 00340 png_set_sRGB(pptr, iptr, PNG_sRGB_INTENT_PERCEPTUAL); 00341 00342 png_write_info(pptr, iptr); 00343 00344 for (int i = h; i > 0; i --, ptr += w * 3) { 00345 png_write_row(pptr, ptr); 00346 } 00347 00348 png_write_end(pptr, iptr); 00349 png_destroy_write_struct(&pptr, &iptr); 00350 00351 fclose(fp); 00352 00353 # if 0 // The original PPM output code... 00354 strcpy(ext, ".ppm"); 00355 fp = fl_fopen(filename, "wb"); 00356 fprintf(fp, "P6\n%d %d 255\n", w, h); 00357 fwrite(pixels, w * h, 3, fp); 00358 fclose(fp); 00359 # endif // 0 00360 00361 delete[] pixels; 00362 #endif // HAVE_LIBPNG && HAVE_LIBZ 00363 } 00364 00365 void revert_cb(Fl_Widget *,void *) { 00366 if (modflag) { 00367 if (!fl_choice("This user interface has been changed. Really revert?", 00368 "Cancel", "Revert", NULL)) return; 00369 } 00370 undo_suspend(); 00371 if (!read_file(filename, 0)) { 00372 undo_resume(); 00373 fl_message("Can't read %s: %s", filename, strerror(errno)); 00374 return; 00375 } 00376 undo_resume(); 00377 set_modflag(0); 00378 undo_clear(); 00379 } 00380 00381 void exit_cb(Fl_Widget *,void *) { 00382 if (modflag) 00383 switch (fl_choice("Do you want to save changes to this user\n" 00384 "interface before exiting?", "Cancel", 00385 "Save", "Don't Save")) 00386 { 00387 case 0 : /* Cancel */ 00388 return; 00389 case 1 : /* Save */ 00390 save_cb(NULL, NULL); 00391 if (modflag) return; // Didn't save! 00392 } 00393 00394 save_position(main_window,"main_window_pos"); 00395 00396 if (widgetbin_panel) { 00397 save_position(widgetbin_panel,"widgetbin_pos"); 00398 delete widgetbin_panel; 00399 } 00400 if (sourceview_panel) { 00401 Fl_Preferences svp(fluid_prefs, "sourceview"); 00402 svp.set("autorefresh", sv_autorefresh->value()); 00403 svp.set("autoposition", sv_autoposition->value()); 00404 svp.set("tab", sv_tab->find(sv_tab->value())); 00405 save_position(sourceview_panel,"sourceview_pos"); 00406 delete sourceview_panel; 00407 } 00408 if (about_panel) 00409 delete about_panel; 00410 if (help_dialog) 00411 delete help_dialog; 00412 00413 undo_clear(); 00414 00415 exit(0); 00416 } 00417 00418 #ifdef __APPLE__ 00419 # include <FL/x.H> 00420 00421 void 00422 apple_open_cb(const char *c) { 00423 if (modflag) { 00424 switch (fl_choice("Do you want to save changes to this user\n" 00425 "interface before opening another one?", "Don't Save", 00426 "Save", "Cancel")) 00427 { 00428 case 0 : /* Cancel */ 00429 return; 00430 case 1 : /* Save */ 00431 save_cb(NULL, NULL); 00432 if (modflag) return; // Didn't save! 00433 } 00434 } 00435 const char *oldfilename; 00436 oldfilename = filename; 00437 filename = NULL; 00438 set_filename(c); 00439 undo_suspend(); 00440 if (!read_file(c, 0)) { 00441 undo_resume(); 00442 fl_message("Can't read %s: %s", c, strerror(errno)); 00443 free((void *)filename); 00444 filename = oldfilename; 00445 if (main_window) main_window->label(filename); 00446 return; 00447 } 00448 00449 // Loaded a file; free the old filename... 00450 set_modflag(0); 00451 undo_resume(); 00452 undo_clear(); 00453 if (oldfilename) free((void *)oldfilename); 00454 } 00455 #endif // __APPLE__ 00456 00457 void open_cb(Fl_Widget *, void *v) { 00458 if (!v && modflag) { 00459 switch (fl_choice("Do you want to save changes to this user\n" 00460 "interface before opening another one?", "Cancel", 00461 "Save", "Don't Save")) 00462 { 00463 case 0 : /* Cancel */ 00464 return; 00465 case 1 : /* Save */ 00466 save_cb(NULL, NULL); 00467 if (modflag) return; // Didn't save! 00468 } 00469 } 00470 const char *c; 00471 const char *oldfilename; 00472 fl_file_chooser_ok_label("Open"); 00473 c = fl_file_chooser("Open:", "FLUID Files (*.f[ld])", filename); 00474 fl_file_chooser_ok_label(NULL); 00475 if (!c) return; 00476 oldfilename = filename; 00477 filename = NULL; 00478 set_filename(c); 00479 if (v != 0) undo_checkpoint(); 00480 undo_suspend(); 00481 if (!read_file(c, v!=0)) { 00482 undo_resume(); 00483 fl_message("Can't read %s: %s", c, strerror(errno)); 00484 free((void *)filename); 00485 filename = oldfilename; 00486 if (main_window) set_modflag(modflag); 00487 return; 00488 } 00489 undo_resume(); 00490 if (v) { 00491 // Inserting a file; restore the original filename... 00492 free((void *)filename); 00493 filename = oldfilename; 00494 set_modflag(1); 00495 } else { 00496 // Loaded a file; free the old filename... 00497 set_modflag(0); 00498 undo_clear(); 00499 if (oldfilename) free((void *)oldfilename); 00500 } 00501 } 00502 00503 void open_history_cb(Fl_Widget *, void *v) { 00504 if (modflag) { 00505 switch (fl_choice("Do you want to save changes to this user\n" 00506 "interface before opening another one?", "Cancel", 00507 "Save", "Don't Save")) 00508 { 00509 case 0 : /* Cancel */ 00510 return; 00511 case 1 : /* Save */ 00512 save_cb(NULL, NULL); 00513 if (modflag) return; // Didn't save! 00514 } 00515 } 00516 const char *oldfilename = filename; 00517 filename = NULL; 00518 set_filename((char *)v); 00519 undo_suspend(); 00520 if (!read_file(filename, 0)) { 00521 undo_resume(); 00522 undo_clear(); 00523 fl_message("Can't read %s: %s", filename, strerror(errno)); 00524 free((void *)filename); 00525 filename = oldfilename; 00526 if (main_window) main_window->label(filename); 00527 return; 00528 } 00529 set_modflag(0); 00530 undo_resume(); 00531 undo_clear(); 00532 if (oldfilename) free((void *)oldfilename); 00533 } 00534 00535 void new_cb(Fl_Widget *, void *v) { 00536 // Check if the current file has been modified... 00537 if (!v && modflag) { 00538 // Yes, ask the user what to do... 00539 switch (fl_choice("Do you want to save changes to this user\n" 00540 "interface before creating a new one?", "Cancel", 00541 "Save", "Don't Save")) 00542 { 00543 case 0 : /* Cancel */ 00544 return; 00545 case 1 : /* Save */ 00546 save_cb(NULL, NULL); 00547 if (modflag) return; // Didn't save! 00548 } 00549 } 00550 00551 // Setup the template panel... 00552 if (!template_panel) make_template_panel(); 00553 00554 template_clear(); 00555 template_browser->add("Blank"); 00556 template_load(); 00557 00558 template_name->hide(); 00559 template_name->value(""); 00560 00561 template_instance->show(); 00562 template_instance->deactivate(); 00563 template_instance->value(""); 00564 00565 template_delete->hide(); 00566 00567 template_submit->label("New"); 00568 template_submit->deactivate(); 00569 00570 template_panel->label("New"); 00571 00572 // Show the panel and wait for the user to do something... 00573 template_panel->show(); 00574 while (template_panel->shown()) Fl::wait(); 00575 00576 // See if the user chose anything... 00577 int item = template_browser->value(); 00578 if (item < 1) return; 00579 00580 // Clear the current data... 00581 delete_all(); 00582 set_filename(NULL); 00583 00584 // Load the template, if any... 00585 const char *tname = (const char *)template_browser->data(item); 00586 00587 if (tname) { 00588 // Grab the instance name... 00589 const char *iname = template_instance->value(); 00590 00591 if (iname && *iname) { 00592 // Copy the template to a temp file, then read it in... 00593 char line[1024], *ptr, *next; 00594 FILE *infile, *outfile; 00595 00596 if ((infile = fl_fopen(tname, "r")) == NULL) { 00597 fl_alert("Error reading template file \"%s\":\n%s", tname, 00598 strerror(errno)); 00599 set_modflag(0); 00600 undo_clear(); 00601 return; 00602 } 00603 00604 if ((outfile = fl_fopen(cutfname(1), "w")) == NULL) { 00605 fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1), 00606 strerror(errno)); 00607 fclose(infile); 00608 set_modflag(0); 00609 undo_clear(); 00610 return; 00611 } 00612 00613 while (fgets(line, sizeof(line), infile)) { 00614 // Replace @INSTANCE@ with the instance name... 00615 for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != NULL; ptr = next + 10) { 00616 fwrite(ptr, next - ptr, 1, outfile); 00617 fputs(iname, outfile); 00618 } 00619 00620 fputs(ptr, outfile); 00621 } 00622 00623 fclose(infile); 00624 fclose(outfile); 00625 00626 undo_suspend(); 00627 read_file(cutfname(1), 0); 00628 unlink(cutfname(1)); 00629 undo_resume(); 00630 } else { 00631 // No instance name, so read the template without replacements... 00632 undo_suspend(); 00633 read_file(tname, 0); 00634 undo_resume(); 00635 } 00636 } 00637 00638 set_modflag(0); 00639 undo_clear(); 00640 } 00641 00642 int exit_early = 0; 00643 int compile_only = 0; 00644 int compile_strings = 0; 00645 int header_file_set = 0; 00646 int code_file_set = 0; 00647 const char* header_file_name = ".h"; 00648 const char* code_file_name = ".cxx"; 00649 int i18n_type = 0; 00650 const char* i18n_include = ""; 00651 const char* i18n_function = ""; 00652 const char* i18n_file = ""; 00653 const char* i18n_set = ""; 00654 char i18n_program[FL_PATH_MAX] = ""; 00655 00656 void write_cb(Fl_Widget *, void *) { 00657 if (!filename) { 00658 save_cb(0,0); 00659 if (!filename) return; 00660 } 00661 char cname[FL_PATH_MAX]; 00662 char hname[FL_PATH_MAX]; 00663 strlcpy(i18n_program, fl_filename_name(filename), sizeof(i18n_program)); 00664 fl_filename_setext(i18n_program, sizeof(i18n_program), ""); 00665 if (*code_file_name == '.' && strchr(code_file_name, '/') == NULL) { 00666 strlcpy(cname, fl_filename_name(filename), sizeof(cname)); 00667 fl_filename_setext(cname, sizeof(cname), code_file_name); 00668 } else { 00669 strlcpy(cname, code_file_name, sizeof(hname)); 00670 } 00671 if (*header_file_name == '.' && strchr(header_file_name, '/') == NULL) { 00672 strlcpy(hname, fl_filename_name(filename), sizeof(hname)); 00673 fl_filename_setext(hname, sizeof(hname), header_file_name); 00674 } else { 00675 strlcpy(hname, header_file_name, sizeof(hname)); 00676 } 00677 if (!compile_only) goto_source_dir(); 00678 int x = write_code(cname,hname); 00679 if (!compile_only) leave_source_dir(); 00680 strlcat(cname, " and ", sizeof(cname)); 00681 strlcat(cname, hname, sizeof(cname)); 00682 if (compile_only) { 00683 if (!x) {fprintf(stderr,"%s : %s\n",cname,strerror(errno)); exit(1);} 00684 } else { 00685 if (!x) { 00686 fl_message("Can't write %s: %s", cname, strerror(errno)); 00687 } else if (completion_button->value()) { 00688 fl_message("Wrote %s", cname); 00689 } 00690 } 00691 } 00692 00693 void write_strings_cb(Fl_Widget *, void *) { 00694 static const char *exts[] = { ".txt", ".po", ".msg" }; 00695 if (!filename) { 00696 save_cb(0,0); 00697 if (!filename) return; 00698 } 00699 char sname[FL_PATH_MAX]; 00700 strlcpy(sname, fl_filename_name(filename), sizeof(sname)); 00701 fl_filename_setext(sname, sizeof(sname), exts[i18n_type]); 00702 if (!compile_only) goto_source_dir(); 00703 int x = write_strings(sname); 00704 if (!compile_only) leave_source_dir(); 00705 if (compile_only) { 00706 if (x) {fprintf(stderr,"%s : %s\n",sname,strerror(errno)); exit(1);} 00707 } else { 00708 if (x) { 00709 fl_message("Can't write %s: %s", sname, strerror(errno)); 00710 } else if (completion_button->value()) { 00711 fl_message("Wrote %s", sname); 00712 } 00713 } 00714 } 00715 00716 void openwidget_cb(Fl_Widget *, void *) { 00717 if (!Fl_Type::current) { 00718 fl_message("Please select a widget"); 00719 return; 00720 } 00721 Fl_Type::current->open(); 00722 } 00723 00724 void toggle_overlays(Fl_Widget *,void *); 00725 00726 void select_all_cb(Fl_Widget *,void *); 00727 void select_none_cb(Fl_Widget *,void *); 00728 00729 void group_cb(Fl_Widget *, void *); 00730 00731 void ungroup_cb(Fl_Widget *, void *); 00732 00733 extern int pasteoffset; 00734 static int ipasteoffset; 00735 00736 void copy_cb(Fl_Widget*, void*) { 00737 if (!Fl_Type::current) { 00738 fl_beep(); 00739 return; 00740 } 00741 ipasteoffset = 10; 00742 if (!write_file(cutfname(),1)) { 00743 fl_message("Can't write %s: %s", cutfname(), strerror(errno)); 00744 return; 00745 } 00746 } 00747 00748 extern void select_only(Fl_Type *); 00749 void cut_cb(Fl_Widget *, void *) { 00750 if (!Fl_Type::current) { 00751 fl_beep(); 00752 return; 00753 } 00754 if (!write_file(cutfname(),1)) { 00755 fl_message("Can't write %s: %s", cutfname(), strerror(errno)); 00756 return; 00757 } 00758 undo_checkpoint(); 00759 set_modflag(1); 00760 ipasteoffset = 0; 00761 Fl_Type *p = Fl_Type::current->parent; 00762 while (p && p->selected) p = p->parent; 00763 delete_all(1); 00764 if (p) select_only(p); 00765 } 00766 00767 void delete_cb(Fl_Widget *, void *) { 00768 if (!Fl_Type::current) { 00769 fl_beep(); 00770 return; 00771 } 00772 undo_checkpoint(); 00773 set_modflag(1); 00774 ipasteoffset = 0; 00775 Fl_Type *p = Fl_Type::current->parent; 00776 while (p && p->selected) p = p->parent; 00777 delete_all(1); 00778 if (p) select_only(p); 00779 } 00780 00781 extern int force_parent; 00782 00783 void paste_cb(Fl_Widget*, void*) { 00784 //if (ipasteoffset) force_parent = 1; 00785 pasteoffset = ipasteoffset; 00786 if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx; 00787 if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy; 00788 undo_checkpoint(); 00789 undo_suspend(); 00790 if (!read_file(cutfname(), 1)) { 00791 fl_message("Can't read %s: %s", cutfname(), strerror(errno)); 00792 } 00793 undo_resume(); 00794 pasteoffset = 0; 00795 ipasteoffset += 10; 00796 force_parent = 0; 00797 } 00798 00799 // Duplicate the selected widgets... 00800 void duplicate_cb(Fl_Widget*, void*) { 00801 if (!Fl_Type::current) { 00802 fl_beep(); 00803 return; 00804 } 00805 00806 if (!write_file(cutfname(1),1)) { 00807 fl_message("Can't write %s: %s", cutfname(1), strerror(errno)); 00808 return; 00809 } 00810 00811 pasteoffset = 0; 00812 force_parent = 1; 00813 00814 undo_checkpoint(); 00815 undo_suspend(); 00816 if (!read_file(cutfname(1), 1)) { 00817 fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); 00818 } 00819 unlink(cutfname(1)); 00820 undo_resume(); 00821 00822 force_parent = 0; 00823 } 00824 00825 void earlier_cb(Fl_Widget*,void*); 00826 00827 void later_cb(Fl_Widget*,void*); 00828 00829 Fl_Type *sort(Fl_Type *parent); 00830 00831 static void sort_cb(Fl_Widget *,void *) { 00832 sort((Fl_Type*)0); 00833 } 00834 00835 void show_project_cb(Fl_Widget *, void *); 00836 void show_grid_cb(Fl_Widget *, void *); 00837 void show_settings_cb(Fl_Widget *, void *); 00838 void show_global_settings_cb(Fl_Widget *, void *); 00839 00840 void align_widget_cb(Fl_Widget *, long); 00841 void widget_size_cb(Fl_Widget *, long); 00842 00843 void about_cb(Fl_Widget *, void *) { 00844 if (!about_panel) make_about_panel(); 00845 about_panel->show(); 00846 } 00847 00848 void show_help(const char *name) { 00849 const char *docdir; 00850 char helpname[FL_PATH_MAX]; 00851 00852 if (!help_dialog) help_dialog = new Fl_Help_Dialog(); 00853 00854 if ((docdir = getenv("FLTK_DOCDIR")) == NULL) { 00855 #ifdef __EMX__ 00856 // Doesn't make sense to have a hardcoded fallback 00857 static char fltk_docdir[FL_PATH_MAX]; 00858 00859 strlcpy(fltk_docdir, __XOS2RedirRoot("/XFree86/lib/X11/fltk/doc"), 00860 sizeof(fltk_docdir)); 00861 00862 docdir = fltk_docdir; 00863 #else 00864 docdir = FLTK_DOCDIR; 00865 #endif // __EMX__ 00866 } 00867 snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name); 00868 00869 help_dialog->load(helpname); 00870 help_dialog->show(); 00871 } 00872 00873 void help_cb(Fl_Widget *, void *) { 00874 show_help("fluid.html"); 00875 } 00876 00877 void manual_cb(Fl_Widget *, void *) { 00878 show_help("main.html"); 00879 } 00880 00881 00883 00884 #if defined(WIN32) && !defined(__CYGWIN__) 00885 // Draw a shaded box... 00886 static void win_box(int x, int y, int w, int h) { 00887 fl_color(0xc0, 0xc0, 0xc0); 00888 fl_rectf(x, y, w, h); 00889 fl_color(0, 0, 0); 00890 fl_rect(x, y, w, h); 00891 fl_color(0xf0, 0xf0, 0xf0); 00892 fl_rectf(x + 1, y + 1, 4, h - 2); 00893 fl_rectf(x + 1, y + 1, w - 2, 4); 00894 fl_color(0x90, 0x90, 0x90); 00895 fl_rectf(x + w - 5, y + 1, 4, h - 2); 00896 fl_rectf(x + 1, y + h - 5, w - 2, 4); 00897 } 00898 00899 // Load and show the print dialog... 00900 void print_menu_cb(Fl_Widget *, void *) { 00901 PRINTDLG dialog; // Print dialog 00902 DOCINFO docinfo; // Document info 00903 int first, last; // First and last page 00904 int page; // Current page 00905 int winpage; // Current window page 00906 int num_pages; // Number of pages 00907 Fl_Type *t; // Current widget 00908 int num_windows; // Number of windows 00909 Fl_Window_Type *windows[1000]; // Windows to print 00910 00911 00912 // Show print dialog... 00913 for (t = Fl_Type::first, num_pages = 0; t; t = t->next) { 00914 if (t->is_window()) num_pages ++; 00915 } 00916 00917 memset(&dialog, 0, sizeof(dialog)); 00918 dialog.lStructSize = sizeof(dialog); 00919 dialog.hwndOwner = fl_xid(main_window); 00920 dialog.Flags = PD_ALLPAGES | 00921 PD_RETURNDC; 00922 dialog.nFromPage = 1; 00923 dialog.nToPage = num_pages; 00924 dialog.nMinPage = 1; 00925 dialog.nMaxPage = num_pages; 00926 dialog.nCopies = 1; 00927 00928 if (!PrintDlg(&dialog)) return; 00929 00930 // Get the base filename... 00931 const char *basename = strrchr(filename, '/'); 00932 if (basename) basename ++; 00933 else basename = filename; 00934 00935 // Do the print job... 00936 memset(&docinfo, 0, sizeof(docinfo)); 00937 docinfo.cbSize = sizeof(docinfo); 00938 docinfo.lpszDocName = basename; 00939 00940 StartDoc(dialog.hDC, &docinfo); 00941 00942 // Figure out how many pages we'll have to print... 00943 if (dialog.Flags & PD_PAGENUMS) { 00944 // Get from and to page numbers... 00945 first = dialog.nFromPage; 00946 last = dialog.nToPage; 00947 00948 if (first > last) { 00949 // Swap first/last page 00950 page = first; 00951 first = last; 00952 last = page; 00953 } 00954 } else { 00955 // Print everything... 00956 first = 1; 00957 last = dialog.nMaxPage; 00958 } 00959 00960 for (t = Fl_Type::first, num_windows = 0, winpage = 0; t; t = t->next) { 00961 if (t->is_window()) { 00962 winpage ++; 00963 windows[num_windows] = (Fl_Window_Type *)t; 00964 num_windows ++; 00965 #if 0 00966 if (dialog.Flags & PD_ALLPAGES) num_windows ++; 00967 else if ((dialog.Flags & PD_PAGENUMS) && winpage >= first && 00968 winpage <= last) num_windows ++; 00969 else if ((dialog.Flags & PD_SELECTION) && t->selected) num_windows ++; 00970 #endif // 0 00971 } 00972 } 00973 00974 num_pages = num_windows; 00975 00976 // Figure out the page size and margins... 00977 int width, length; // Size of page 00978 int xdpi, ydpi; // Output resolution 00979 char buffer[1024]; 00980 00981 width = GetDeviceCaps(dialog.hDC, HORZRES); 00982 length = GetDeviceCaps(dialog.hDC, VERTRES); 00983 xdpi = GetDeviceCaps(dialog.hDC, LOGPIXELSX); 00984 ydpi = GetDeviceCaps(dialog.hDC, LOGPIXELSY); 00985 00986 // fl_message("width=%d, length=%d, xdpi=%d, ydpi=%d, num_windows=%d\n", 00987 // width, length, xdpi, ydpi, num_windows); 00988 00989 HDC save_dc = fl_gc; 00990 HWND save_win = fl_window; 00991 int fontsize = 14 * ydpi / 72; 00992 00993 fl_gc = dialog.hDC; 00994 fl_window = (HWND)dialog.hDC; 00995 fl_push_no_clip(); 00996 00997 // Get the time and date... 00998 time_t curtime = time(NULL); 00999 struct tm *curdate = localtime(&curtime); 01000 char date[1024]; 01001 01002 strftime(date, sizeof(date), "%c", curdate); 01003 01004 // Print each of the windows... 01005 for (winpage = 0; winpage < num_windows; winpage ++) { 01006 // Draw header... 01007 StartPage(dialog.hDC); 01008 01009 fl_font(FL_HELVETICA_BOLD, fontsize); 01010 fl_color(0, 0, 0); 01011 01012 fl_draw(basename, 0, fontsize); 01013 01014 fl_draw(date, (width - (int)fl_width(date)) / 2, fontsize); 01015 01016 sprintf(buffer, "%d/%d", winpage + 1, num_windows); 01017 fl_draw(buffer, width - (int)fl_width(buffer), fontsize); 01018 01019 // Get window image... 01020 uchar *pixels; // Window image data 01021 int w, h; // Window image dimensions 01022 int ww, hh; // Scaled size 01023 int ulx, uly; // Upper-lefthand corner 01024 Fl_Window *win; // Window widget 01025 BITMAPINFO info; // Bitmap information 01026 01027 win = (Fl_Window *)(windows[winpage]->o); 01028 pixels = windows[winpage]->read_image(w, h); 01029 01030 // Swap colors: FLTK uses R-G-B --> Windows GDI uses B-G-R 01031 01032 { uchar *p = pixels; 01033 for (int i=0; i<w*h; i++, p+=3) { 01034 uchar temp = p[0]; p[0] = p[2]; p[2] = temp; 01035 } 01036 } 01037 01038 // Figure out the window size, first at 100 PPI and then scaled 01039 // down if that is too big... 01040 ww = w * xdpi / 100; 01041 hh = h * ydpi / 100; 01042 01043 if (ww > width) { 01044 ww = width; 01045 hh = h * ww * ydpi / xdpi / w; 01046 } 01047 01048 if (hh > (length - ydpi / 2)) { 01049 hh = length - ydpi / 2; 01050 ww = w * hh / h; 01051 } 01052 01053 // Position the window in the center... 01054 ulx = (width - ww) / 2; 01055 uly = (length - hh) / 2; 01056 01057 // fl_message("winpage=%d, ulx=%d, uly=%d, ww=%d, hh=%d", 01058 // winpage, ulx, uly, ww, hh); 01059 01060 // Draw a simulated window border... 01061 int xborder = 4 * ww / w; 01062 int yborder = 4 * hh / h; 01063 01064 win_box(ulx - xborder, uly - 5 * yborder, 01065 ww + 2 * xborder, hh + 6 * yborder); 01066 01067 fl_color(0, 0, 255); 01068 fl_rectf(ulx, uly - 4 * yborder, ww, 4 * yborder); 01069 01070 fl_font(FL_HELVETICA_BOLD, 2 * yborder); 01071 fl_color(255, 255, 255); 01072 fl_draw(win->label() ? win->label() : "Window", 01073 ulx + xborder, uly - 3 * yborder); 01074 01075 int x = ulx + ww - 4 * xborder; 01076 01077 win_box(x, uly - 4 * yborder, 4 * xborder, 4 * yborder); 01078 fl_color(0, 0, 0); 01079 fl_line(x + xborder, uly - yborder, 01080 x + 3 * xborder, uly - 3 * yborder); 01081 fl_line(x + xborder, uly - 3 * yborder, 01082 x + 3 * xborder, uly - yborder); 01083 x -= 4 * xborder; 01084 01085 if (win->resizable()) { 01086 win_box(x, uly - 4 * yborder, 4 * xborder, 4 * yborder); 01087 fl_color(0, 0, 0); 01088 fl_rect(x + xborder, uly - 3 * yborder, 2 * xborder, 2 * yborder); 01089 x -= 4 * xborder; 01090 } 01091 01092 if (!win->modal()) { 01093 win_box(x, uly - 4 * yborder, 4 * xborder, 4 * yborder); 01094 fl_color(0, 0, 0); 01095 fl_line(x + xborder, uly - yborder, x + 3 * xborder, uly - yborder); 01096 x -= 4 * xborder; 01097 } 01098 01099 // Color image... 01100 memset(&info, 0, sizeof(info)); 01101 info.bmiHeader.biSize = sizeof(info); 01102 info.bmiHeader.biWidth = w; 01103 info.bmiHeader.biHeight = 1; 01104 info.bmiHeader.biPlanes = 1; 01105 info.bmiHeader.biBitCount = 24; 01106 info.bmiHeader.biCompression = BI_RGB; 01107 01108 for (int y = 0; y < h; y ++) { 01109 StretchDIBits(dialog.hDC, ulx, uly + y * hh / h, ww, (hh + h - 1) / h, 0, 0, w, 1, 01110 pixels + y * w * 3, &info, DIB_RGB_COLORS, SRCCOPY); 01111 } 01112 01113 delete[] pixels; 01114 01115 // Show the page... 01116 EndPage(dialog.hDC); 01117 } 01118 01119 // Finish up... 01120 EndDoc(dialog.hDC); 01121 01122 fl_gc = save_dc; 01123 fl_window = save_win; 01124 fl_pop_clip(); 01125 01126 // Free the print DC and return... 01127 DeleteDC(dialog.hDC); 01128 } 01129 #else 01130 // Load and show the print dialog... 01131 void print_menu_cb(Fl_Widget *, void *) { 01132 if (!print_panel) make_print_panel(); 01133 01134 print_load(); 01135 01136 print_selection->deactivate(); 01137 01138 for (Fl_Type *t = Fl_Type::first; t; t = t->next) { 01139 if (t->selected && t->is_window()) { 01140 print_selection->activate(); 01141 break; 01142 } 01143 } 01144 01145 print_all->setonly(); 01146 print_all->do_callback(); 01147 01148 print_panel->show(); 01149 } 01150 01151 // Quote a string for PostScript printing 01152 static const char *ps_string(const char *s) { 01153 char *bufptr; 01154 static char buffer[FL_PATH_MAX]; 01155 01156 01157 if (!s) { 01158 buffer[0] = '\0'; 01159 } else { 01160 for (bufptr = buffer; bufptr < (buffer + sizeof(buffer) - 3) && *s;) { 01161 if (*s == '(' || *s == ')' || *s == '\\') *bufptr++ = '\\'; 01162 *bufptr++ = *s++; 01163 } 01164 01165 *bufptr = '\0'; 01166 } 01167 01168 return (buffer); 01169 } 01170 01171 // Actually print... 01172 void print_cb(Fl_Return_Button *, void *) { 01173 FILE *outfile; // Output file or pipe to print command 01174 char command[1024]; // Print command 01175 int copies; // Collated copies 01176 int first, last; // First and last page 01177 int page; // Current page 01178 int winpage; // Current window page 01179 int num_pages; // Number of pages 01180 Fl_Type *t; // Current widget 01181 int num_windows; // Number of windows 01182 Fl_Window_Type *windows[1000]; // Windows to print 01183 01184 // Show progress, deactivate controls... 01185 print_panel_controls->deactivate(); 01186 print_progress->show(); 01187 01188 // Figure out how many pages we'll have to print... 01189 if (print_collate_button->value()) copies = (int)print_copies->value(); 01190 else copies = 1; 01191 01192 if (print_pages->value()) { 01193 // Get from and to page numbers... 01194 if ((first = atoi(print_from->value())) < 1) first = 1; 01195 if ((last = atoi(print_to->value())) < 1) last = 1000; 01196 01197 if (first > last) { 01198 // Swap first/last page 01199 page = first; 01200 first = last; 01201 last = page; 01202 } 01203 } else { 01204 // Print everything... 01205 first = 1; 01206 last = 1000; 01207 } 01208 01209 for (t = Fl_Type::first, num_windows = 0, winpage = 0; t; t = t->next) { 01210 if (t->is_window()) { 01211 winpage ++; 01212 windows[num_windows] = (Fl_Window_Type *)t; 01213 01214 if (print_all->value()) num_windows ++; 01215 else if (print_pages->value() && winpage >= first && 01216 winpage <= last) num_windows ++; 01217 else if (print_selection->value() && t->selected) num_windows ++; 01218 } 01219 } 01220 01221 num_pages = num_windows * copies; 01222 01223 print_progress->minimum(0); 01224 print_progress->maximum(num_pages); 01225 print_progress->value(0); 01226 Fl::check(); 01227 01228 // Get the base filename... 01229 const char *basename = strrchr(filename, '/'); 01230 if (basename) basename ++; 01231 else basename = filename; 01232 01233 // Open the print stream... 01234 if (print_choice->value()) { 01235 // Pipe the output into the lp command... 01236 const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); 01237 01238 snprintf(command, sizeof(command), "lp -s -d %s -n %.0f -t '%s' -o media=%s", 01239 printer, print_collate_button->value() ? 1.0 : print_copies->value(), 01240 basename, print_page_size->text(print_page_size->value())); 01241 outfile = popen(command, "w"); 01242 } else { 01243 // Print to file... 01244 fl_file_chooser_ok_label("Print"); 01245 const char *outname = fl_file_chooser("Print To", "PostScript (*.ps)", NULL, 1); 01246 fl_file_chooser_ok_label(NULL); 01247 01248 if (outname && !access(outname, 0)) { 01249 if (fl_choice("The file \"%s\" already exists.\n" 01250 "Do you want to replace it?", "Cancel", 01251 "Replace", NULL, outname) == 0) outname = NULL; 01252 } 01253 01254 if (outname) outfile = fl_fopen(outname, "w"); 01255 else outfile = NULL; 01256 } 01257 01258 if (outfile) { 01259 // Figure out the page size and margins... 01260 int width, length; // Size of page 01261 int left, bottom, // Bottom lefthand corner 01262 right, top; // Top righthand corner 01263 01264 if (print_page_size->value()) { 01265 // A4 01266 width = 595; 01267 length = 842; 01268 } else { 01269 // Letter 01270 width = 612; 01271 length = 792; 01272 } 01273 01274 int output_mode; 01275 for (output_mode = 0; output_mode < 4; output_mode ++) { 01276 if (print_output_mode[output_mode]->value()) break; 01277 } 01278 01279 if (output_mode & 1) { 01280 // Landscape 01281 left = 36; 01282 bottom = 18; 01283 right = length - 36; 01284 top = width - 18; 01285 } else { 01286 // Portrait 01287 left = 18; 01288 bottom = 36; 01289 right = width - 18; 01290 top = length - 36; 01291 } 01292 01293 // Get the time and date... 01294 time_t curtime = time(NULL); 01295 struct tm *curdate = localtime(&curtime); 01296 char date[1024]; 01297 01298 strftime(date, sizeof(date), "%c", curdate); 01299 01300 // Write the prolog... 01301 fprintf(outfile, 01302 "%%!PS-Adobe-3.0\n" 01303 "%%%%BoundingBox: 18 36 %d %d\n" 01304 "%%%%Pages: %d\n" 01305 "%%%%LanguageLevel: 1\n" 01306 "%%%%DocumentData: Clean7Bit\n" 01307 "%%%%DocumentNeededResources: font Helvetica-Bold\n" 01308 "%%%%Creator: FLUID %.4f\n" 01309 "%%%%CreationDate: %s\n" 01310 "%%%%Title: (%s)\n" 01311 "%%%%EndComments\n" 01312 "%%%%BeginProlog\n" 01313 "%%languagelevel 1 eq {\n" 01314 " /rectfill {\n" 01315 " newpath 4 2 roll moveto dup 0 exch rlineto exch 0 rlineto\n" 01316 " neg 0 exch rlineto closepath fill\n" 01317 " } bind def\n" 01318 " /rectstroke {\n" 01319 " newpath 4 2 roll moveto dup 0 exch rlineto exch 0 rlineto\n" 01320 " neg 0 exch rlineto closepath stroke\n" 01321 " } bind def\n" 01322 "%%} if\n" 01323 "%%%%EndProlog\n" 01324 "%%%%BeginSetup\n" 01325 "%%%%BeginFeature: *PageSize %s\n" 01326 "languagelevel 1 ne {\n" 01327 " <</PageSize[%d %d]/ImagingBBox null>>setpagedevice\n" 01328 "} {\n" 01329 " %s\n" 01330 "} ifelse\n" 01331 "%%%%EndFeature\n" 01332 "%%%%EndSetup\n", 01333 width - 18, length - 36, 01334 num_pages, 01335 FL_VERSION, 01336 date, 01337 basename, 01338 print_page_size->text(print_page_size->value()), 01339 width, length, 01340 print_page_size->value() ? "a4tray" : "lettertray"); 01341 01342 // Print each of the windows... 01343 char progress[255]; // Progress text 01344 int copy; // Current copy 01345 01346 for (copy = 0, page = 0; copy < copies; copy ++) { 01347 for (winpage = 0; winpage < num_pages; winpage ++) { 01348 // Start next page... 01349 page ++; 01350 sprintf(progress, "Printing page %d/%d...", page, num_pages); 01351 print_progress->value(page); 01352 print_progress->label(progress); 01353 Fl::check(); 01354 01355 // Add common page stuff... 01356 fprintf(outfile, 01357 "%%%%Page: %d %d\n" 01358 "gsave\n", 01359 page, page); 01360 01361 if (output_mode & 1) { 01362 // Landscape... 01363 fprintf(outfile, "%d 0 translate 90 rotate\n", width); 01364 } 01365 01366 // Draw header... 01367 fprintf(outfile, 01368 "0 setgray\n" 01369 "/Helvetica-Bold findfont 14 scalefont setfont\n" 01370 "%d %d moveto (%s) show\n" 01371 "%.1f %d moveto (%s) dup stringwidth pop -0.5 mul 0 rmoveto show\n" 01372 "%d %d moveto (%d/%d) dup stringwidth pop neg 0 rmoveto show\n", 01373 left, top - 15, ps_string(basename), 01374 0.5 * (left + right), top - 15, date, 01375 right, top - 15, winpage + 1, num_windows); 01376 01377 // Get window image... 01378 uchar *pixels; // Window image data 01379 int w, h; // Window image dimensions 01380 float ww, hh; // Scaled size 01381 float border; // Width of 1 pixel 01382 float llx, lly, // Lower-lefthand corner 01383 urx, ury; // Upper-righthand corner 01384 Fl_Window *win; // Window widget 01385 01386 win = (Fl_Window *)(windows[winpage]->o); 01387 pixels = windows[winpage]->read_image(w, h); 01388 01389 // Figure out the window size, first at 100 PPI and then scaled 01390 // down if that is too big... 01391 ww = w * 72.0 / 100.0; 01392 hh = h * 72.0 / 100.0; 01393 01394 if (ww > (right - left)) { 01395 ww = right - left; 01396 hh = h * ww / w; 01397 } 01398 01399 if (hh > (top - bottom - 36)) { 01400 hh = top - bottom; 01401 ww = w * hh / h; 01402 } 01403 01404 border = ww / w; 01405 01406 // Position the window in the center... 01407 llx = 0.5 * (right - left - ww); 01408 lly = 0.5 * (top - bottom - hh); 01409 urx = 0.5 * (right - left + ww); 01410 ury = 0.5 * (top - bottom + hh); 01411 01412 // Draw a simulated window border... 01413 fprintf(outfile, 01414 "0.75 setgray\n" // Gray background 01415 "newpath %.2f %.2f %.2f 180 90 arcn\n" // Top left 01416 "%.2f %.2f %.2f 90 0 arcn\n" // Top right 01417 "%.2f %.2f %.2f 0 -90 arcn\n" // Bottom right 01418 "%.2f %.2f %.2f -90 -180 arcn\n" // Bottom left 01419 "closepath gsave fill grestore\n" // Fill 01420 "0 setlinewidth 0 setgray stroke\n", // Outline 01421 llx, ury + 12 * border, 4 * border, 01422 urx, ury + 12 * border, 4 * border, 01423 urx, lly, 4 * border, 01424 llx, lly, 4 * border); 01425 01426 // Title bar... 01427 if (output_mode & 2) { 01428 fputs("0.25 setgray\n", outfile); 01429 } else { 01430 fputs("0.1 0.2 0.6 setrgbcolor\n", outfile); 01431 } 01432 01433 fprintf(outfile, "%.2f %.2f %.2f %.2f rectfill\n", 01434 llx + 12 * border, ury, 01435 ww - (24 + 16 * (!win->modal() || win->resizable()) + 01436 16 * (!win->modal() && win->resizable())) * border, 01437 16 * border); 01438 01439 if (win->resizable()) { 01440 fprintf(outfile, 01441 "%.2f %.2f %.2f -90 -180 arcn\n" // Bottom left 01442 "0 %.2f rlineto %.2f 0 rlineto 0 -%.2f rlineto closepath fill\n" 01443 "%.2f %.2f %.2f 0 -90 arcn\n" // Bottom right 01444 "-%.2f 0 rlineto 0 %.2f rlineto %.2f 0 rlineto closepath fill\n", 01445 llx, lly, 4 * border, 01446 12 * border, 16 * border, 16 * border, 01447 urx, lly, 4 * border, 01448 12 * border, 16 * border, 16 * border); 01449 } 01450 01451 // Inside outline and button shading... 01452 fprintf(outfile, 01453 "%.2f setlinewidth 0.5 setgray\n" 01454 "%.2f %.2f %.2f %.2f rectstroke\n" 01455 "%.2f %.2f moveto 0 %.2f rlineto\n" 01456 "%.2f %.2f moveto 0 %.2f rlineto\n", 01457 border, 01458 llx - 0.5 * border, lly - 0.5 * border, ww + border, hh + border, 01459 llx + 12 * border, ury, 16 * border, 01460 urx - 12 * border, ury, 16 * border); 01461 01462 if (!win->modal() || win->resizable()) { 01463 fprintf(outfile, "%.2f %.2f moveto 0 %.2f rlineto\n", 01464 urx - 28 * border, ury, 16 * border); 01465 } 01466 01467 if (!win->modal() && win->resizable()) { 01468 fprintf(outfile, "%.2f %.2f moveto 0 %.2f rlineto\n", 01469 urx - 44 * border, ury, 16 * border); 01470 } 01471 01472 fprintf(outfile, "%.2f %.2f moveto %.2f 0 rlineto stroke\n", 01473 llx - 3.5 * border, ury + 0.5 * border, ww + 7 * border); 01474 01475 // Button icons... 01476 fprintf(outfile, 01477 "%.2f setlinewidth 0 setgray\n" 01478 "%.2f %.2f moveto %.2f -%.2f rlineto %.2f %.2f rlineto\n" 01479 "%.2f %.2f moveto -%.2f -%.2f rlineto 0 %.2f rmoveto %.2f -%.2f rlineto\n", 01480 2 * border, 01481 llx, ury + 10 * border, 4 * border, 4 * border, 4 * border, 4 * border, 01482 urx, ury + 12 * border, 8 * border, 8 * border, 8 * border, 8 * border, 8 * border); 01483 01484 float x = urx - 16 * border; 01485 01486 if (win->resizable()) { 01487 // Maximize button 01488 fprintf(outfile, 01489 "%.2f %.2f moveto -%.2f 0 rlineto 0 -%.2f rlineto " 01490 "%.2f 0 rlineto 0 %.2f rlineto\n", 01491 x, ury + 12 * border, 8 * border, 8 * border, 01492 8 * border, 8 * border); 01493 01494 x -= 16 * border; 01495 } 01496 01497 if (!win->modal()) { 01498 // Minimize button 01499 fprintf(outfile, 01500 "%.2f %.2f moveto -%.2f 0 rlineto\n", 01501 x, ury + 4 * border, 8 * border); 01502 } 01503 01504 fputs("stroke\n", outfile); 01505 01506 if (win->label()) { 01507 // Add window title... 01508 fprintf(outfile, 01509 "1 setgray\n" 01510 "/Helvetica-Bold findfont %.2f scalefont setfont\n" 01511 "(%s) %.2f %.2f moveto show\n", 01512 12 * border, 01513 ps_string(win->label()), llx + 16 * border, ury + 4 * border); 01514 } 01515 01516 fprintf(outfile, 01517 "gsave\n" 01518 "%.2f %.2f translate %.2f %.2f scale\n", 01519 llx, ury - border, border, border); 01520 01521 if (output_mode & 2) { 01522 // Grayscale image... 01523 fprintf(outfile, 01524 "/imgdata %d string def\n" 01525 "%d %d 8[1 0 0 -1 0 1] " 01526 "{currentfile imgdata readhexstring pop} image\n", 01527 w, 01528 w, h); 01529 01530 uchar *ptr = pixels; 01531 int i, count = w * h; 01532 01533 for (i = 0; i < count; i ++, ptr += 3) { 01534 fprintf(outfile, "%02X", 01535 (31 * ptr[0] + 61 * ptr[1] + 8 * ptr[2]) / 100); 01536 if (!(i % 40)) putc('\n', outfile); 01537 } 01538 } else { 01539 // Color image... 01540 fprintf(outfile, 01541 "/imgdata %d string def\n" 01542 "%d %d 8[1 0 0 -1 0 1] " 01543 "{currentfile imgdata readhexstring pop} false 3 colorimage\n", 01544 w * 3, 01545 w, h); 01546 01547 uchar *ptr = pixels; 01548 int i, count = w * h; 01549 01550 for (i = 0; i < count; i ++, ptr += 3) { 01551 fprintf(outfile, "%02X%02X%02X", ptr[0], ptr[1], ptr[2]); 01552 if (!(i % 13)) putc('\n', outfile); 01553 } 01554 } 01555 01556 fputs("\ngrestore\n", outfile); 01557 01558 delete[] pixels; 01559 01560 // Show the page... 01561 fputs("grestore showpage\n", outfile); 01562 } 01563 } 01564 01565 // Finish up... 01566 fputs("%%EOF\n", outfile); 01567 01568 if (print_choice->value()) pclose(outfile); 01569 else fclose(outfile); 01570 } else { 01571 // Unable to print... 01572 fl_alert("Error printing: %s", strerror(errno)); 01573 } 01574 01575 // Hide progress, activate controls, hide print panel... 01576 print_panel_controls->activate(); 01577 print_progress->hide(); 01578 print_panel->hide(); 01579 } 01580 #endif // WIN32 && !__CYGWIN__ 01581 01583 01584 extern Fl_Menu_Item New_Menu[]; 01585 01586 void toggle_widgetbin_cb(Fl_Widget *, void *); 01587 void toggle_sourceview_cb(Fl_Double_Window *, void *); 01588 01589 Fl_Menu_Item Main_Menu[] = { 01590 {"&File",0,0,0,FL_SUBMENU}, 01591 {"&New...", FL_COMMAND+'n', new_cb, 0}, 01592 {"&Open...", FL_COMMAND+'o', open_cb, 0}, 01593 {"&Insert...", FL_COMMAND+'i', open_cb, (void*)1, FL_MENU_DIVIDER}, 01594 {"&Save", FL_COMMAND+'s', save_cb, 0}, 01595 {"Save &As...", FL_COMMAND+FL_SHIFT+'s', save_cb, (void*)1}, 01596 {"Sa&ve A Copy...", 0, save_cb, (void*)2}, 01597 {"Save &Template...", 0, save_template_cb}, 01598 {"&Revert...", 0, revert_cb, 0, FL_MENU_DIVIDER}, 01599 {"&Print...", FL_COMMAND+'p', print_menu_cb}, 01600 {"Write &Code...", FL_COMMAND+FL_SHIFT+'c', write_cb, 0}, 01601 {"&Write Strings...", FL_COMMAND+FL_SHIFT+'w', write_strings_cb, 0, FL_MENU_DIVIDER}, 01602 {relative_history[0], FL_COMMAND+'0', open_history_cb, absolute_history[0]}, 01603 {relative_history[1], FL_COMMAND+'1', open_history_cb, absolute_history[1]}, 01604 {relative_history[2], FL_COMMAND+'2', open_history_cb, absolute_history[2]}, 01605 {relative_history[3], FL_COMMAND+'3', open_history_cb, absolute_history[3]}, 01606 {relative_history[4], FL_COMMAND+'4', open_history_cb, absolute_history[4]}, 01607 {relative_history[5], FL_COMMAND+'5', open_history_cb, absolute_history[5]}, 01608 {relative_history[6], FL_COMMAND+'6', open_history_cb, absolute_history[6]}, 01609 {relative_history[7], FL_COMMAND+'7', open_history_cb, absolute_history[7]}, 01610 {relative_history[8], FL_COMMAND+'8', open_history_cb, absolute_history[8]}, 01611 {relative_history[9], FL_COMMAND+'9', open_history_cb, absolute_history[9], FL_MENU_DIVIDER}, 01612 {"&Quit", FL_COMMAND+'q', exit_cb}, 01613 {0}, 01614 {"&Edit",0,0,0,FL_SUBMENU}, 01615 {"&Undo", FL_COMMAND+'z', undo_cb}, 01616 {"&Redo", FL_COMMAND+FL_SHIFT+'z', redo_cb, 0, FL_MENU_DIVIDER}, 01617 {"C&ut", FL_COMMAND+'x', cut_cb}, 01618 {"&Copy", FL_COMMAND+'c', copy_cb}, 01619 {"&Paste", FL_COMMAND+'v', paste_cb}, 01620 {"Dup&licate", FL_COMMAND+'u', duplicate_cb}, 01621 {"&Delete", FL_Delete, delete_cb, 0, FL_MENU_DIVIDER}, 01622 {"Select &All", FL_COMMAND+'a', select_all_cb}, 01623 {"Select &None", FL_COMMAND+FL_SHIFT+'a', select_none_cb, 0, FL_MENU_DIVIDER}, 01624 {"Pr&operties...", FL_F+1, openwidget_cb}, 01625 {"&Sort",0,sort_cb}, 01626 {"&Earlier", FL_F+2, earlier_cb}, 01627 {"&Later", FL_F+3, later_cb}, 01628 {"&Group", FL_F+7, group_cb}, 01629 {"Ung&roup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER}, 01630 {"Hide O&verlays",FL_COMMAND+FL_SHIFT+'o',toggle_overlays}, 01631 {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb}, 01632 {"Show Source Code...",FL_ALT+FL_SHIFT+'s', (Fl_Callback*)toggle_sourceview_cb, 0, FL_MENU_DIVIDER}, 01633 {"Pro&ject Settings...",FL_ALT+'p',show_project_cb}, 01634 {"GU&I Settings...",FL_ALT+FL_SHIFT+'p',show_settings_cb,0,FL_MENU_DIVIDER}, 01635 {"Global &FLTK Settings...",FL_ALT+FL_SHIFT+'g',show_global_settings_cb}, 01636 {0}, 01637 {"&New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER}, 01638 {"&Layout",0,0,0,FL_SUBMENU}, 01639 {"&Align",0,0,0,FL_SUBMENU}, 01640 {"&Left",0,(Fl_Callback *)align_widget_cb,(void*)10}, 01641 {"&Center",0,(Fl_Callback *)align_widget_cb,(void*)11}, 01642 {"&Right",0,(Fl_Callback *)align_widget_cb,(void*)12}, 01643 {"&Top",0,(Fl_Callback *)align_widget_cb,(void*)13}, 01644 {"&Middle",0,(Fl_Callback *)align_widget_cb,(void*)14}, 01645 {"&Bottom",0,(Fl_Callback *)align_widget_cb,(void*)15}, 01646 {0}, 01647 {"&Space Evenly",0,0,0,FL_SUBMENU}, 01648 {"&Across",0,(Fl_Callback *)align_widget_cb,(void*)20}, 01649 {"&Down",0,(Fl_Callback *)align_widget_cb,(void*)21}, 01650 {0}, 01651 {"&Make Same Size",0,0,0,FL_SUBMENU}, 01652 {"&Width",0,(Fl_Callback *)align_widget_cb,(void*)30}, 01653 {"&Height",0,(Fl_Callback *)align_widget_cb,(void*)31}, 01654 {"&Both",0,(Fl_Callback *)align_widget_cb,(void*)32}, 01655 {0}, 01656 {"&Center In Group",0,0,0,FL_SUBMENU}, 01657 {"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40}, 01658 {"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41}, 01659 {0}, 01660 {"Set &Widget Size",0,0,0,FL_SUBMENU|FL_MENU_DIVIDER}, 01661 {"&Tiny",FL_ALT+'1',(Fl_Callback *)widget_size_cb,(void*)8,0,FL_NORMAL_LABEL,FL_HELVETICA,8}, 01662 {"&Small",FL_ALT+'2',(Fl_Callback *)widget_size_cb,(void*)11,0,FL_NORMAL_LABEL,FL_HELVETICA,11}, 01663 {"&Normal",FL_ALT+'3',(Fl_Callback *)widget_size_cb,(void*)14,0,FL_NORMAL_LABEL,FL_HELVETICA,14}, 01664 {"&Medium",FL_ALT+'4',(Fl_Callback *)widget_size_cb,(void*)18,0,FL_NORMAL_LABEL,FL_HELVETICA,18}, 01665 {"&Large",FL_ALT+'5',(Fl_Callback *)widget_size_cb,(void*)24,0,FL_NORMAL_LABEL,FL_HELVETICA,24}, 01666 {"&Huge",FL_ALT+'6',(Fl_Callback *)widget_size_cb,(void*)32,0,FL_NORMAL_LABEL,FL_HELVETICA,32}, 01667 {0}, 01668 {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb}, 01669 {0}, 01670 {"&Shell",0,0,0,FL_SUBMENU}, 01671 {"Execute &Command...",FL_ALT+'x',(Fl_Callback *)show_shell_window}, 01672 {"Execute &Again...",FL_ALT+'g',(Fl_Callback *)do_shell_command}, 01673 {0}, 01674 {"&Help",0,0,0,FL_SUBMENU}, 01675 {"&Rapid development with FLUID...",0,help_cb}, 01676 {"&FLTK Programmers Manual...",0,manual_cb, 0, FL_MENU_DIVIDER}, 01677 {"&About FLUID...",0,about_cb}, 01678 {0}, 01679 {0}}; 01680 01681 #define BROWSERWIDTH 300 01682 #define BROWSERHEIGHT 500 01683 #define WINWIDTH 300 01684 #define MENUHEIGHT 25 01685 #define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT) 01686 01687 extern void fill_in_New_Menu(); 01688 01689 void scheme_cb(Fl_Choice *, void *) { 01690 if (compile_only) 01691 return; 01692 01693 switch (scheme_choice->value()) { 01694 case 0 : // Default 01695 Fl::scheme(NULL); 01696 break; 01697 case 1 : // None 01698 Fl::scheme("none"); 01699 break; 01700 case 2 : // Plastic 01701 Fl::scheme("plastic"); 01702 break; 01703 case 3 : // GTK+ 01704 Fl::scheme("gtk+"); 01705 break; 01706 } 01707 01708 fluid_prefs.set("scheme", scheme_choice->value()); 01709 } 01710 01711 void toggle_widgetbin_cb(Fl_Widget *, void *) { 01712 if (!widgetbin_panel) { 01713 make_widgetbin(); 01714 if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return; 01715 } 01716 01717 if (widgetbin_panel->visible()) { 01718 widgetbin_panel->hide(); 01719 widgetbin_item->label("Show Widget &Bin..."); 01720 } else { 01721 widgetbin_panel->show(); 01722 widgetbin_item->label("Hide Widget &Bin"); 01723 } 01724 } 01725 01726 01727 void toggle_sourceview_cb(Fl_Double_Window *, void *) { 01728 if (!sourceview_panel) { 01729 make_sourceview(); 01730 sourceview_panel->callback((Fl_Callback*)toggle_sourceview_cb); 01731 Fl_Preferences svp(fluid_prefs, "sourceview"); 01732 int autorefresh; 01733 svp.get("autorefresh", autorefresh, 1); 01734 sv_autorefresh->value(autorefresh); 01735 int autoposition; 01736 svp.get("autoposition", autoposition, 1); 01737 sv_autoposition->value(autoposition); 01738 int tab; 01739 svp.get("tab", tab, 0); 01740 if (tab>=0 && tab<sv_tab->children()) sv_tab->value(sv_tab->child(tab)); 01741 if (!position_window(sourceview_panel,"sourceview_pos", 0, 320, 120, 550, 500)) return; 01742 } 01743 01744 if (sourceview_panel->visible()) { 01745 sourceview_panel->hide(); 01746 sourceview_item->label("Show Source Code..."); 01747 } else { 01748 sourceview_panel->show(); 01749 sourceview_item->label("Hide Source Code..."); 01750 update_sourceview_cb(0,0); 01751 } 01752 } 01753 01754 void toggle_sourceview_b_cb(Fl_Button*, void *) { 01755 toggle_sourceview_cb(0,0); 01756 } 01757 01758 void make_main_window() { 01759 if (!compile_only) { 01760 fluid_prefs.get("snap", snap, 1); 01761 fluid_prefs.get("gridx", gridx, 5); 01762 fluid_prefs.get("gridy", gridy, 5); 01763 fluid_prefs.get("show_guides", show_guides, 0); 01764 fluid_prefs.get("widget_size", Fl_Widget_Type::default_size, 14); 01765 fluid_prefs.get("show_comments", show_comments, 1); 01766 make_layout_window(); 01767 make_shell_window(); 01768 } 01769 01770 if (!main_window) { 01771 Fl_Widget *o; 01772 main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid"); 01773 main_window->box(FL_NO_BOX); 01774 o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT); 01775 o->box(FL_FLAT_BOX); 01776 o->tooltip("Double-click to view or change an item."); 01777 main_window->resizable(o); 01778 main_menubar = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT); 01779 main_menubar->menu(Main_Menu); 01780 // quick access to all dynamic menu items 01781 save_item = (Fl_Menu_Item*)main_menubar->find_item(save_cb); 01782 history_item = (Fl_Menu_Item*)main_menubar->find_item(open_history_cb); 01783 widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb); 01784 sourceview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_sourceview_cb); 01785 main_menubar->global(); 01786 fill_in_New_Menu(); 01787 main_window->end(); 01788 } 01789 01790 if (!compile_only) { 01791 load_history(); 01792 make_settings_window(); 01793 make_global_settings_window(); 01794 } 01795 } 01796 01797 // Load file history from preferences... 01798 void load_history() { 01799 int i; // Looping var 01800 int max_files; 01801 01802 01803 fluid_prefs.get("recent_files", max_files, 5); 01804 if (max_files > 10) max_files = 10; 01805 01806 for (i = 0; i < max_files; i ++) { 01807 fluid_prefs.get( Fl_Preferences::Name("file%d", i), absolute_history[i], "", sizeof(absolute_history[i])); 01808 if (absolute_history[i][0]) { 01809 // Make a relative version of the filename for the menu... 01810 fl_filename_relative(relative_history[i], sizeof(relative_history[i]), 01811 absolute_history[i]); 01812 01813 if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; 01814 else history_item[i].flags = 0; 01815 } else break; 01816 } 01817 01818 for (; i < 10; i ++) { 01819 if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; 01820 history_item[i].hide(); 01821 } 01822 } 01823 01824 // Update file history from preferences... 01825 void update_history(const char *flname) { 01826 int i; // Looping var 01827 char absolute[FL_PATH_MAX]; 01828 int max_files; 01829 01830 01831 fluid_prefs.get("recent_files", max_files, 5); 01832 if (max_files > 10) max_files = 10; 01833 01834 fl_filename_absolute(absolute, sizeof(absolute), flname); 01835 01836 for (i = 0; i < max_files; i ++) 01837 #if defined(WIN32) || defined(__APPLE__) 01838 if (!strcasecmp(absolute, absolute_history[i])) break; 01839 #else 01840 if (!strcmp(absolute, absolute_history[i])) break; 01841 #endif // WIN32 || __APPLE__ 01842 01843 if (i == 0) return; 01844 01845 if (i >= max_files) i = max_files - 1; 01846 01847 // Move the other flnames down in the list... 01848 memmove(absolute_history + 1, absolute_history, 01849 i * sizeof(absolute_history[0])); 01850 memmove(relative_history + 1, relative_history, 01851 i * sizeof(relative_history[0])); 01852 01853 // Put the new file at the top... 01854 strlcpy(absolute_history[0], absolute, sizeof(absolute_history[0])); 01855 01856 fl_filename_relative(relative_history[0], sizeof(relative_history[0]), 01857 absolute_history[0]); 01858 01859 // Update the menu items as needed... 01860 for (i = 0; i < max_files; i ++) { 01861 fluid_prefs.set( Fl_Preferences::Name("file%d", i), absolute_history[i]); 01862 if (absolute_history[i][0]) { 01863 if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; 01864 else history_item[i].flags = 0; 01865 } else break; 01866 } 01867 01868 for (; i < 10; i ++) { 01869 fluid_prefs.set( Fl_Preferences::Name("file%d", i), ""); 01870 if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; 01871 history_item[i].hide(); 01872 } 01873 } 01874 01875 // ********** portable process class definition ********** 01876 01877 class Fl_Process { 01878 public: 01879 // construction / destruction 01880 Fl_Process() {_fpt= NULL;} 01881 ~Fl_Process() {if (_fpt) close();} 01882 01883 // FIXME: popen needs the utf8 equivalen fl_popen 01884 FILE * popen (const char *cmd, const char *mode="r"); 01885 //not necessary here: FILE * fl_fopen (const char *file, const char *mode="r"); 01886 int close(); 01887 01888 FILE * desc() const { return _fpt;} // non null if file is open 01889 char * get_line(char * line, size_t s) const {return _fpt ? fgets(line, s, _fpt) : NULL;} 01890 01891 #if defined(WIN32) && !defined(__CYGWIN__) 01892 protected: 01893 HANDLE pin[2], pout[2], perr[2]; 01894 char ptmode; 01895 PROCESS_INFORMATION pi; 01896 STARTUPINFO si; 01897 01898 static bool createPipe(HANDLE * h, BOOL bInheritHnd=TRUE); 01899 01900 private: 01901 FILE * freeHandles() { 01902 clean_close(pin[0]); clean_close(pin[1]); 01903 clean_close(pout[0]); clean_close(pout[1]); 01904 clean_close(perr[0]); clean_close(perr[1]); 01905 return NULL; // convenient for error management 01906 } 01907 static void clean_close(HANDLE& h); 01908 #endif 01909 01910 protected: 01911 FILE * _fpt; 01912 }; 01913 01914 #if defined(WIN32) && !defined(__CYGWIN__) 01915 bool Fl_Process::createPipe(HANDLE * h, BOOL bInheritHnd) { 01916 SECURITY_ATTRIBUTES sa; 01917 sa.nLength = sizeof(sa); 01918 sa.lpSecurityDescriptor = NULL; 01919 sa.bInheritHandle = bInheritHnd; 01920 return CreatePipe (&h[0],&h[1],&sa,0) ? true : false; 01921 } 01922 #endif 01923 // portable open process: 01924 FILE * Fl_Process::popen(const char *cmd, const char *mode) { 01925 #if defined(WIN32) && !defined(__CYGWIN__) 01926 // PRECONDITIONS 01927 if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return NULL; 01928 if (_fpt) close(); // close first before reuse 01929 01930 ptmode = *mode; 01931 pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE; 01932 // stderr to stdout wanted ? 01933 int fusion = (strstr(cmd,"2>&1") !=NULL); 01934 01935 // Create windows pipes 01936 if (!createPipe(pin) || !createPipe(pout) || (!fusion && !createPipe(perr) ) ) 01937 return freeHandles(); // error 01938 01939 // Initialize Startup Info 01940 ZeroMemory(&si, sizeof(STARTUPINFO)); 01941 si.cb = sizeof(STARTUPINFO); 01942 si.dwFlags = STARTF_USESTDHANDLES; 01943 si.hStdInput = pin[0]; 01944 si.hStdOutput = pout[1]; 01945 si.hStdError = fusion ? pout[1] : perr [1]; 01946 01947 if ( CreateProcess(NULL, (LPTSTR) cmd,NULL,NULL,TRUE, 01948 DETACHED_PROCESS,NULL,NULL, &si, &pi)) { 01949 // don't need theses handles inherited by child process: 01950 clean_close(pin[0]); clean_close(pout[1]); clean_close(perr[1]); 01951 HANDLE & h = *mode == 'r' ? pout[0] : pin[1]; 01952 _fpt = _fdopen(_open_osfhandle((fl_intptr_t) h,_O_BINARY),mode); 01953 h= INVALID_HANDLE_VALUE; // reset the handle pointer that is shared 01954 // with _fpt so we don't free it twice 01955 } 01956 01957 if (!_fpt) freeHandles(); 01958 return _fpt; 01959 #else 01960 _fpt=::popen(cmd,mode); 01961 return _fpt; 01962 #endif 01963 } 01964 01965 int Fl_Process::close() { 01966 #if defined(WIN32) && !defined(__CYGWIN__) 01967 if (_fpt) { 01968 fclose(_fpt); 01969 clean_close(perr[0]); 01970 clean_close(pin[1]); 01971 clean_close(pout[0]); 01972 _fpt = NULL; 01973 return 0; 01974 } 01975 return -1; 01976 #else 01977 int ret = ::pclose(_fpt); 01978 _fpt=NULL; 01979 return ret; 01980 #endif 01981 } 01982 01983 #if defined(WIN32) && !defined(__CYGWIN__) 01984 void Fl_Process::clean_close(HANDLE& h) { 01985 if (h!= INVALID_HANDLE_VALUE) CloseHandle(h); 01986 h = INVALID_HANDLE_VALUE; 01987 } 01988 #endif 01989 // ********** Fl_Process class end ********** 01990 01991 static Fl_Process s_proc; 01992 01993 // Shell command support... 01994 01995 static bool prepare_shell_command(const char * &command) { // common pre-shell command code all platforms 01996 shell_window->hide(); 01997 if (s_proc.desc()) { 01998 fl_alert("Previous shell command still running!"); 01999 return false; 02000 } 02001 if ((command = shell_command_input->value()) == NULL || !*command) { 02002 fl_alert("No shell command entered!"); 02003 return false; 02004 } 02005 if (shell_savefl_button->value()) { 02006 save_cb(0, 0); 02007 } 02008 if (shell_writecode_button->value()) { 02009 compile_only = 1; 02010 write_cb(0, 0); 02011 compile_only = 0; 02012 } 02013 if (shell_writemsgs_button->value()) { 02014 compile_only = 1; 02015 write_strings_cb(0, 0); 02016 compile_only = 0; 02017 } 02018 return true; 02019 } 02020 02021 #if !defined(__MWERKS__) 02022 // Support the full piped shell command... 02023 void 02024 shell_pipe_cb(int, void*) { 02025 char line[1024]=""; // Line from command output... 02026 02027 if (s_proc.get_line(line, sizeof(line)) != NULL) { 02028 // Add the line to the output list... 02029 shell_run_buffer->append(line); 02030 } else { 02031 // End of file; tell the parent... 02032 Fl::remove_fd(fileno(s_proc.desc())); 02033 s_proc.close(); 02034 shell_run_buffer->append("... END SHELL COMMAND ...\n"); 02035 } 02036 02037 shell_run_display->scroll(shell_run_display->count_lines(0, 02038 shell_run_buffer->length(), 1), 0); 02039 } 02040 02041 void 02042 do_shell_command(Fl_Return_Button*, void*) { 02043 const char *command=NULL; // Command to run 02044 02045 if (!prepare_shell_command(command)) return; 02046 02047 // Show the output window and clear things... 02048 shell_run_buffer->text(""); 02049 shell_run_buffer->append(command); 02050 shell_run_buffer->append("\n"); 02051 shell_run_window->label("Shell Command Running..."); 02052 02053 if (s_proc.popen((char *)command) == NULL) { 02054 fl_alert("Unable to run shell command: %s", strerror(errno)); 02055 return; 02056 } 02057 02058 shell_run_button->deactivate(); 02059 shell_run_window->hotspot(shell_run_display); 02060 shell_run_window->show(); 02061 02062 Fl::add_fd(fileno(s_proc.desc()), shell_pipe_cb); 02063 02064 while (s_proc.desc()) Fl::wait(); 02065 02066 shell_run_button->activate(); 02067 shell_run_window->label("Shell Command Complete"); 02068 fl_beep(); 02069 02070 while (shell_run_window->shown()) Fl::wait(); 02071 } 02072 #else 02073 // Just do basic shell command stuff, no status window... 02074 void 02075 do_shell_command(Fl_Return_Button*, void*) { 02076 const char *command; // Command to run 02077 int status; // Status from command... 02078 02079 if (!prepare_shell_command(command)) return; 02080 02081 if ((status = system(command)) != 0) { 02082 fl_alert("Shell command returned status %d!", status); 02083 } else if (completion_button->value()) { 02084 fl_message("Shell command completed successfully!"); 02085 } 02086 } 02087 #endif // !__MWERKS__ 02088 02089 void 02090 show_shell_window() { 02091 shell_window->hotspot(shell_command_input); 02092 shell_window->show(); 02093 } 02094 02095 void set_filename(const char *c) { 02096 if (filename) free((void *)filename); 02097 filename = c ? strdup(c) : NULL; 02098 02099 if (filename) update_history(filename); 02100 02101 set_modflag(modflag); 02102 } 02103 02104 // 02105 // The Source View system offers an immediate preview of the code 02106 // files that will be generated by FLUID. It also marks the code 02107 // generated for the last selected item in the header and the source 02108 // file. 02109 // 02110 // Can we patent this? ;-) - Matt, mm@matthiasm.com 02111 // 02112 02113 // 02114 // Update the header and source code highlighting depending on the 02115 // currently selected object 02116 // 02117 void update_sourceview_position() 02118 { 02119 if (!sourceview_panel || !sourceview_panel->visible()) 02120 return; 02121 if (sv_autoposition->value()==0) 02122 return; 02123 if (sourceview_panel && sourceview_panel->visible() && Fl_Type::current) { 02124 int pos0, pos1; 02125 if (sv_source->visible_r()) { 02126 pos0 = Fl_Type::current->code_position; 02127 pos1 = Fl_Type::current->code_position_end; 02128 if (pos0>=0) { 02129 if (pos1<pos0) 02130 pos1 = pos0; 02131 sv_source->buffer()->highlight(pos0, pos1); 02132 int line = sv_source->buffer()->count_lines(0, pos0); 02133 sv_source->scroll(line, 0); 02134 } 02135 } 02136 if (sv_header->visible_r()) { 02137 pos0 = Fl_Type::current->header_position; 02138 pos1 = Fl_Type::current->header_position_end; 02139 if (pos0>=0) { 02140 if (pos1<pos0) 02141 pos1 = pos0; 02142 sv_header->buffer()->highlight(pos0, pos1); 02143 int line = sv_header->buffer()->count_lines(0, pos0); 02144 sv_header->scroll(line, 0); 02145 } 02146 } 02147 } 02148 } 02149 02150 void update_sourceview_position_cb(Fl_Tabs*, void*) 02151 { 02152 update_sourceview_position(); 02153 } 02154 02155 static char *sv_source_filename = 0; 02156 static char *sv_header_filename = 0; 02157 02158 // 02159 // Generate a header and source file in a temporary directory and 02160 // load those into the Code Viewer widgets. 02161 // 02162 void update_sourceview_cb(Fl_Button*, void*) 02163 { 02164 if (!sourceview_panel || !sourceview_panel->visible()) 02165 return; 02166 // generate space for the source and header file filenames 02167 if (!sv_source_filename) { 02168 sv_source_filename = (char*)malloc(FL_PATH_MAX); 02169 fluid_prefs.getUserdataPath(sv_source_filename, FL_PATH_MAX); 02170 strlcat(sv_source_filename, "source_view_tmp.cxx", FL_PATH_MAX); 02171 } 02172 if (!sv_header_filename) { 02173 sv_header_filename = (char*)malloc(FL_PATH_MAX); 02174 fluid_prefs.getUserdataPath(sv_header_filename, FL_PATH_MAX); 02175 strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX); 02176 } 02177 02178 strlcpy(i18n_program, fl_filename_name(sv_source_filename), sizeof(i18n_program)); 02179 fl_filename_setext(i18n_program, sizeof(i18n_program), ""); 02180 const char *code_file_name_bak = code_file_name; 02181 code_file_name = sv_source_filename; 02182 const char *header_file_name_bak = header_file_name; 02183 header_file_name = sv_header_filename; 02184 02185 // generate the code and load the files 02186 write_sourceview = 1; 02187 // generate files 02188 if (write_code(sv_source_filename, sv_header_filename)) 02189 { 02190 // load file into source editor 02191 int pos = sv_source->top_line(); 02192 sv_source->buffer()->loadfile(sv_source_filename); 02193 sv_source->scroll(pos, 0); 02194 // load file into header editor 02195 pos = sv_header->top_line(); 02196 sv_header->buffer()->loadfile(sv_header_filename); 02197 sv_header->scroll(pos, 0); 02198 // update the source code highlighting 02199 update_sourceview_position(); 02200 } 02201 write_sourceview = 0; 02202 02203 code_file_name = code_file_name_bak; 02204 header_file_name = header_file_name_bak; 02205 } 02206 02207 void update_sourceview_timer(void*) 02208 { 02209 update_sourceview_cb(0,0); 02210 } 02211 02212 // Set the "modified" flag and update the title of the main window... 02213 void set_modflag(int mf) { 02214 const char *basename; 02215 static char title[FL_PATH_MAX]; 02216 02217 modflag = mf; 02218 02219 if (main_window) { 02220 if (!filename) basename = "Untitled.fl"; 02221 else if ((basename = strrchr(filename, '/')) != NULL) basename ++; 02222 #if defined(WIN32) || defined(__EMX__) 02223 else if ((basename = strrchr(filename, '\\')) != NULL) basename ++; 02224 #endif // WIN32 || __EMX__ 02225 else basename = filename; 02226 02227 if (modflag) { 02228 snprintf(title, sizeof(title), "%s (modified)", basename); 02229 main_window->label(title); 02230 } else main_window->label(basename); 02231 } 02232 // if the UI was modified in any way, update the Source View panel 02233 if (sourceview_panel && sourceview_panel->visible() && sv_autorefresh->value()) 02234 { 02235 // we will only update ealiest 0.5 seconds after the last change, and only 02236 // if no other change was made, so dragging a widget will not generate any 02237 // CPU load 02238 Fl::remove_timeout(update_sourceview_timer, 0); 02239 Fl::add_timeout(0.5, update_sourceview_timer, 0); 02240 } 02241 02242 // Enable/disable the Save menu item... 02243 if (modflag) save_item->activate(); 02244 else save_item->deactivate(); 02245 } 02246 02248 02249 static int arg(int argc, char** argv, int& i) { 02250 if (argv[i][1] == 'c' && !argv[i][2]) {compile_only = 1; i++; return 1;} 02251 if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) {compile_only = 1; compile_strings = 1; i++; return 1;} 02252 if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { 02253 code_file_name = argv[i+1]; 02254 code_file_set = 1; 02255 i += 2; 02256 return 2; 02257 } 02258 if (argv[i][1] == 'h' && !argv[i][2]) { 02259 header_file_name = argv[i+1]; 02260 header_file_set = 1; 02261 i += 2; 02262 return 2; 02263 } 02264 Fl_Plugin_Manager pm("commandline"); 02265 int j, n = pm.plugins(); 02266 for (j=0; j<n; j++) { 02267 Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(j); 02268 int r = pi->arg(argc, argv, i); 02269 if (r) return r; 02270 } 02271 return 0; 02272 } 02273 02274 #if ! (defined(WIN32) && !defined (__CYGWIN__)) 02275 02276 int quit_flag = 0; 02277 #include <signal.h> 02278 #ifdef _sigargs 02279 #define SIGARG _sigargs 02280 #else 02281 #ifdef __sigargs 02282 #define SIGARG __sigargs 02283 #else 02284 #define SIGARG int // you may need to fix this for older systems 02285 #endif 02286 #endif 02287 02288 extern "C" { 02289 static void sigint(SIGARG) { 02290 signal(SIGINT,sigint); 02291 quit_flag = 1; 02292 } 02293 } 02294 #endif 02295 02296 02297 int main(int argc,char **argv) { 02298 int i = 1; 02299 02300 if (!Fl::args(argc,argv,i,arg) || i < argc-1) { 02301 static const char *msg = 02302 "usage: %s <switches> name.fl\n" 02303 " -c : write .cxx and .h and exit\n" 02304 " -cs : write .cxx and .h and strings and exit\n" 02305 " -o <name> : .cxx output filename, or extension if <name> starts with '.'\n" 02306 " -h <name> : .h output filename, or extension if <name> starts with '.'\n"; 02307 int len = strlen(msg) + strlen(argv[0]) + strlen(Fl::help); 02308 Fl_Plugin_Manager pm("commandline"); 02309 int i, n = pm.plugins(); 02310 for (i=0; i<n; i++) { 02311 Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(i); 02312 if (pi) len += strlen(pi->help()); 02313 } 02314 char *buf = (char*)malloc(len+1); 02315 sprintf(buf, msg, argv[0]); 02316 for (i=0; i<n; i++) { 02317 Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(i); 02318 if (pi) strcat(buf, pi->help()); 02319 } 02320 strcat(buf, Fl::help); 02321 #ifdef _MSC_VER 02322 fl_message("%s\n", buf); 02323 #else 02324 fprintf(stderr, "%s\n", buf); 02325 #endif 02326 free(buf); 02327 return 1; 02328 } 02329 if (exit_early) 02330 exit(0); 02331 02332 const char *c = argv[i]; 02333 02334 fl_register_images(); 02335 02336 make_main_window(); 02337 02338 02339 if (c) set_filename(c); 02340 if (!compile_only) { 02341 #ifdef __APPLE__ 02342 fl_open_callback(apple_open_cb); 02343 #endif // __APPLE__ 02344 Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX)); 02345 Fl_File_Icon::load_system_icons(); 02346 main_window->callback(exit_cb); 02347 position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT ); 02348 main_window->show(argc,argv); 02349 toggle_widgetbin_cb(0,0); 02350 toggle_sourceview_cb(0,0); 02351 if (!c && openlast_button->value() && absolute_history[0][0]) { 02352 // Open previous file when no file specified... 02353 open_history_cb(0, absolute_history[0]); 02354 } 02355 } 02356 undo_suspend(); 02357 if (c && !read_file(c,0)) { 02358 if (compile_only) { 02359 fprintf(stderr,"%s : %s\n", c, strerror(errno)); 02360 exit(1); 02361 } 02362 fl_message("Can't read %s: %s", c, strerror(errno)); 02363 } 02364 undo_resume(); 02365 if (compile_only) { 02366 if (compile_strings) write_strings_cb(0,0); 02367 write_cb(0,0); 02368 exit(0); 02369 } 02370 set_modflag(0); 02371 undo_clear(); 02372 #ifndef WIN32 02373 signal(SIGINT,sigint); 02374 #endif 02375 02376 grid_cb(horizontal_input, 0); // Makes sure that windows get snap params... 02377 02378 #ifdef WIN32 02379 Fl::run(); 02380 #else 02381 while (!quit_flag) Fl::wait(); 02382 02383 if (quit_flag) exit_cb(0,0); 02384 #endif // WIN32 02385 02386 undo_clear(); 02387 02388 return (0); 02389 } 02390 02391 // 02392 // End of "$Id: fluid.cxx 8202 2011-01-06 21:36:04Z matt $". 02393 //