fluid.cxx 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133
  1. //
  2. // "$Id: fluid.cxx 10113 2014-02-25 04:24:41Z greg.ercolano $"
  3. //
  4. // FLUID main entry for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2010 by Bill Spitzak and others.
  7. //
  8. // This library is free software. Distribution and use rights are outlined in
  9. // the file "COPYING" which should have been included with this file. If this
  10. // file is missing or damaged, see the license at:
  11. //
  12. // http://www.fltk.org/COPYING.php
  13. //
  14. // Please report all bugs and problems on the following page:
  15. //
  16. // http://www.fltk.org/str.php
  17. //
  18. #undef IDE_SUPPORT
  19. #include <FL/Fl.H>
  20. #include <FL/Fl_Double_Window.H>
  21. #include <FL/Fl_Box.H>
  22. #include <FL/Fl_Button.H>
  23. #include <FL/Fl_File_Icon.H>
  24. #include <FL/Fl_Help_Dialog.H>
  25. #include <FL/Fl_Hold_Browser.H>
  26. #include <FL/Fl_Menu_Bar.H>
  27. #include <FL/Fl_Input.H>
  28. #include <FL/Fl_Plugin.H>
  29. #include <FL/fl_ask.H>
  30. #include <FL/fl_draw.H>
  31. #include <FL/Fl_File_Chooser.H>
  32. #include <FL/Fl_PNG_Image.H>
  33. #include <FL/fl_message.H>
  34. #include <FL/filename.H>
  35. #include <FL/Fl_Native_File_Chooser.H>
  36. #include <FL/Fl_Printer.H>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <errno.h>
  40. #include <sys/stat.h>
  41. #include <time.h> // time(), localtime(), etc.
  42. #include "../src/flstring.h"
  43. #include "alignment_panel.h"
  44. #include "function_panel.h"
  45. #include "template_panel.h"
  46. #if defined(WIN32) && !defined(__CYGWIN__)
  47. # include <direct.h>
  48. # include <windows.h>
  49. # include <io.h>
  50. # include <fcntl.h>
  51. # include <commdlg.h>
  52. # include <FL/x.H>
  53. # ifndef __WATCOMC__
  54. // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
  55. // on Windows, which is supposed to be POSIX compliant...
  56. # define access _access
  57. # define chdir _chdir
  58. # define getcwd _getcwd
  59. # endif // !__WATCOMC__
  60. #else
  61. # include <unistd.h>
  62. #endif
  63. #ifdef __EMX__
  64. # include <X11/Xlibint.h>
  65. #endif
  66. #include "about_panel.h"
  67. #include "undo.h"
  68. #include "Fl_Type.h"
  69. extern "C"
  70. {
  71. #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
  72. # include <zlib.h>
  73. # ifdef HAVE_PNG_H
  74. # include <png.h>
  75. # else
  76. # include <libpng/png.h>
  77. # endif // HAVE_PNG_H
  78. #endif // HAVE_LIBPNG && HAVE_LIBZ
  79. }
  80. static Fl_Help_Dialog *help_dialog = 0;
  81. Fl_Preferences fluid_prefs(Fl_Preferences::USER, "fltk.org", "fluid");
  82. int gridx = 5;
  83. int gridy = 5;
  84. int snap = 1;
  85. int show_guides = 1;
  86. int show_comments = 1;
  87. int show_coredevmenus = 1;
  88. // File history info...
  89. char absolute_history[10][FL_PATH_MAX];
  90. char relative_history[10][FL_PATH_MAX];
  91. void load_history();
  92. void update_history(const char *);
  93. // Shell command support...
  94. void show_shell_window();
  95. Fl_Menu_Item *save_item = 0L;
  96. Fl_Menu_Item *history_item = 0L;
  97. Fl_Menu_Item *widgetbin_item = 0L;
  98. Fl_Menu_Item *sourceview_item = 0L;
  99. ////////////////////////////////////////////////////////////////
  100. static const char *filename;
  101. void set_filename(const char *c);
  102. void set_modflag(int mf);
  103. int modflag;
  104. static char* pwd;
  105. static char in_source_dir;
  106. void goto_source_dir() {
  107. if (in_source_dir) return;
  108. if (!filename || !*filename) return;
  109. const char *p = fl_filename_name(filename);
  110. if (p <= filename) return; // it is in the current directory
  111. char buffer[FL_PATH_MAX];
  112. strlcpy(buffer, filename, sizeof(buffer));
  113. int n = p-filename; if (n>1) n--; buffer[n] = 0;
  114. if (!pwd) {
  115. pwd = getcwd(0,FL_PATH_MAX);
  116. if (!pwd) {fprintf(stderr,"getwd : %s\n",strerror(errno)); return;}
  117. }
  118. if (chdir(buffer)<0) {fprintf(stderr, "Can't chdir to %s : %s\n",
  119. buffer, strerror(errno)); return;}
  120. in_source_dir = 1;
  121. }
  122. void leave_source_dir() {
  123. if (!in_source_dir) return;
  124. if (chdir(pwd)<0) {fprintf(stderr, "Can't chdir to %s : %s\n",
  125. pwd, strerror(errno));}
  126. in_source_dir = 0;
  127. }
  128. char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0 ) {
  129. Fl_Preferences pos(fluid_prefs, prefsName);
  130. if (prevpos_button->value()) {
  131. pos.get("x", X, X);
  132. pos.get("y", Y, Y);
  133. if ( W!=0 ) {
  134. pos.get("w", W, W);
  135. pos.get("h", H, H);
  136. w->resize( X, Y, W, H );
  137. }
  138. else
  139. w->position( X, Y );
  140. }
  141. pos.get("visible", Visible, Visible);
  142. return Visible;
  143. }
  144. void save_position(Fl_Window *w, const char *prefsName) {
  145. Fl_Preferences pos(fluid_prefs, prefsName);
  146. pos.set("x", w->x());
  147. pos.set("y", w->y());
  148. pos.set("w", w->w());
  149. pos.set("h", w->h());
  150. pos.set("visible", (int)(w->shown() && w->visible()));
  151. }
  152. Fl_Window *main_window;
  153. Fl_Menu_Bar *main_menubar;
  154. static char* cutfname(int which = 0) {
  155. static char name[2][FL_PATH_MAX];
  156. static char beenhere = 0;
  157. if (!beenhere) {
  158. beenhere = 1;
  159. fluid_prefs.getUserdataPath(name[0], sizeof(name[0]));
  160. strlcat(name[0], "cut_buffer", sizeof(name[0]));
  161. fluid_prefs.getUserdataPath(name[1], sizeof(name[1]));
  162. strlcat(name[1], "dup_buffer", sizeof(name[1]));
  163. }
  164. return name[which];
  165. }
  166. void save_cb(Fl_Widget *, void *v) {
  167. Fl_Native_File_Chooser fnfc;
  168. const char *c = filename;
  169. if (v || !c || !*c) {
  170. fnfc.title("Save To:");
  171. fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
  172. fnfc.filter("FLUID Files\t*.f[ld]");
  173. if (fnfc.show() != 0) return;
  174. c = fnfc.filename();
  175. if (!access(c, 0)) {
  176. const char *basename;
  177. if ((basename = strrchr(c, '/')) != NULL)
  178. basename ++;
  179. #if defined(WIN32) || defined(__EMX__)
  180. if ((basename = strrchr(c, '\\')) != NULL)
  181. basename ++;
  182. #endif // WIN32 || __EMX__
  183. else
  184. basename = c;
  185. if (fl_choice("The file \"%s\" already exists.\n"
  186. "Do you want to replace it?", "Cancel",
  187. "Replace", NULL, basename) == 0) return;
  188. }
  189. if (v != (void *)2) set_filename(c);
  190. }
  191. if (!write_file(c)) {
  192. fl_alert("Error writing %s: %s", c, strerror(errno));
  193. return;
  194. }
  195. if (v != (void *)2) {
  196. set_modflag(0);
  197. undo_save = undo_current;
  198. }
  199. }
  200. void save_template_cb(Fl_Widget *, void *) {
  201. // Setup the template panel...
  202. if (!template_panel) make_template_panel();
  203. template_clear();
  204. template_browser->add("New Template");
  205. template_load();
  206. template_name->show();
  207. template_name->value("");
  208. template_instance->hide();
  209. template_delete->show();
  210. template_delete->deactivate();
  211. template_submit->label("Save");
  212. template_submit->deactivate();
  213. template_panel->label("Save Template");
  214. // Show the panel and wait for the user to do something...
  215. template_panel->show();
  216. while (template_panel->shown()) Fl::wait();
  217. // Get the template name, return if it is empty...
  218. const char *c = template_name->value();
  219. if (!c || !*c) return;
  220. // Convert template name to filename_with_underscores
  221. char safename[FL_PATH_MAX], *safeptr;
  222. strlcpy(safename, c, sizeof(safename));
  223. for (safeptr = safename; *safeptr; safeptr ++) {
  224. if (isspace(*safeptr)) *safeptr = '_';
  225. }
  226. // Find the templates directory...
  227. char filename[FL_PATH_MAX];
  228. fluid_prefs.getUserdataPath(filename, sizeof(filename));
  229. strlcat(filename, "templates", sizeof(filename));
  230. #if defined(WIN32) && !defined(__CYGWIN__)
  231. if (access(filename, 0)) mkdir(filename);
  232. #else
  233. if (access(filename, 0)) mkdir(filename, 0777);
  234. #endif // WIN32 && !__CYGWIN__
  235. strlcat(filename, "/", sizeof(filename));
  236. strlcat(filename, safename, sizeof(filename));
  237. char *ext = filename + strlen(filename);
  238. if (ext >= (filename + sizeof(filename) - 5)) {
  239. fl_alert("The template name \"%s\" is too long!", c);
  240. return;
  241. }
  242. // Save the .fl file...
  243. strcpy(ext, ".fl");
  244. if (!access(filename, 0)) {
  245. if (fl_choice("The template \"%s\" already exists.\n"
  246. "Do you want to replace it?", "Cancel",
  247. "Replace", NULL, c) == 0) return;
  248. }
  249. if (!write_file(filename)) {
  250. fl_alert("Error writing %s: %s", filename, strerror(errno));
  251. return;
  252. }
  253. #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
  254. // Get the screenshot, if any...
  255. Fl_Type *t;
  256. for (t = Fl_Type::first; t; t = t->next) {
  257. // Find the first window...
  258. if (t->is_window()) break;
  259. }
  260. if (!t) return;
  261. // Grab a screenshot...
  262. Fl_Window_Type *wt = (Fl_Window_Type *)t;
  263. uchar *pixels;
  264. int w, h;
  265. if ((pixels = wt->read_image(w, h)) == NULL) return;
  266. // Save to a PNG file...
  267. strcpy(ext, ".png");
  268. FILE *fp;
  269. if ((fp = fl_fopen(filename, "wb")) == NULL) {
  270. delete[] pixels;
  271. fl_alert("Error writing %s: %s", filename, strerror(errno));
  272. return;
  273. }
  274. png_structp pptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  275. png_infop iptr = png_create_info_struct(pptr);
  276. png_bytep ptr = (png_bytep)pixels;
  277. png_init_io(pptr, fp);
  278. png_set_IHDR(pptr, iptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
  279. PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  280. png_set_sRGB(pptr, iptr, PNG_sRGB_INTENT_PERCEPTUAL);
  281. png_write_info(pptr, iptr);
  282. for (int i = h; i > 0; i --, ptr += w * 3) {
  283. png_write_row(pptr, ptr);
  284. }
  285. png_write_end(pptr, iptr);
  286. png_destroy_write_struct(&pptr, &iptr);
  287. fclose(fp);
  288. # if 0 // The original PPM output code...
  289. strcpy(ext, ".ppm");
  290. fp = fl_fopen(filename, "wb");
  291. fprintf(fp, "P6\n%d %d 255\n", w, h);
  292. fwrite(pixels, w * h, 3, fp);
  293. fclose(fp);
  294. # endif // 0
  295. delete[] pixels;
  296. #endif // HAVE_LIBPNG && HAVE_LIBZ
  297. }
  298. void revert_cb(Fl_Widget *,void *) {
  299. if (modflag) {
  300. if (!fl_choice("This user interface has been changed. Really revert?",
  301. "Cancel", "Revert", NULL)) return;
  302. }
  303. undo_suspend();
  304. if (!read_file(filename, 0)) {
  305. undo_resume();
  306. fl_message("Can't read %s: %s", filename, strerror(errno));
  307. return;
  308. }
  309. undo_resume();
  310. set_modflag(0);
  311. undo_clear();
  312. }
  313. void exit_cb(Fl_Widget *,void *) {
  314. if (modflag)
  315. switch (fl_choice("Do you want to save changes to this user\n"
  316. "interface before exiting?", "Cancel",
  317. "Save", "Don't Save"))
  318. {
  319. case 0 : /* Cancel */
  320. return;
  321. case 1 : /* Save */
  322. save_cb(NULL, NULL);
  323. if (modflag) return; // Didn't save!
  324. }
  325. save_position(main_window,"main_window_pos");
  326. if (widgetbin_panel) {
  327. save_position(widgetbin_panel,"widgetbin_pos");
  328. delete widgetbin_panel;
  329. }
  330. if (sourceview_panel) {
  331. Fl_Preferences svp(fluid_prefs, "sourceview");
  332. svp.set("autorefresh", sv_autorefresh->value());
  333. svp.set("autoposition", sv_autoposition->value());
  334. svp.set("tab", sv_tab->find(sv_tab->value()));
  335. save_position(sourceview_panel,"sourceview_pos");
  336. delete sourceview_panel;
  337. }
  338. if (about_panel)
  339. delete about_panel;
  340. if (help_dialog)
  341. delete help_dialog;
  342. undo_clear();
  343. exit(0);
  344. }
  345. extern void* const LOAD;
  346. #ifdef USE_LUA
  347. #define VM_SCRIPT_EXT ".lua"
  348. #include "widget_panel.h"
  349. #include "luacpp.h"
  350. lua::Lua *Lua = NULL;
  351. void my_lua_show_error_func(const char* error_message){
  352. fl_alert(error_message);
  353. }
  354. void my_close_script_vm(){
  355. if(Lua) delete Lua;
  356. Lua = NULL;
  357. }
  358. void my_open_script_vm(){
  359. my_close_script_vm();
  360. Lua = new lua::Lua();
  361. Lua->set_lua_error(my_lua_show_error_func);
  362. }
  363. int vm_script_preprocess_file(const char *file_name){
  364. return Lua->lua_preprocess_file(file_name);
  365. }
  366. int vm_script_loadstring(const char *script){
  367. return Lua->loadstring(script);
  368. }
  369. int vm_script_dofile(const char *file_name){
  370. return Lua->dofile(file_name);
  371. }
  372. void vm_script_gvar(const char* key, const char *value){
  373. Lua->gvar(key, value);
  374. }
  375. #endif
  376. #ifdef USE_SQUILU
  377. #define VM_SCRIPT_EXT ".nut"
  378. #include "widget_panel.h"
  379. #include "squirrel.h"
  380. #include <sqstdblob.h>
  381. #include <sqstdsystem.h>
  382. #include <sqstdio.h>
  383. #include <sqstdmath.h>
  384. #include <sqstdstring.h>
  385. #include <sqstdaux.h>
  386. HSQUIRRELVM sqvm = NULL;
  387. void sq_errorfunc(HSQUIRRELVM v,const SQChar *s,...)
  388. {
  389. SQChar buf[1024];
  390. va_list vl;
  391. va_start(vl, s);
  392. scsnprintf(buf, sizeof(buf), s, vl);
  393. va_end(vl);
  394. fl_alert(buf);
  395. }
  396. void my_close_script_vm(){
  397. if(sqvm) sq_close(sqvm);
  398. sqvm = NULL;
  399. }
  400. void my_open_script_vm(){
  401. my_close_script_vm();
  402. sqvm = sq_open(1024);
  403. sq_setprintfunc(sqvm,sq_errorfunc,sq_errorfunc);
  404. sq_pushroottable(sqvm);
  405. sqstd_register_bloblib(sqvm);
  406. sqstd_register_iolib(sqvm);
  407. sqstd_register_systemlib(sqvm);
  408. sqstd_register_mathlib(sqvm);
  409. sqstd_register_stringlib(sqvm);
  410. sq_poptop(sqvm);
  411. }
  412. int vm_script_preprocess_file(const char *file_name){
  413. int top = sq_gettop(sqvm); //saves the stack top
  414. int ret_value = -1;
  415. sq_pushstring(sqvm, _SC("preprocess_file"), -1);
  416. if(sq_getonroottable(sqvm) == SQ_OK){
  417. SQObjectType stype = sq_gettype(sqvm, -1);
  418. if(stype == OT_CLOSURE || stype == OT_NATIVECLOSURE){
  419. sq_pushroottable(sqvm);
  420. sq_pushstring(sqvm, file_name, -1);
  421. if(sq_call(sqvm, 2, SQTrue, SQFalse) == SQ_OK){
  422. if(sq_gettype(sqvm, -1) == OT_INTEGER){
  423. sq_getinteger(sqvm, -1, &ret_value);
  424. }
  425. }
  426. }
  427. }
  428. sq_settop(sqvm, top); //returns stack to it's orign
  429. return ret_value;
  430. }
  431. int vm_script_loadstring(const char *script){
  432. SQInteger top = sq_gettop(sqvm);
  433. int result = sq_compilebuffer(sqvm, script, strlen(script), "script", SQFalse);
  434. sq_settop(sqvm, top);
  435. return result;
  436. }
  437. int vm_script_dofile(const char *file_name){
  438. return sqstd_dofile(sqvm, file_name, SQFalse, SQFalse);
  439. }
  440. void vm_script_gvar(const char* key, const char *value){
  441. sq_pushstring(sqvm, key, -1);
  442. sq_pushstring(sqvm, value, -1);
  443. sq_setonroottable(sqvm);
  444. }
  445. #endif
  446. #if defined(USE_LUA) || defined(USE_SQUILU)
  447. #define USE_VM_SCRIPT
  448. #endif
  449. #if USE_VM_SCRIPT
  450. void get_user_vm_script_file_name(char *buf, size_t buf_size){
  451. fluid_prefs.getUserdataPath(buf, buf_size);
  452. strlcat(buf, "user_script" VM_SCRIPT_EXT, buf_size);
  453. }
  454. void get_project_vm_script_file_name(char *buf, size_t buf_size){
  455. snprintf(buf, buf_size, "%s" VM_SCRIPT_EXT, filename);
  456. }
  457. #endif
  458. void save_vm_script_cb(Fl_Button *, void *v){
  459. if (v == LOAD) return;
  460. #ifdef USE_VM_SCRIPT
  461. char uls_filename[FL_PATH_MAX];
  462. get_user_vm_script_file_name(uls_filename, sizeof(uls_filename));
  463. vm_script_user_editor->buffer()->savefile(uls_filename);
  464. get_project_vm_script_file_name(uls_filename, sizeof(uls_filename));
  465. vm_script_project_editor->buffer()->savefile(uls_filename);
  466. #endif
  467. }
  468. void check_vm_script_cb(Fl_Button *, void *v){
  469. if (v == LOAD) return;
  470. #ifdef USE_VM_SCRIPT
  471. int ret_value;
  472. if(vm_script_user_editor->visible_r())
  473. ret_value = vm_script_loadstring(vm_script_user_editor->buffer()->text());
  474. else
  475. ret_value = vm_script_loadstring(vm_script_project_editor->buffer()->text());
  476. if(!ret_value) fl_alert("Parse OK !");
  477. #endif
  478. }
  479. static bool vm_script_already_loaded = false;
  480. void reload_vm_script_cb(Fl_Button *, void *v){
  481. #ifdef USE_VM_SCRIPT
  482. //printf("reload_lua_cb\n");
  483. if (v == LOAD && vm_script_already_loaded) return;
  484. vm_script_already_loaded = true;
  485. my_open_script_vm();
  486. char uls_filename[FL_PATH_MAX];
  487. get_user_vm_script_file_name(uls_filename, sizeof(uls_filename));
  488. vm_script_user_editor->buffer()->loadfile(uls_filename);
  489. vm_script_dofile(uls_filename); //first user script
  490. get_project_vm_script_file_name(uls_filename, sizeof(uls_filename));
  491. vm_script_project_editor->buffer()->loadfile(uls_filename);
  492. vm_script_dofile(uls_filename); //then project script
  493. vm_script_gvar("PROJECT_SCRIPT_FILE_NAME", uls_filename);
  494. #endif
  495. }
  496. void vm_script_editor_cb(CodeEditor *, void *v){
  497. if (v == LOAD) return;
  498. }
  499. //#endif
  500. #ifdef __APPLE__
  501. # include <FL/x.H>
  502. void
  503. apple_open_cb(const char *c) {
  504. if (modflag) {
  505. switch (fl_choice("Do you want to save changes to this user\n"
  506. "interface before opening another one?", "Don't Save",
  507. "Save", "Cancel"))
  508. {
  509. case 0 : /* Cancel */
  510. return;
  511. case 1 : /* Save */
  512. save_cb(NULL, NULL);
  513. if (modflag) return; // Didn't save!
  514. }
  515. }
  516. const char *oldfilename;
  517. oldfilename = filename;
  518. filename = NULL;
  519. set_filename(c);
  520. undo_suspend();
  521. if (!read_file(c, 0)) {
  522. undo_resume();
  523. fl_message("Can't read %s: %s", c, strerror(errno));
  524. free((void *)filename);
  525. filename = oldfilename;
  526. if (main_window) main_window->label(filename);
  527. return;
  528. }
  529. // Loaded a file; free the old filename...
  530. set_modflag(0);
  531. undo_resume();
  532. undo_clear();
  533. if (oldfilename) free((void *)oldfilename);
  534. }
  535. #endif // __APPLE__
  536. void open_cb(Fl_Widget *, void *v) {
  537. if (!v && modflag) {
  538. switch (fl_choice("Do you want to save changes to this user\n"
  539. "interface before opening another one?", "Cancel",
  540. "Save", "Don't Save"))
  541. {
  542. case 0 : /* Cancel */
  543. return;
  544. case 1 : /* Save */
  545. save_cb(NULL, NULL);
  546. if (modflag) return; // Didn't save!
  547. }
  548. }
  549. const char *c;
  550. const char *oldfilename;
  551. Fl_Native_File_Chooser fnfc;
  552. fnfc.title("Open:");
  553. fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
  554. fnfc.filter("FLUID Files\t*.f[ld]\n");
  555. if (fnfc.show() != 0) return;
  556. c = fnfc.filename();
  557. oldfilename = filename;
  558. filename = NULL;
  559. set_filename(c);
  560. if (v != 0) undo_checkpoint();
  561. undo_suspend();
  562. if (!read_file(c, v!=0)) {
  563. undo_resume();
  564. fl_message("Can't read %s: %s", c, strerror(errno));
  565. free((void *)filename);
  566. filename = oldfilename;
  567. if (main_window) set_modflag(modflag);
  568. return;
  569. }
  570. undo_resume();
  571. if (v) {
  572. // Inserting a file; restore the original filename...
  573. free((void *)filename);
  574. filename = oldfilename;
  575. set_modflag(1);
  576. } else {
  577. // Loaded a file; free the old filename...
  578. set_modflag(0);
  579. undo_clear();
  580. if (oldfilename) free((void *)oldfilename);
  581. }
  582. #ifdef USE_VM_SCRIPT
  583. vm_script_already_loaded = false;
  584. #endif
  585. }
  586. void open_history_cb(Fl_Widget *, void *v) {
  587. if (modflag) {
  588. switch (fl_choice("Do you want to save changes to this user\n"
  589. "interface before opening another one?", "Cancel",
  590. "Save", "Don't Save"))
  591. {
  592. case 0 : /* Cancel */
  593. return;
  594. case 1 : /* Save */
  595. save_cb(NULL, NULL);
  596. if (modflag) return; // Didn't save!
  597. }
  598. }
  599. const char *oldfilename = filename;
  600. filename = NULL;
  601. set_filename((char *)v);
  602. undo_suspend();
  603. if (!read_file(filename, 0)) {
  604. undo_resume();
  605. undo_clear();
  606. fl_message("Can't read %s: %s", filename, strerror(errno));
  607. free((void *)filename);
  608. filename = oldfilename;
  609. if (main_window) main_window->label(filename);
  610. return;
  611. }
  612. set_modflag(0);
  613. undo_resume();
  614. undo_clear();
  615. if (oldfilename) free((void *)oldfilename);
  616. }
  617. void new_cb(Fl_Widget *, void *v) {
  618. // Check if the current file has been modified...
  619. if (!v && modflag) {
  620. // Yes, ask the user what to do...
  621. switch (fl_choice("Do you want to save changes to this user\n"
  622. "interface before creating a new one?", "Cancel",
  623. "Save", "Don't Save"))
  624. {
  625. case 0 : /* Cancel */
  626. return;
  627. case 1 : /* Save */
  628. save_cb(NULL, NULL);
  629. if (modflag) return; // Didn't save!
  630. }
  631. }
  632. // Setup the template panel...
  633. if (!template_panel) make_template_panel();
  634. template_clear();
  635. template_browser->add("Blank");
  636. template_load();
  637. template_name->hide();
  638. template_name->value("");
  639. template_instance->show();
  640. template_instance->deactivate();
  641. template_instance->value("");
  642. template_delete->hide();
  643. template_submit->label("New");
  644. template_submit->deactivate();
  645. template_panel->label("New");
  646. // Show the panel and wait for the user to do something...
  647. template_panel->show();
  648. while (template_panel->shown()) Fl::wait();
  649. // See if the user chose anything...
  650. int item = template_browser->value();
  651. if (item < 1) return;
  652. // Clear the current data...
  653. delete_all();
  654. set_filename(NULL);
  655. // Load the template, if any...
  656. const char *tname = (const char *)template_browser->data(item);
  657. if (tname) {
  658. // Grab the instance name...
  659. const char *iname = template_instance->value();
  660. if (iname && *iname) {
  661. // Copy the template to a temp file, then read it in...
  662. char line[1024], *ptr, *next;
  663. FILE *infile, *outfile;
  664. if ((infile = fl_fopen(tname, "r")) == NULL) {
  665. fl_alert("Error reading template file \"%s\":\n%s", tname,
  666. strerror(errno));
  667. set_modflag(0);
  668. undo_clear();
  669. return;
  670. }
  671. if ((outfile = fl_fopen(cutfname(1), "w")) == NULL) {
  672. fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1),
  673. strerror(errno));
  674. fclose(infile);
  675. set_modflag(0);
  676. undo_clear();
  677. return;
  678. }
  679. while (fgets(line, sizeof(line), infile)) {
  680. // Replace @INSTANCE@ with the instance name...
  681. for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != NULL; ptr = next + 10) {
  682. fwrite(ptr, next - ptr, 1, outfile);
  683. fputs(iname, outfile);
  684. }
  685. fputs(ptr, outfile);
  686. }
  687. fclose(infile);
  688. fclose(outfile);
  689. undo_suspend();
  690. read_file(cutfname(1), 0);
  691. unlink(cutfname(1));
  692. undo_resume();
  693. } else {
  694. // No instance name, so read the template without replacements...
  695. undo_suspend();
  696. read_file(tname, 0);
  697. undo_resume();
  698. }
  699. }
  700. set_modflag(0);
  701. undo_clear();
  702. }
  703. int exit_early = 0;
  704. int compile_only = 0;
  705. int compile_strings = 0;
  706. int header_file_set = 0;
  707. int code_file_set = 0;
  708. const char* header_file_name = ".h";
  709. const char* code_file_name = ".cxx";
  710. int i18n_type = 0;
  711. const char* i18n_include = "";
  712. const char* i18n_function = "";
  713. const char* i18n_file = "";
  714. const char* i18n_set = "";
  715. char i18n_program[FL_PATH_MAX] = "";
  716. void write_cb(Fl_Widget *, void *) {
  717. if (!filename) {
  718. save_cb(0,0);
  719. if (!filename) return;
  720. }
  721. char cname[FL_PATH_MAX];
  722. char hname[FL_PATH_MAX];
  723. strlcpy(i18n_program, fl_filename_name(filename), sizeof(i18n_program));
  724. fl_filename_setext(i18n_program, sizeof(i18n_program), "");
  725. if (*code_file_name == '.' && strchr(code_file_name, '/') == NULL) {
  726. strlcpy(cname, fl_filename_name(filename), sizeof(cname));
  727. fl_filename_setext(cname, sizeof(cname), code_file_name);
  728. } else {
  729. strlcpy(cname, code_file_name, sizeof(hname));
  730. }
  731. if (*header_file_name == '.' && strchr(header_file_name, '/') == NULL) {
  732. strlcpy(hname, fl_filename_name(filename), sizeof(hname));
  733. fl_filename_setext(hname, sizeof(hname), header_file_name);
  734. } else {
  735. strlcpy(hname, header_file_name, sizeof(hname));
  736. }
  737. if (!compile_only) goto_source_dir();
  738. int x = write_code(cname,hname);
  739. #ifdef USE_VM_SCRIPT
  740. if(x){
  741. //order is important header file first
  742. //because most lua scripts goes to the header
  743. //and itialize variables
  744. vm_script_preprocess_file(hname);
  745. vm_script_preprocess_file(cname);
  746. }
  747. #endif
  748. if (!compile_only) leave_source_dir();
  749. strlcat(cname, " and ", sizeof(cname));
  750. strlcat(cname, hname, sizeof(cname));
  751. if (compile_only) {
  752. if (!x) {fprintf(stderr,"%s : %s\n",cname,strerror(errno)); exit(1);}
  753. } else {
  754. if (!x) {
  755. fl_message("Can't write %s: %s", cname, strerror(errno));
  756. } else if (completion_button->value()) {
  757. fl_message("Wrote %s", cname);
  758. }
  759. }
  760. }
  761. void save_write_exit_cb(Fl_Widget *w, void *v) {
  762. save_cb(w,v);
  763. write_cb(w,v);
  764. exit_cb(w,v);
  765. }
  766. void write_strings_cb(Fl_Widget *, void *) {
  767. static const char *exts[] = { ".txt", ".po", ".msg" };
  768. if (!filename) {
  769. save_cb(0,0);
  770. if (!filename) return;
  771. }
  772. char sname[FL_PATH_MAX];
  773. strlcpy(sname, fl_filename_name(filename), sizeof(sname));
  774. fl_filename_setext(sname, sizeof(sname), exts[i18n_type]);
  775. if (!compile_only) goto_source_dir();
  776. int x = write_strings(sname);
  777. if (!compile_only) leave_source_dir();
  778. if (compile_only) {
  779. if (x) {fprintf(stderr,"%s : %s\n",sname,strerror(errno)); exit(1);}
  780. } else {
  781. if (x) {
  782. fl_message("Can't write %s: %s", sname, strerror(errno));
  783. } else if (completion_button->value()) {
  784. fl_message("Wrote %s", sname);
  785. }
  786. }
  787. }
  788. void openwidget_cb(Fl_Widget *, void *) {
  789. if (!Fl_Type::current) {
  790. fl_message("Please select a widget");
  791. return;
  792. }
  793. Fl_Type::current->open();
  794. }
  795. void toggle_overlays(Fl_Widget *,void *);
  796. void select_all_cb(Fl_Widget *,void *);
  797. void select_none_cb(Fl_Widget *,void *);
  798. void group_cb(Fl_Widget *, void *);
  799. void ungroup_cb(Fl_Widget *, void *);
  800. extern int pasteoffset;
  801. static int ipasteoffset;
  802. void copy_cb(Fl_Widget*, void*) {
  803. if (!Fl_Type::current) {
  804. fl_beep();
  805. return;
  806. }
  807. ipasteoffset = 10;
  808. if (!write_file(cutfname(),1)) {
  809. fl_message("Can't write %s: %s", cutfname(), strerror(errno));
  810. return;
  811. }
  812. }
  813. extern void select_only(Fl_Type *);
  814. void cut_cb(Fl_Widget *, void *) {
  815. if (!Fl_Type::current) {
  816. fl_beep();
  817. return;
  818. }
  819. if (!write_file(cutfname(),1)) {
  820. fl_message("Can't write %s: %s", cutfname(), strerror(errno));
  821. return;
  822. }
  823. undo_checkpoint();
  824. set_modflag(1);
  825. ipasteoffset = 0;
  826. Fl_Type *p = Fl_Type::current->parent;
  827. while (p && p->selected) p = p->parent;
  828. delete_all(1);
  829. if (p) select_only(p);
  830. }
  831. void delete_cb(Fl_Widget *, void *) {
  832. if (!Fl_Type::current) {
  833. fl_beep();
  834. return;
  835. }
  836. undo_checkpoint();
  837. set_modflag(1);
  838. ipasteoffset = 0;
  839. Fl_Type *p = Fl_Type::current->parent;
  840. while (p && p->selected) p = p->parent;
  841. delete_all(1);
  842. if (p) select_only(p);
  843. }
  844. extern int force_parent;
  845. void paste_cb(Fl_Widget*, void*) {
  846. //if (ipasteoffset) force_parent = 1;
  847. pasteoffset = ipasteoffset;
  848. if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx;
  849. if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy;
  850. undo_checkpoint();
  851. undo_suspend();
  852. if (!read_file(cutfname(), 1)) {
  853. fl_message("Can't read %s: %s", cutfname(), strerror(errno));
  854. }
  855. undo_resume();
  856. pasteoffset = 0;
  857. ipasteoffset += 10;
  858. force_parent = 0;
  859. }
  860. // Duplicate the selected widgets...
  861. void duplicate_cb(Fl_Widget*, void*) {
  862. if (!Fl_Type::current) {
  863. fl_beep();
  864. return;
  865. }
  866. if (!write_file(cutfname(1),1)) {
  867. fl_message("Can't write %s: %s", cutfname(1), strerror(errno));
  868. return;
  869. }
  870. pasteoffset = 0;
  871. force_parent = 1;
  872. undo_checkpoint();
  873. undo_suspend();
  874. if (!read_file(cutfname(1), 1)) {
  875. fl_message("Can't read %s: %s", cutfname(1), strerror(errno));
  876. }
  877. unlink(cutfname(1));
  878. undo_resume();
  879. force_parent = 0;
  880. }
  881. void earlier_cb(Fl_Widget*,void*);
  882. void later_cb(Fl_Widget*,void*);
  883. Fl_Type *sort(Fl_Type *parent);
  884. static void sort_cb(Fl_Widget *,void *) {
  885. sort((Fl_Type*)0);
  886. }
  887. Fl_Type *sort_by_name(Fl_Type *parent);
  888. static void sort_by_name_cb(Fl_Widget *,void *) {
  889. sort_by_name((Fl_Type*)0);
  890. }
  891. void show_project_cb(Fl_Widget *, void *);
  892. void show_grid_cb(Fl_Widget *, void *);
  893. void show_settings_cb(Fl_Widget *, void *);
  894. void show_global_settings_cb(Fl_Widget *, void *);
  895. void align_widget_cb(Fl_Widget *, long);
  896. void widget_size_cb(Fl_Widget *, long);
  897. void about_cb(Fl_Widget *, void *) {
  898. if (!about_panel) make_about_panel();
  899. about_panel->show();
  900. }
  901. void show_help(const char *name) {
  902. const char *docdir;
  903. char helpname[FL_PATH_MAX];
  904. if (!help_dialog) help_dialog = new Fl_Help_Dialog();
  905. if ((docdir = getenv("FLTK_DOCDIR")) == NULL) {
  906. #ifdef __EMX__
  907. // Doesn't make sense to have a hardcoded fallback
  908. static char fltk_docdir[FL_PATH_MAX];
  909. strlcpy(fltk_docdir, __XOS2RedirRoot("/XFree86/lib/X11/fltk/doc"),
  910. sizeof(fltk_docdir));
  911. docdir = fltk_docdir;
  912. #else
  913. docdir = FLTK_DOCDIR;
  914. #endif // __EMX__
  915. }
  916. snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name);
  917. // make sure that we can read the file
  918. FILE *f = fopen(helpname, "rb");
  919. if (f) {
  920. fclose(f);
  921. help_dialog->load(helpname);
  922. } else {
  923. // if we can not read the file, we display the canned version instead
  924. // or ask the native browser to open the page on www.fltk.org
  925. if (strcmp(name, "fluid.html")==0) {
  926. if (!Fl_Shared_Image::find("embedded:/fluid-org.png"))
  927. new Fl_PNG_Image("embedded:/fluid-org.png", fluid_org_png, sizeof(fluid_org_png));
  928. help_dialog->value
  929. (
  930. "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
  931. "<html><head><title>FLTK: Programming with FLUID</title></head><body>\n"
  932. "<h2>What is FLUID?</h2>\n"
  933. "The Fast Light User Interface Designer, or FLUID, is a graphical editor "
  934. "that is used to produce FLTK source code. FLUID edits and saves its state "
  935. "in <code>.fl</code> files. These files are text, and you can (with care) "
  936. "edit them in a text editor, perhaps to get some special effects.<p>\n"
  937. "FLUID can \"compile\" the <code>.fl</code> file into a <code>.cxx</code> "
  938. "and a <code>.h</code> file. The <code>.cxx</code> file defines all the "
  939. "objects from the <code>.fl</code> file and the <code>.h</code> file "
  940. "declares all the global ones. FLUID also supports localization "
  941. "(Internationalization) of label strings using message files and the GNU "
  942. "gettext or POSIX catgets interfaces.<p>\n"
  943. "A simple program can be made by putting all your code (including a <code>"
  944. "main()</code> function) into the <code>.fl</code> file and thus making the "
  945. "<code>.cxx</code> file a single source file to compile. Most programs are "
  946. "more complex than this, so you write other <code>.cxx</code> files that "
  947. "call the FLUID functions. These <code>.cxx</code> files must <code>"
  948. "#include</code> the <code>.h</code> file or they can <code>#include</code> "
  949. "the <code>.cxx</code> file so it still appears to be a single source file.<p>"
  950. "<img src=\"embedded:/fluid-org.png\"></p>"
  951. "<p>More information is available online at <a href="
  952. "\"http://www.fltk.org/doc-1.3/fluid.html\">http://www.fltk.org/</a>"
  953. "</body></html>"
  954. );
  955. } else if (strcmp(name, "license.html")==0) {
  956. fl_open_uri("http://www.fltk.org/doc-1.3/license.html");
  957. return;
  958. } else if (strcmp(name, "index.html")==0) {
  959. fl_open_uri("http://www.fltk.org/doc-1.3/index.html");
  960. return;
  961. } else {
  962. snprintf(helpname, sizeof(helpname), "http://www.fltk.org/%s", name);
  963. fl_open_uri(helpname);
  964. return;
  965. }
  966. }
  967. help_dialog->show();
  968. }
  969. void help_cb(Fl_Widget *, void *) {
  970. show_help("fluid.html");
  971. }
  972. void manual_cb(Fl_Widget *, void *) {
  973. show_help("index.html");
  974. }
  975. ////////////////////////////////////////////////////////////////
  976. void print_menu_cb(Fl_Widget *, void *) {
  977. int w, h, ww, hh;
  978. int frompage, topage;
  979. Fl_Type *t; // Current widget
  980. int num_windows; // Number of windows
  981. Fl_Window_Type *windows[1000]; // Windows to print
  982. int winpage; // Current window page
  983. Fl_Window *win;
  984. for (t = Fl_Type::first, num_windows = 0; t; t = t->next) {
  985. if (t->is_window()) {
  986. windows[num_windows] = (Fl_Window_Type *)t;
  987. if (!((Fl_Window*)(windows[num_windows]->o))->shown()) continue;
  988. num_windows ++;
  989. }
  990. }
  991. Fl_Printer printjob;
  992. if ( printjob.start_job(num_windows, &frompage, &topage) ) return;
  993. int pagecount = 0;
  994. for (winpage = 0; winpage < num_windows; winpage++) {
  995. float scale = 1, scale_x = 1, scale_y = 1;
  996. if (winpage+1 < frompage || winpage+1 > topage) continue;
  997. printjob.start_page();
  998. printjob.printable_rect(&w, &h);
  999. // Get the time and date...
  1000. time_t curtime = time(NULL);
  1001. struct tm *curdate = localtime(&curtime);
  1002. char date[1024];
  1003. strftime(date, sizeof(date), "%c", curdate);
  1004. fl_font(FL_HELVETICA, 12);
  1005. fl_color(FL_BLACK);
  1006. fl_draw(date, (w - (int)fl_width(date))/2, fl_height());
  1007. sprintf(date, "%d/%d", ++pagecount, topage-frompage+1);
  1008. fl_draw(date, w - (int)fl_width(date), fl_height());
  1009. // Get the base filename...
  1010. const char *basename = strrchr(filename,
  1011. #ifdef WIN32
  1012. '\\'
  1013. #else
  1014. '/'
  1015. #endif
  1016. );
  1017. if (basename) basename ++;
  1018. else basename = filename;
  1019. sprintf(date, "%s", basename);
  1020. fl_draw(date, 0, fl_height());
  1021. // print centered and scaled to fit in the page
  1022. win = (Fl_Window*)windows[winpage]->o;
  1023. ww = win->decorated_w();
  1024. if(ww > w) scale_x = float(w)/ww;
  1025. hh = win->decorated_h();
  1026. if(hh > h) scale_y = float(h)/hh;
  1027. if (scale_x < scale) scale = scale_x;
  1028. if (scale_y < scale) scale = scale_y;
  1029. if (scale < 1) {
  1030. printjob.scale(scale);
  1031. printjob.printable_rect(&w, &h);
  1032. }
  1033. printjob.origin(w/2, h/2);
  1034. printjob.print_window(win, -ww/2, -hh/2);
  1035. printjob.end_page();
  1036. }
  1037. printjob.end_job();
  1038. }
  1039. ////////////////////////////////////////////////////////////////
  1040. extern Fl_Menu_Item New_Menu[];
  1041. void toggle_widgetbin_cb(Fl_Widget *, void *);
  1042. void toggle_sourceview_cb(Fl_Double_Window *, void *);
  1043. Fl_Menu_Item Main_Menu[] = {
  1044. {"&File",0,0,0,FL_SUBMENU},
  1045. {"&New...", FL_COMMAND+'n', new_cb, 0},
  1046. {"&Open...", FL_COMMAND+'o', open_cb, 0},
  1047. {"&Insert...", FL_COMMAND+'i', open_cb, (void*)1, FL_MENU_DIVIDER},
  1048. {"&Save", FL_COMMAND+'s', save_cb, 0},
  1049. {"Save &As...", FL_COMMAND+FL_SHIFT+'s', save_cb, (void*)1},
  1050. {"Sa&ve A Copy...", 0, save_cb, (void*)2},
  1051. {"Save &Template...", 0, save_template_cb},
  1052. {"&Revert...", 0, revert_cb, 0, FL_MENU_DIVIDER},
  1053. {"&Print...", FL_COMMAND+'p', print_menu_cb},
  1054. {"Write &Code...", FL_COMMAND+FL_SHIFT+'c', write_cb, 0},
  1055. {"Sa&ve, Write code, Exit", FL_F+12, save_write_exit_cb, 0},
  1056. {"&Write Strings...", FL_COMMAND+FL_SHIFT+'w', write_strings_cb, 0, FL_MENU_DIVIDER},
  1057. {relative_history[0], FL_COMMAND+'0', open_history_cb, absolute_history[0]},
  1058. {relative_history[1], FL_COMMAND+'1', open_history_cb, absolute_history[1]},
  1059. {relative_history[2], FL_COMMAND+'2', open_history_cb, absolute_history[2]},
  1060. {relative_history[3], FL_COMMAND+'3', open_history_cb, absolute_history[3]},
  1061. {relative_history[4], FL_COMMAND+'4', open_history_cb, absolute_history[4]},
  1062. {relative_history[5], FL_COMMAND+'5', open_history_cb, absolute_history[5]},
  1063. {relative_history[6], FL_COMMAND+'6', open_history_cb, absolute_history[6]},
  1064. {relative_history[7], FL_COMMAND+'7', open_history_cb, absolute_history[7]},
  1065. {relative_history[8], FL_COMMAND+'8', open_history_cb, absolute_history[8]},
  1066. {relative_history[9], FL_COMMAND+'9', open_history_cb, absolute_history[9], FL_MENU_DIVIDER},
  1067. {"&Quit", FL_COMMAND+'q', exit_cb},
  1068. {0},
  1069. {"&Edit",0,0,0,FL_SUBMENU},
  1070. {"&Undo", FL_COMMAND+'z', undo_cb},
  1071. {"&Redo", FL_COMMAND+FL_SHIFT+'z', redo_cb, 0, FL_MENU_DIVIDER},
  1072. {"C&ut", FL_COMMAND+'x', cut_cb},
  1073. {"&Copy", FL_COMMAND+'c', copy_cb},
  1074. {"&Paste", FL_COMMAND+'v', paste_cb},
  1075. {"Dup&licate", FL_COMMAND+'u', duplicate_cb},
  1076. {"&Delete", FL_Delete, delete_cb, 0, FL_MENU_DIVIDER},
  1077. {"Select &All", FL_COMMAND+'a', select_all_cb},
  1078. {"Select &None", FL_COMMAND+FL_SHIFT+'a', select_none_cb, 0, FL_MENU_DIVIDER},
  1079. {"Pr&operties...", FL_F+1, openwidget_cb},
  1080. {"&Sort",0,sort_cb},
  1081. {"Sort by name",0,sort_by_name_cb},
  1082. {"&Earlier", FL_F+2, earlier_cb},
  1083. {"&Later", FL_F+3, later_cb},
  1084. {"&Group", FL_F+7, group_cb},
  1085. {"Ung&roup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER},
  1086. {"Hide O&verlays",FL_COMMAND+FL_SHIFT+'o',toggle_overlays},
  1087. {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb},
  1088. {"Show Source Code...",FL_ALT+FL_SHIFT+'s', (Fl_Callback*)toggle_sourceview_cb, 0, FL_MENU_DIVIDER},
  1089. {"Pro&ject Settings...",FL_ALT+'p',show_project_cb},
  1090. {"GU&I Settings...",FL_ALT+FL_SHIFT+'p',show_settings_cb,0,FL_MENU_DIVIDER},
  1091. {"Global &FLTK Settings...",FL_ALT+FL_SHIFT+'g',show_global_settings_cb},
  1092. {0},
  1093. {"&New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER},
  1094. {"&Layout",0,0,0,FL_SUBMENU},
  1095. {"&Align",0,0,0,FL_SUBMENU},
  1096. {"&Left",0,(Fl_Callback *)align_widget_cb,(void*)10},
  1097. {"&Center",0,(Fl_Callback *)align_widget_cb,(void*)11},
  1098. {"&Right",0,(Fl_Callback *)align_widget_cb,(void*)12},
  1099. {"&Top",0,(Fl_Callback *)align_widget_cb,(void*)13},
  1100. {"&Middle",0,(Fl_Callback *)align_widget_cb,(void*)14},
  1101. {"&Bottom",0,(Fl_Callback *)align_widget_cb,(void*)15},
  1102. {0},
  1103. {"&Space Evenly",0,0,0,FL_SUBMENU},
  1104. {"&Across",0,(Fl_Callback *)align_widget_cb,(void*)20},
  1105. {"&Down",0,(Fl_Callback *)align_widget_cb,(void*)21},
  1106. {0},
  1107. {"&Make Same Size",0,0,0,FL_SUBMENU},
  1108. {"&Width",0,(Fl_Callback *)align_widget_cb,(void*)30},
  1109. {"&Height",0,(Fl_Callback *)align_widget_cb,(void*)31},
  1110. {"&Both",0,(Fl_Callback *)align_widget_cb,(void*)32},
  1111. {0},
  1112. {"Make Same Size as Parent",0,0,0,FL_SUBMENU},
  1113. {"Width",0,(Fl_Callback *)align_widget_cb,(void*)300},
  1114. {"Height",0,(Fl_Callback *)align_widget_cb,(void*)310},
  1115. {"Both",0,(Fl_Callback *)align_widget_cb,(void*)320},
  1116. {0},
  1117. {"Fill Parent Same Size",0,0,0,FL_SUBMENU},
  1118. {"Width",0,(Fl_Callback *)align_widget_cb,(void*)3000},
  1119. {"Height",0,(Fl_Callback *)align_widget_cb,(void*)3100},
  1120. {"Both",0,(Fl_Callback *)align_widget_cb,(void*)3200},
  1121. {0},
  1122. {"&Center In Group",0,0,0,FL_SUBMENU},
  1123. {"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40},
  1124. {"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41},
  1125. {0},
  1126. {"Set &Widget Size",0,0,0,FL_SUBMENU|FL_MENU_DIVIDER},
  1127. {"&Tiny",FL_ALT+'1',(Fl_Callback *)widget_size_cb,(void*)8,0,FL_NORMAL_LABEL,FL_HELVETICA,8},
  1128. {"&Small",FL_ALT+'2',(Fl_Callback *)widget_size_cb,(void*)11,0,FL_NORMAL_LABEL,FL_HELVETICA,11},
  1129. {"&Normal",FL_ALT+'3',(Fl_Callback *)widget_size_cb,(void*)14,0,FL_NORMAL_LABEL,FL_HELVETICA,14},
  1130. {"&Medium",FL_ALT+'4',(Fl_Callback *)widget_size_cb,(void*)18,0,FL_NORMAL_LABEL,FL_HELVETICA,18},
  1131. {"&Large",FL_ALT+'5',(Fl_Callback *)widget_size_cb,(void*)24,0,FL_NORMAL_LABEL,FL_HELVETICA,24},
  1132. {"&Huge",FL_ALT+'6',(Fl_Callback *)widget_size_cb,(void*)32,0,FL_NORMAL_LABEL,FL_HELVETICA,32},
  1133. {0},
  1134. {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb},
  1135. {0},
  1136. {"&Shell",0,0,0,FL_SUBMENU},
  1137. {"Execute &Command...",FL_ALT+'x',(Fl_Callback *)show_shell_window},
  1138. {"Execute &Again...",FL_ALT+'g',(Fl_Callback *)do_shell_command},
  1139. {0},
  1140. {"&Help",0,0,0,FL_SUBMENU},
  1141. {"&Rapid development with FLUID...",0,help_cb},
  1142. {"&FLTK Programmers Manual...",0,manual_cb, 0, FL_MENU_DIVIDER},
  1143. {"&About FLUID...",0,about_cb},
  1144. {0},
  1145. {0}};
  1146. #define BROWSERWIDTH 300
  1147. #define BROWSERHEIGHT 500
  1148. #define WINWIDTH 300
  1149. #define MENUHEIGHT 25
  1150. #define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT*2)
  1151. extern void fill_in_New_Menu();
  1152. void scheme_cb(Fl_Choice *, void *) {
  1153. if (compile_only)
  1154. return;
  1155. switch (scheme_choice->value()) {
  1156. case 0 : // Default
  1157. Fl::scheme(NULL);
  1158. break;
  1159. case 1 : // None
  1160. Fl::scheme("none");
  1161. break;
  1162. case 2 : // Plastic
  1163. Fl::scheme("plastic");
  1164. break;
  1165. case 3 : // GTK+
  1166. Fl::scheme("gtk+");
  1167. break;
  1168. case 4 : // Gleam
  1169. Fl::scheme("gleam");
  1170. break;
  1171. }
  1172. fluid_prefs.set("scheme", scheme_choice->value());
  1173. }
  1174. void toggle_widgetbin_cb(Fl_Widget *, void *) {
  1175. if (!widgetbin_panel) {
  1176. make_widgetbin();
  1177. if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return;
  1178. }
  1179. if (widgetbin_panel->visible()) {
  1180. widgetbin_panel->hide();
  1181. widgetbin_item->label("Show Widget &Bin...");
  1182. } else {
  1183. widgetbin_panel->show();
  1184. widgetbin_item->label("Hide Widget &Bin");
  1185. }
  1186. }
  1187. void toggle_sourceview_cb(Fl_Double_Window *, void *) {
  1188. if (!sourceview_panel) {
  1189. make_sourceview();
  1190. sourceview_panel->callback((Fl_Callback*)toggle_sourceview_cb);
  1191. Fl_Preferences svp(fluid_prefs, "sourceview");
  1192. int autorefresh;
  1193. svp.get("autorefresh", autorefresh, 1);
  1194. sv_autorefresh->value(autorefresh);
  1195. int autoposition;
  1196. svp.get("autoposition", autoposition, 1);
  1197. sv_autoposition->value(autoposition);
  1198. int tab;
  1199. svp.get("tab", tab, 0);
  1200. if (tab>=0 && tab<sv_tab->children()) sv_tab->value(sv_tab->child(tab));
  1201. if (!position_window(sourceview_panel,"sourceview_pos", 0, 320, 120, 550, 500)) return;
  1202. }
  1203. if (sourceview_panel->visible()) {
  1204. sourceview_panel->hide();
  1205. sourceview_item->label("Show Source Code...");
  1206. } else {
  1207. sourceview_panel->show();
  1208. sourceview_item->label("Hide Source Code...");
  1209. update_sourceview_cb(0,0);
  1210. }
  1211. }
  1212. void toggle_sourceview_b_cb(Fl_Button*, void *) {
  1213. toggle_sourceview_cb(0,0);
  1214. }
  1215. extern void select(Fl_Type *o, int v);
  1216. extern void deselect();
  1217. Fl_Hold_Browser *widget_borwser_alphabetical = NULL;
  1218. void widget_borwser_alphabetical_cb(Fl_Hold_Browser* o, void* v) {
  1219. Fl_Type *t = (Fl_Type *)o->data(o->value());
  1220. if(t) {
  1221. deselect();
  1222. select(t,1);
  1223. t->open();
  1224. }
  1225. }
  1226. void main_tabs_cb(Fl_Tabs* o, void* v) {
  1227. if(widget_borwser_alphabetical && widget_borwser_alphabetical->visible_r()) {
  1228. //fl_alert("Alphabetical !");
  1229. Fl_Hold_Browser *wba = widget_borwser_alphabetical;
  1230. Fl_Type *f;
  1231. wba->clear();
  1232. char buf[1024];
  1233. char *p;
  1234. #define MAX_WNAME 160
  1235. for (f = Fl_Type::first; f ; f = f->next) {
  1236. if(f->is_code_block()) continue;
  1237. const char *name = f->name();
  1238. Fl_Type *parent = f->parent;
  1239. const char *parent_name = parent ? parent->name() : NULL;
  1240. if(!name) name = (f->title() ? f->title() : "?");
  1241. if(!parent_name) parent_name = (parent && parent->title() ? parent->title() : "?");
  1242. snprintf(buf, MAX_WNAME, "%s -> %s", name, parent_name);
  1243. buf[MAX_WNAME] = '\0';
  1244. for(p=buf; *p; p++) if(*p == '\n') *p=' ';
  1245. wba->add(buf, f);
  1246. }
  1247. wba->sort(FL_SORT_ASCENDING);
  1248. }
  1249. }
  1250. void make_main_window() {
  1251. if (!compile_only) {
  1252. fluid_prefs.get("snap", snap, 1);
  1253. fluid_prefs.get("gridx", gridx, 5);
  1254. fluid_prefs.get("gridy", gridy, 5);
  1255. fluid_prefs.get("show_guides", show_guides, 0);
  1256. fluid_prefs.get("widget_size", Fl_Widget_Type::default_size, 14);
  1257. fluid_prefs.get("show_comments", show_comments, 1);
  1258. make_layout_window();
  1259. make_shell_window();
  1260. }
  1261. if (!main_window) {
  1262. Fl_Widget *o;
  1263. main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid");
  1264. main_window->box(FL_FLAT_BOX);
  1265. main_window->color(FL_BACKGROUND_COLOR);
  1266. Fl_Tabs *tabs = new Fl_Tabs(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT+MENUHEIGHT);
  1267. Fl_Group *gmain = new Fl_Group(0, MENUHEIGHT*2,BROWSERWIDTH,BROWSERHEIGHT, "Main View");
  1268. o = make_widget_browser(0,MENUHEIGHT*2,BROWSERWIDTH,BROWSERHEIGHT);
  1269. o->box(FL_FLAT_BOX);
  1270. o->tooltip("Double-click to view or change an item.");
  1271. gmain->end();
  1272. gmain->resizable(o);
  1273. Fl_Group *galpha = new Fl_Group(0, MENUHEIGHT*2,BROWSERWIDTH,BROWSERHEIGHT, "Alphabetical View");
  1274. widget_borwser_alphabetical = new Fl_Hold_Browser(0,MENUHEIGHT*2,BROWSERWIDTH,BROWSERHEIGHT);
  1275. o = widget_borwser_alphabetical;
  1276. o->box(FL_FLAT_BOX);
  1277. o->tooltip("Double-click to view or change an item.");
  1278. o->callback((Fl_Callback*)widget_borwser_alphabetical_cb);
  1279. galpha->end();
  1280. tabs->end();
  1281. tabs->resizable(gmain);
  1282. tabs->callback((Fl_Callback*)main_tabs_cb);
  1283. main_window->resizable(tabs);
  1284. main_menubar = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT);
  1285. main_menubar->menu(Main_Menu);
  1286. // quick access to all dynamic menu items
  1287. save_item = (Fl_Menu_Item*)main_menubar->find_item(save_cb);
  1288. history_item = (Fl_Menu_Item*)main_menubar->find_item(open_history_cb);
  1289. widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb);
  1290. sourceview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_sourceview_cb);
  1291. main_menubar->global();
  1292. fill_in_New_Menu();
  1293. main_window->end();
  1294. }
  1295. if (!compile_only) {
  1296. load_history();
  1297. make_settings_window();
  1298. make_global_settings_window();
  1299. }
  1300. }
  1301. // Load file history from preferences...
  1302. void load_history() {
  1303. int i; // Looping var
  1304. int max_files;
  1305. fluid_prefs.get("recent_files", max_files, 5);
  1306. if (max_files > 10) max_files = 10;
  1307. for (i = 0; i < max_files; i ++) {
  1308. fluid_prefs.get( Fl_Preferences::Name("file%d", i), absolute_history[i], "", sizeof(absolute_history[i]));
  1309. if (absolute_history[i][0]) {
  1310. // Make a relative version of the filename for the menu...
  1311. fl_filename_relative(relative_history[i], sizeof(relative_history[i]),
  1312. absolute_history[i]);
  1313. if (i == 9) history_item[i].flags = FL_MENU_DIVIDER;
  1314. else history_item[i].flags = 0;
  1315. } else break;
  1316. }
  1317. for (; i < 10; i ++) {
  1318. if (i) history_item[i-1].flags |= FL_MENU_DIVIDER;
  1319. history_item[i].hide();
  1320. }
  1321. }
  1322. // Update file history from preferences...
  1323. void update_history(const char *flname) {
  1324. int i; // Looping var
  1325. char absolute[FL_PATH_MAX];
  1326. int max_files;
  1327. fluid_prefs.get("recent_files", max_files, 5);
  1328. if (max_files > 10) max_files = 10;
  1329. fl_filename_absolute(absolute, sizeof(absolute), flname);
  1330. for (i = 0; i < max_files; i ++)
  1331. #if defined(WIN32) || defined(__APPLE__)
  1332. if (!strcasecmp(absolute, absolute_history[i])) break;
  1333. #else
  1334. if (!strcmp(absolute, absolute_history[i])) break;
  1335. #endif // WIN32 || __APPLE__
  1336. if (i == 0) return;
  1337. if (i >= max_files) i = max_files - 1;
  1338. // Move the other flnames down in the list...
  1339. memmove(absolute_history + 1, absolute_history,
  1340. i * sizeof(absolute_history[0]));
  1341. memmove(relative_history + 1, relative_history,
  1342. i * sizeof(relative_history[0]));
  1343. // Put the new file at the top...
  1344. strlcpy(absolute_history[0], absolute, sizeof(absolute_history[0]));
  1345. fl_filename_relative(relative_history[0], sizeof(relative_history[0]),
  1346. absolute_history[0]);
  1347. // Update the menu items as needed...
  1348. for (i = 0; i < max_files; i ++) {
  1349. fluid_prefs.set( Fl_Preferences::Name("file%d", i), absolute_history[i]);
  1350. if (absolute_history[i][0]) {
  1351. if (i == 9) history_item[i].flags = FL_MENU_DIVIDER;
  1352. else history_item[i].flags = 0;
  1353. } else break;
  1354. }
  1355. for (; i < 10; i ++) {
  1356. fluid_prefs.set( Fl_Preferences::Name("file%d", i), "");
  1357. if (i) history_item[i-1].flags |= FL_MENU_DIVIDER;
  1358. history_item[i].hide();
  1359. }
  1360. fluid_prefs.flush();
  1361. }
  1362. // ********** portable process class definition **********
  1363. class Fl_Process {
  1364. public:
  1365. // construction / destruction
  1366. Fl_Process() {_fpt= NULL;}
  1367. ~Fl_Process() {if (_fpt) close();}
  1368. // FIXME: popen needs the utf8 equivalen fl_popen
  1369. FILE * popen (const char *cmd, const char *mode="r");
  1370. //not necessary here: FILE * fl_fopen (const char *file, const char *mode="r");
  1371. int close();
  1372. FILE * desc() const { return _fpt;} // non null if file is open
  1373. char * get_line(char * line, size_t s) const {return _fpt ? fgets(line, s, _fpt) : NULL;}
  1374. #if defined(WIN32) && !defined(__CYGWIN__)
  1375. protected:
  1376. HANDLE pin[2], pout[2], perr[2];
  1377. char ptmode;
  1378. PROCESS_INFORMATION pi;
  1379. STARTUPINFO si;
  1380. static bool createPipe(HANDLE * h, BOOL bInheritHnd=TRUE);
  1381. private:
  1382. FILE * freeHandles() {
  1383. clean_close(pin[0]); clean_close(pin[1]);
  1384. clean_close(pout[0]); clean_close(pout[1]);
  1385. clean_close(perr[0]); clean_close(perr[1]);
  1386. return NULL; // convenient for error management
  1387. }
  1388. static void clean_close(HANDLE& h);
  1389. #endif
  1390. protected:
  1391. FILE * _fpt;
  1392. };
  1393. #if defined(WIN32) && !defined(__CYGWIN__)
  1394. bool Fl_Process::createPipe(HANDLE * h, BOOL bInheritHnd) {
  1395. SECURITY_ATTRIBUTES sa;
  1396. sa.nLength = sizeof(sa);
  1397. sa.lpSecurityDescriptor = NULL;
  1398. sa.bInheritHandle = bInheritHnd;
  1399. return CreatePipe (&h[0],&h[1],&sa,0) ? true : false;
  1400. }
  1401. #endif
  1402. // portable open process:
  1403. FILE * Fl_Process::popen(const char *cmd, const char *mode) {
  1404. #if defined(WIN32) && !defined(__CYGWIN__)
  1405. // PRECONDITIONS
  1406. if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return NULL;
  1407. if (_fpt) close(); // close first before reuse
  1408. ptmode = *mode;
  1409. pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE;
  1410. // stderr to stdout wanted ?
  1411. int fusion = (strstr(cmd,"2>&1") !=NULL);
  1412. // Create windows pipes
  1413. if (!createPipe(pin) || !createPipe(pout) || (!fusion && !createPipe(perr) ) )
  1414. return freeHandles(); // error
  1415. // Initialize Startup Info
  1416. ZeroMemory(&si, sizeof(STARTUPINFO));
  1417. si.cb = sizeof(STARTUPINFO);
  1418. si.dwFlags = STARTF_USESTDHANDLES;
  1419. si.hStdInput = pin[0];
  1420. si.hStdOutput = pout[1];
  1421. si.hStdError = fusion ? pout[1] : perr [1];
  1422. if ( CreateProcess(NULL, (LPTSTR) cmd,NULL,NULL,TRUE,
  1423. DETACHED_PROCESS,NULL,NULL, &si, &pi)) {
  1424. // don't need theses handles inherited by child process:
  1425. clean_close(pin[0]); clean_close(pout[1]); clean_close(perr[1]);
  1426. HANDLE & h = *mode == 'r' ? pout[0] : pin[1];
  1427. _fpt = _fdopen(_open_osfhandle((fl_intptr_t) h,_O_BINARY),mode);
  1428. h= INVALID_HANDLE_VALUE; // reset the handle pointer that is shared
  1429. // with _fpt so we don't free it twice
  1430. }
  1431. if (!_fpt) freeHandles();
  1432. return _fpt;
  1433. #else
  1434. _fpt=::popen(cmd,mode);
  1435. return _fpt;
  1436. #endif
  1437. }
  1438. int Fl_Process::close() {
  1439. #if defined(WIN32) && !defined(__CYGWIN__)
  1440. if (_fpt) {
  1441. fclose(_fpt);
  1442. clean_close(perr[0]);
  1443. clean_close(pin[1]);
  1444. clean_close(pout[0]);
  1445. _fpt = NULL;
  1446. return 0;
  1447. }
  1448. return -1;
  1449. #else
  1450. int ret = ::pclose(_fpt);
  1451. _fpt=NULL;
  1452. return ret;
  1453. #endif
  1454. }
  1455. #if defined(WIN32) && !defined(__CYGWIN__)
  1456. void Fl_Process::clean_close(HANDLE& h) {
  1457. if (h!= INVALID_HANDLE_VALUE) CloseHandle(h);
  1458. h = INVALID_HANDLE_VALUE;
  1459. }
  1460. #endif
  1461. // ********** Fl_Process class end **********
  1462. static Fl_Process s_proc;
  1463. // Shell command support...
  1464. static bool prepare_shell_command(const char * &command) { // common pre-shell command code all platforms
  1465. shell_window->hide();
  1466. if (s_proc.desc()) {
  1467. fl_alert("Previous shell command still running!");
  1468. return false;
  1469. }
  1470. if ((command = shell_command_input->value()) == NULL || !*command) {
  1471. fl_alert("No shell command entered!");
  1472. return false;
  1473. }
  1474. if (shell_savefl_button->value()) {
  1475. save_cb(0, 0);
  1476. }
  1477. if (shell_writecode_button->value()) {
  1478. compile_only = 1;
  1479. write_cb(0, 0);
  1480. compile_only = 0;
  1481. }
  1482. if (shell_writemsgs_button->value()) {
  1483. compile_only = 1;
  1484. write_strings_cb(0, 0);
  1485. compile_only = 0;
  1486. }
  1487. return true;
  1488. }
  1489. #if !defined(__MWERKS__)
  1490. // Support the full piped shell command...
  1491. void
  1492. shell_pipe_cb(FL_SOCKET, void*) {
  1493. char line[1024]=""; // Line from command output...
  1494. if (s_proc.get_line(line, sizeof(line)) != NULL) {
  1495. // Add the line to the output list...
  1496. shell_run_buffer->append(line);
  1497. } else {
  1498. // End of file; tell the parent...
  1499. Fl::remove_fd(fileno(s_proc.desc()));
  1500. s_proc.close();
  1501. shell_run_buffer->append("... END SHELL COMMAND ...\n");
  1502. }
  1503. shell_run_display->scroll(shell_run_display->count_lines(0,
  1504. shell_run_buffer->length(), 1), 0);
  1505. }
  1506. void
  1507. do_shell_command(Fl_Return_Button*, void*) {
  1508. const char *command=NULL; // Command to run
  1509. if (!prepare_shell_command(command)) return;
  1510. // Show the output window and clear things...
  1511. shell_run_buffer->text("");
  1512. shell_run_buffer->append(command);
  1513. shell_run_buffer->append("\n");
  1514. shell_run_window->label("Shell Command Running...");
  1515. if (s_proc.popen((char *)command) == NULL) {
  1516. fl_alert("Unable to run shell command: %s", strerror(errno));
  1517. return;
  1518. }
  1519. shell_run_button->deactivate();
  1520. shell_run_window->hotspot(shell_run_display);
  1521. shell_run_window->show();
  1522. Fl::add_fd(fileno(s_proc.desc()), shell_pipe_cb);
  1523. while (s_proc.desc()) Fl::wait();
  1524. shell_run_button->activate();
  1525. shell_run_window->label("Shell Command Complete");
  1526. fl_beep();
  1527. while (shell_run_window->shown()) Fl::wait();
  1528. }
  1529. #else
  1530. // Just do basic shell command stuff, no status window...
  1531. void
  1532. do_shell_command(Fl_Return_Button*, void*) {
  1533. const char *command; // Command to run
  1534. int status; // Status from command...
  1535. if (!prepare_shell_command(command)) return;
  1536. if ((status = system(command)) != 0) {
  1537. fl_alert("Shell command returned status %d!", status);
  1538. } else if (completion_button->value()) {
  1539. fl_message("Shell command completed successfully!");
  1540. }
  1541. }
  1542. #endif // !__MWERKS__
  1543. void
  1544. show_shell_window() {
  1545. shell_window->hotspot(shell_command_input);
  1546. shell_window->show();
  1547. }
  1548. void set_filename(const char *c) {
  1549. if (filename) free((void *)filename);
  1550. filename = c ? strdup(c) : NULL;
  1551. if (filename && !compile_only)
  1552. update_history(filename);
  1553. set_modflag(modflag);
  1554. }
  1555. //
  1556. // The Source View system offers an immediate preview of the code
  1557. // files that will be generated by FLUID. It also marks the code
  1558. // generated for the last selected item in the header and the source
  1559. // file.
  1560. //
  1561. // Can we patent this? ;-) - Matt, [email protected]
  1562. //
  1563. //
  1564. // Update the header and source code highlighting depending on the
  1565. // currently selected object
  1566. //
  1567. void update_sourceview_position()
  1568. {
  1569. if (!sourceview_panel || !sourceview_panel->visible())
  1570. return;
  1571. if (sv_autoposition->value()==0)
  1572. return;
  1573. if (sourceview_panel && sourceview_panel->visible() && Fl_Type::current) {
  1574. int pos0, pos1;
  1575. if (sv_source->visible_r()) {
  1576. pos0 = Fl_Type::current->code_position;
  1577. pos1 = Fl_Type::current->code_position_end;
  1578. if (pos0>=0) {
  1579. if (pos1<pos0)
  1580. pos1 = pos0;
  1581. sv_source->buffer()->highlight(pos0, pos1);
  1582. int line = sv_source->buffer()->count_lines(0, pos0);
  1583. sv_source->scroll(line, 0);
  1584. }
  1585. }
  1586. if (sv_header->visible_r()) {
  1587. pos0 = Fl_Type::current->header_position;
  1588. pos1 = Fl_Type::current->header_position_end;
  1589. if (pos0>=0) {
  1590. if (pos1<pos0)
  1591. pos1 = pos0;
  1592. sv_header->buffer()->highlight(pos0, pos1);
  1593. int line = sv_header->buffer()->count_lines(0, pos0);
  1594. sv_header->scroll(line, 0);
  1595. }
  1596. }
  1597. }
  1598. }
  1599. //
  1600. // Update the selected object depending on the view position
  1601. //
  1602. void update_selected_object_by_view_position(int source_position, int header_position)
  1603. {
  1604. Fl_Type *t, *found = NULL;
  1605. for (t = Fl_Type::first; t; t = t->next) {
  1606. // Find the first window...
  1607. if(source_position >= 0) {
  1608. if( (source_position >= t->code_position) && (source_position <= t->code_position_end) ){
  1609. found = t;
  1610. };
  1611. } else if(header_position >= 0) {
  1612. if( (header_position >= t->header_position) && (header_position <= t->header_position_end) ) {
  1613. found = t;
  1614. };
  1615. } else return;
  1616. }
  1617. if (found){
  1618. deselect();
  1619. //Fl_Type::current = t;
  1620. select(found,1);
  1621. found->open();
  1622. }
  1623. }
  1624. void update_sourceview_position_cb(Fl_Tabs*, void*)
  1625. {
  1626. update_sourceview_position();
  1627. }
  1628. void update_widget_browser_position_cb(CodeViewer *source, CodeViewer *header, Fl_Input *ii){
  1629. char buf[64];
  1630. int start, end, line;
  1631. CodeViewer *o = source ? source : header;
  1632. if(o) {
  1633. o->buffer()->selection_position(&start, &end);
  1634. line = o->buffer()->count_lines(0, start);
  1635. sprintf(buf,"%d", line);
  1636. ii->value(buf);
  1637. update_selected_object_by_view_position(source ? start : -1, header ? start : -1);
  1638. }
  1639. }
  1640. static char *sv_source_filename = 0;
  1641. static char *sv_header_filename = 0;
  1642. //
  1643. // Generate a header and source file in a temporary directory and
  1644. // load those into the Code Viewer widgets.
  1645. //
  1646. void update_sourceview_cb(Fl_Button*, void*)
  1647. {
  1648. if (!sourceview_panel || !sourceview_panel->visible())
  1649. return;
  1650. // generate space for the source and header file filenames
  1651. if (!sv_source_filename) {
  1652. sv_source_filename = (char*)malloc(FL_PATH_MAX);
  1653. fluid_prefs.getUserdataPath(sv_source_filename, FL_PATH_MAX);
  1654. strlcat(sv_source_filename, "source_view_tmp.cxx", FL_PATH_MAX);
  1655. }
  1656. if (!sv_header_filename) {
  1657. sv_header_filename = (char*)malloc(FL_PATH_MAX);
  1658. fluid_prefs.getUserdataPath(sv_header_filename, FL_PATH_MAX);
  1659. strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX);
  1660. }
  1661. strlcpy(i18n_program, fl_filename_name(sv_source_filename), sizeof(i18n_program));
  1662. fl_filename_setext(i18n_program, sizeof(i18n_program), "");
  1663. const char *code_file_name_bak = code_file_name;
  1664. code_file_name = sv_source_filename;
  1665. const char *header_file_name_bak = header_file_name;
  1666. header_file_name = sv_header_filename;
  1667. // generate the code and load the files
  1668. write_sourceview = 1;
  1669. // generate files
  1670. if (write_code(sv_source_filename, sv_header_filename))
  1671. {
  1672. // load file into source editor
  1673. int pos = sv_source->top_line();
  1674. sv_source->buffer()->loadfile(sv_source_filename);
  1675. sv_source->scroll(pos, 0);
  1676. // load file into header editor
  1677. pos = sv_header->top_line();
  1678. sv_header->buffer()->loadfile(sv_header_filename);
  1679. sv_header->scroll(pos, 0);
  1680. // update the source code highlighting
  1681. update_sourceview_position();
  1682. }
  1683. write_sourceview = 0;
  1684. code_file_name = code_file_name_bak;
  1685. header_file_name = header_file_name_bak;
  1686. }
  1687. void update_sourceview_timer(void*)
  1688. {
  1689. update_sourceview_cb(0,0);
  1690. }
  1691. // Set the "modified" flag and update the title of the main window...
  1692. void set_modflag(int mf) {
  1693. const char *basename;
  1694. static char title[FL_PATH_MAX];
  1695. modflag = mf;
  1696. if (main_window) {
  1697. if (!filename) basename = "Untitled.fl";
  1698. else if ((basename = strrchr(filename, '/')) != NULL) basename ++;
  1699. #if defined(WIN32) || defined(__EMX__)
  1700. else if ((basename = strrchr(filename, '\\')) != NULL) basename ++;
  1701. #endif // WIN32 || __EMX__
  1702. else basename = filename;
  1703. if (modflag) {
  1704. snprintf(title, sizeof(title), "%s (modified)", basename);
  1705. main_window->label(title);
  1706. } else main_window->label(basename);
  1707. }
  1708. // if the UI was modified in any way, update the Source View panel
  1709. if (sourceview_panel && sourceview_panel->visible() && sv_autorefresh->value())
  1710. {
  1711. // we will only update ealiest 0.5 seconds after the last change, and only
  1712. // if no other change was made, so dragging a widget will not generate any
  1713. // CPU load
  1714. Fl::remove_timeout(update_sourceview_timer, 0);
  1715. Fl::add_timeout(0.5, update_sourceview_timer, 0);
  1716. }
  1717. // Enable/disable the Save menu item...
  1718. if (modflag) save_item->activate();
  1719. else save_item->deactivate();
  1720. }
  1721. ////////////////////////////////////////////////////////////////
  1722. static int arg(int argc, char** argv, int& i) {
  1723. if (argv[i][1] == 'c' && !argv[i][2]) {compile_only = 1; i++; return 1;}
  1724. if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) {compile_only = 1; compile_strings = 1; i++; return 1;}
  1725. if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) {
  1726. code_file_name = argv[i+1];
  1727. code_file_set = 1;
  1728. i += 2;
  1729. return 2;
  1730. }
  1731. if (argv[i][1] == 'h' && !argv[i][2]) {
  1732. header_file_name = argv[i+1];
  1733. header_file_set = 1;
  1734. i += 2;
  1735. return 2;
  1736. }
  1737. Fl_Plugin_Manager pm("commandline");
  1738. int j, n = pm.plugins();
  1739. for (j=0; j<n; j++) {
  1740. Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(j);
  1741. int r = pi->arg(argc, argv, i);
  1742. if (r) return r;
  1743. }
  1744. return 0;
  1745. }
  1746. #if ! (defined(WIN32) && !defined (__CYGWIN__))
  1747. int quit_flag = 0;
  1748. #include <signal.h>
  1749. #ifdef _sigargs
  1750. #define SIGARG _sigargs
  1751. #else
  1752. #ifdef __sigargs
  1753. #define SIGARG __sigargs
  1754. #else
  1755. #define SIGARG int // you may need to fix this for older systems
  1756. #endif
  1757. #endif
  1758. extern "C" {
  1759. static void sigint(SIGARG) {
  1760. signal(SIGINT,sigint);
  1761. quit_flag = 1;
  1762. }
  1763. }
  1764. #endif
  1765. int main(int argc,char **argv) {
  1766. int i = 1;
  1767. if (!Fl::args(argc,argv,i,arg) || i < argc-1) {
  1768. static const char *msg =
  1769. "usage: %s <switches> name.fl\n"
  1770. " -c : write .cxx and .h and exit\n"
  1771. " -cs : write .cxx and .h and strings and exit\n"
  1772. " -o <name> : .cxx output filename, or extension if <name> starts with '.'\n"
  1773. " -h <name> : .h output filename, or extension if <name> starts with '.'\n";
  1774. int len = strlen(msg) + strlen(argv[0]) + strlen(Fl::help);
  1775. Fl_Plugin_Manager pm("commandline");
  1776. int i, n = pm.plugins();
  1777. for (i=0; i<n; i++) {
  1778. Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(i);
  1779. if (pi) len += strlen(pi->help());
  1780. }
  1781. char *buf = (char*)malloc(len+1);
  1782. sprintf(buf, msg, argv[0]);
  1783. for (i=0; i<n; i++) {
  1784. Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(i);
  1785. if (pi) strcat(buf, pi->help());
  1786. }
  1787. strcat(buf, Fl::help);
  1788. #ifdef _MSC_VER
  1789. fl_message("%s\n", buf);
  1790. #else
  1791. fprintf(stderr, "%s\n", buf);
  1792. #endif
  1793. free(buf);
  1794. return 1;
  1795. }
  1796. if (exit_early)
  1797. exit(0);
  1798. #ifdef USE_VM_SCRIPT
  1799. my_open_script_vm();
  1800. #endif
  1801. const char *c = argv[i];
  1802. fl_register_images();
  1803. make_main_window();
  1804. if (c) set_filename(c);
  1805. if (!compile_only) {
  1806. #ifdef __APPLE__
  1807. fl_open_callback(apple_open_cb);
  1808. #endif // __APPLE__
  1809. Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX));
  1810. Fl_File_Icon::load_system_icons();
  1811. main_window->callback(exit_cb);
  1812. position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT );
  1813. main_window->show(argc,argv);
  1814. toggle_widgetbin_cb(0,0);
  1815. toggle_sourceview_cb(0,0);
  1816. if (!c && openlast_button->value() && absolute_history[0][0]) {
  1817. // Open previous file when no file specified...
  1818. open_history_cb(0, absolute_history[0]);
  1819. }
  1820. }
  1821. undo_suspend();
  1822. if (c && !read_file(c,0)) {
  1823. if (compile_only) {
  1824. fprintf(stderr,"%s : %s\n", c, strerror(errno));
  1825. exit(1);
  1826. }
  1827. fl_message("Can't read %s: %s", c, strerror(errno));
  1828. }
  1829. undo_resume();
  1830. if (compile_only) {
  1831. if (compile_strings) write_strings_cb(0,0);
  1832. write_cb(0,0);
  1833. exit(0);
  1834. }
  1835. set_modflag(0);
  1836. undo_clear();
  1837. #ifndef WIN32
  1838. signal(SIGINT,sigint);
  1839. #endif
  1840. grid_cb(horizontal_input, 0); // Makes sure that windows get snap params...
  1841. #ifdef WIN32
  1842. Fl::run();
  1843. #else
  1844. while (!quit_flag) Fl::wait();
  1845. if (quit_flag) exit_cb(0,0);
  1846. #endif // WIN32
  1847. undo_clear();
  1848. #ifdef USE_VM_SCRIPT
  1849. my_close_script_vm();
  1850. #endif
  1851. return (0);
  1852. }
  1853. //
  1854. // End of "$Id: fluid.cxx 10113 2014-02-25 04:24:41Z greg.ercolano $".
  1855. //