diff options
| -rw-r--r-- | FL/Fl_Preferences.H | 9 | ||||
| -rw-r--r-- | fluid/Fd_Snap_Action.cxx | 14 | ||||
| -rw-r--r-- | fluid/Fd_Snap_Action.h | 21 | ||||
| -rw-r--r-- | fluid/Fl_Type.cxx | 9 | ||||
| -rw-r--r-- | fluid/README_fl.txt | 4 | ||||
| -rw-r--r-- | fluid/alignment_panel.cxx | 1329 | ||||
| -rw-r--r-- | fluid/alignment_panel.fl | 599 | ||||
| -rw-r--r-- | fluid/alignment_panel.h | 33 | ||||
| -rw-r--r-- | fluid/file.cxx | 55 | ||||
| -rw-r--r-- | fluid/fluid.cxx | 140 | ||||
| -rw-r--r-- | fluid/fluid.h | 33 | ||||
| -rw-r--r-- | fluid/pixmaps/fd_project.png | bin | 0 -> 6950 bytes | |||
| -rw-r--r-- | fluid/pixmaps/fd_user.png | bin | 0 -> 8612 bytes | |||
| -rw-r--r-- | fluid/shell_command.cxx | 832 | ||||
| -rw-r--r-- | fluid/shell_command.h | 100 | ||||
| -rw-r--r-- | fluid/sourceview_panel.cxx | 11 | ||||
| -rw-r--r-- | fluid/sourceview_panel.fl | 11 | ||||
| -rw-r--r-- | src/Fl_Preferences.cxx | 54 | ||||
| -rw-r--r-- | src/filename_absolute.cxx | 1 | ||||
| -rw-r--r-- | test/tree.fl | 6 | ||||
| -rw-r--r-- | test/unittest_core.cxx | 3 |
21 files changed, 2865 insertions, 399 deletions
diff --git a/FL/Fl_Preferences.H b/FL/Fl_Preferences.H index 5f988a344..6aee47878 100644 --- a/FL/Fl_Preferences.H +++ b/FL/Fl_Preferences.H @@ -22,6 +22,7 @@ # include <stdio.h> # include "Fl_Export.H" +# include "fl_attr.h" class Fl_String; @@ -131,6 +132,7 @@ public: ROOT_MASK = 0x00FF, ///< Mask for the values above CORE = 0x0100, ///< OR'd by FLTK to read and write core library preferences and options C_LOCALE = 0x1000, ///< This flag should always be set, it makes sure that floating point + CLEAR = 0x2000, ///< Don't read a possibly existing database. Instead, start with an empty set of preferences. ///< values are written correctly independently of the current locale SYSTEM_L = SYSTEM | C_LOCALE, ///< Preferences are used system-wide, locale independent USER_L = USER | C_LOCALE, ///< Preferences apply only to the current user, locale independent @@ -188,7 +190,7 @@ public: static Root filename( char *buffer, size_t buffer_size, Root root, const char *vendor, const char *application ); Fl_Preferences( Root root, const char *vendor, const char *application ); - Fl_Preferences( const char *path, const char *vendor, const char *application ); + Fl_Preferences( const char *path, const char *vendor, const char *application, Root flags ); Fl_Preferences( Fl_Preferences &parent, const char *group ); Fl_Preferences( Fl_Preferences *parent, const char *group ); Fl_Preferences( Fl_Preferences &parent, int groupIndex ); @@ -197,6 +199,9 @@ public: Fl_Preferences( ID id ); virtual ~Fl_Preferences(); + FL_DEPRECATED("in 1.4.0 - use Fl_Preferences(path, vendor, application, flags) instead", + Fl_Preferences( const char *path, const char *vendor, const char *application ) ); + Root filename( char *buffer, size_t buffer_size); /** Return an ID that can later be reused to open more references to this dataset. @@ -374,7 +379,7 @@ public: // older Sun compilers need this (public definition of the following cl Root root_type_; public: RootNode( Fl_Preferences *, Root root, const char *vendor, const char *application ); - RootNode( Fl_Preferences *, const char *path, const char *vendor, const char *application ); + RootNode( Fl_Preferences *, const char *path, const char *vendor, const char *application, Root flags ); RootNode( Fl_Preferences * ); ~RootNode(); int read(); diff --git a/fluid/Fd_Snap_Action.cxx b/fluid/Fd_Snap_Action.cxx index 3f52907ad..3602256f8 100644 --- a/fluid/Fd_Snap_Action.cxx +++ b/fluid/Fd_Snap_Action.cxx @@ -422,7 +422,7 @@ void Fd_Layout_Suite::init() { name_ = NULL; menu_label = NULL; layout[0] = layout[1] = layout[2] = NULL; - storage_ = 0; + storage_ = FD_STORE_INTERNAL; } /** @@ -651,7 +651,7 @@ void Fd_Layout_List::update_menu_labels() { */ int Fd_Layout_List::load(const Fl_String &filename) { remove_all(FD_STORE_FILE); - Fl_Preferences prefs(filename.c_str(), "layout.fluid.fltk.org", NULL); + Fl_Preferences prefs(filename.c_str(), "layout.fluid.fltk.org", NULL, Fl_Preferences::C_LOCALE); read(prefs, FD_STORE_FILE); return 0; } @@ -661,7 +661,7 @@ int Fd_Layout_List::load(const Fl_String &filename) { */ int Fd_Layout_List::save(const Fl_String &filename) { assert(this); - Fl_Preferences prefs(filename.c_str(), "layout.fluid.fltk.org", NULL); + Fl_Preferences prefs(filename.c_str(), "layout.fluid.fltk.org", NULL, (Fl_Preferences::Root)(Fl_Preferences::C_LOCALE|Fl_Preferences::CLEAR)); prefs.clear(); write(prefs, FD_STORE_FILE); return 0; @@ -670,7 +670,7 @@ int Fd_Layout_List::save(const Fl_String &filename) { /** Write Suite and Layout selection and selected layout data to Preferences database. */ -void Fd_Layout_List::write(Fl_Preferences &prefs, int storage) { +void Fd_Layout_List::write(Fl_Preferences &prefs, Fd_Tool_Store storage) { Fl_Preferences prefs_list(prefs, "Layouts"); prefs_list.clear(); prefs_list.set("current_suite", list_[current_suite()].name_); @@ -688,7 +688,7 @@ void Fd_Layout_List::write(Fl_Preferences &prefs, int storage) { /** Read Suite and Layout selection and selected layout data to Preferences database. */ -void Fd_Layout_List::read(Fl_Preferences &prefs, int storage) { +void Fd_Layout_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { Fl_Preferences prefs_list(prefs, "Layouts"); Fl_String cs; int cp = 0; @@ -859,7 +859,7 @@ int Fd_Layout_List::add(const char *name) { new_suite.layout[i] = new Fd_Layout_Preset; ::memcpy(new_suite.layout[i], old_suite.layout[i], sizeof(Fd_Layout_Preset)); } - int new_storage = old_suite.storage_; + Fd_Tool_Store new_storage = old_suite.storage_; if (new_storage == FD_STORE_INTERNAL) new_storage = FD_STORE_USER; new_suite.storage(new_storage); @@ -904,7 +904,7 @@ void Fd_Layout_List::remove(int ix) { Remove all Suites that use the given storage attribute. \param[in] storage storage attribute, see FD_STORE_INTERNAL, etc. */ -void Fd_Layout_List::remove_all(int storage) { +void Fd_Layout_List::remove_all(Fd_Tool_Store storage) { for (int i=list_size_-1; i>=0; --i) { if (list_[i].storage_ == storage) remove(i); diff --git a/fluid/Fd_Snap_Action.h b/fluid/Fd_Snap_Action.h index 1355332a9..fefb4618f 100644 --- a/fluid/Fd_Snap_Action.h +++ b/fluid/Fd_Snap_Action.h @@ -17,6 +17,7 @@ #ifndef _FLUID_FD_SNAP_ACTION_H #define _FLUID_FD_SNAP_ACTION_H +#include "fluid.h" #include "Fl_Window_Type.h" #include <FL/Fl_String.H> @@ -26,16 +27,6 @@ struct Fl_Menu_Item; extern Fl_Menu_Item main_layout_submenu_[]; /** - Indicate the storage location for a layout suite. - */ -enum { - FD_STORE_INTERNAL, ///< stored inside FLUID app - FD_STORE_USER, ///< suite is stored in the user wide FLUID settings - FD_STORE_PROJECT, ///< suite is stored within the current .fl project file - FD_STORE_FILE ///< store suite in external file -}; - -/** \brief Collection of layout settings. Presets contain default fonts and font sizes for labels and text. They @@ -97,13 +88,13 @@ public: char *name_; ///< name of the suite char *menu_label; ///< label text used in pulldown menu Fd_Layout_Preset *layout[3]; ///< presets for application, dialog, and toolbox windows - int storage_; ///< storage location (see FD_STORE_INTERNAL, etc.) + Fd_Tool_Store storage_; ///< storage location (see FD_STORE_INTERNAL, etc.) void write(Fl_Preferences &prefs); void read(Fl_Preferences &prefs); void write(Fd_Project_Writer*); void read(Fd_Project_Reader*); void update_label(); - void storage(int s) { storage_ = s; update_label(); } + void storage(Fd_Tool_Store s) { storage_ = s; update_label(); } void name(const char *n); void init(); ~Fd_Layout_Suite(); @@ -146,13 +137,13 @@ public: int load(const Fl_String &filename); int save(const Fl_String &filename); - void write(Fl_Preferences &prefs, int storage); - void read(Fl_Preferences &prefs, int storage); + void write(Fl_Preferences &prefs, Fd_Tool_Store storage); + void read(Fl_Preferences &prefs, Fd_Tool_Store storage); void write(Fd_Project_Writer*); void read(Fd_Project_Reader*); int add(Fd_Layout_Suite*); void remove(int index); - void remove_all(int storage); + void remove_all(Fd_Tool_Store storage); Fd_Layout_Preset *at(int); int size(); }; diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx index d98db5883..379c4cb90 100644 --- a/fluid/Fl_Type.cxx +++ b/fluid/Fl_Type.cxx @@ -252,11 +252,16 @@ void delete_all(int selected_only) { } if(!selected_only) { // reset the setting for the external shell command - shell_prefs_get(); - shell_settings_write(); + if (g_shell_config) { + g_shell_config->clear(FD_STORE_PROJECT); + g_shell_config->rebuild_shell_menu(); + g_shell_config->update_settings_dialog(); + } widget_browser->hposition(0); widget_browser->vposition(0); g_layout_list.remove_all(FD_STORE_PROJECT); + g_layout_list.current_suite(0); + g_layout_list.current_preset(0); g_layout_list.update_dialogs(); } selection_changed(0); diff --git a/fluid/README_fl.txt b/fluid/README_fl.txt index 6cd14fe08..1845a1f12 100644 --- a/fluid/README_fl.txt +++ b/fluid/README_fl.txt @@ -444,6 +444,10 @@ Type "Fl_Widget" <word> : C++ variable name "extra_code" <word> : C++ extra code lines ... : inherits more from Fl_Type +Type "Fl_Button" <word> : C++ variable name + + "compact" <word> : integer, set the flag for compact buttons, defaults to 0 + Type "Fl_Flex" <word> : C++ variable name "margins" <word> : this Word is written with printf as "{%d %d %d %d}", diff --git a/fluid/alignment_panel.cxx b/fluid/alignment_panel.cxx index 29f21fd4c..49348eb24 100644 --- a/fluid/alignment_panel.cxx +++ b/fluid/alignment_panel.cxx @@ -22,7 +22,61 @@ #include <FL/Fl_Tooltip.H> #include <FL/fl_ask.H> #include <string.h> +#include "../src/flstring.h" void scheme_cb(Fl_Scheme_Choice *, void *); +int w_settings_shell_list_selected; + +Fl_Double_Window *script_panel=(Fl_Double_Window *)0; + +static void cb_script_panel(Fl_Double_Window*, void*) { + if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) + return; // ignore Escape + script_panel->hide(); // otherwise hide..; +} + +Fl_Text_Editor *script_input=(Fl_Text_Editor *)0; + +Fl_Return_Button *script_panel_ok=(Fl_Return_Button *)0; + +Fl_Button *script_panel_cancel=(Fl_Button *)0; + +Fl_Double_Window* make_script_panel() { + { Fl_Double_Window* o = script_panel = new Fl_Double_Window(540, 180, "Shell Script Editor"); + script_panel->labelsize(11); + script_panel->callback((Fl_Callback*)cb_script_panel); + { script_input = new Fl_Text_Editor(10, 10, 520, 130); + script_input->box(FL_DOWN_BOX); + script_input->labelsize(11); + script_input->textfont(4); + script_input->textsize(11); + script_input->when(FL_WHEN_RELEASE | FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY); + Fl_Group::current()->resizable(script_input); + script_input->buffer(new Fl_Text_Buffer); + } // Fl_Text_Editor* script_input + { Fl_Group* o = new Fl_Group(10, 150, 520, 20); + o->labelsize(11); + { script_panel_ok = new Fl_Return_Button(400, 150, 60, 20, "OK"); + script_panel_ok->labelsize(11); + script_panel_ok->window()->hotspot(script_panel_ok); + } // Fl_Return_Button* script_panel_ok + { script_panel_cancel = new Fl_Button(470, 150, 60, 20, "Cancel"); + script_panel_cancel->labelsize(11); + } // Fl_Button* script_panel_cancel + { Fl_Box* o = new Fl_Box(10, 150, 380, 20); + o->labelsize(11); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + script_panel->set_modal(); + o->size_range(200, 150); + script_panel->end(); + } // Fl_Double_Window* script_panel + // Enable line numbers + script_input->linenumber_width(60); + script_input->linenumber_size(script_input->Fl_Text_Display::textsize()); + return script_panel; +} Fl_Double_Window *settings_window=(Fl_Double_Window *)0; @@ -755,63 +809,1089 @@ static Fl_Image *image_shell_64() { return image; } -static void cb_Command(Fl_Input* o, void* v) { +Fl_Browser *w_settings_shell_list=(Fl_Browser *)0; + +static void cb_w_settings_shell_list(Fl_Browser* o, void* v) { if (v == LOAD) { - o->value(g_shell_command.c_str()); + // load from g_shell_config + if (g_shell_config) { + o->clear(); + w_settings_shell_list_selected = 0; + for (int i=0; i<g_shell_config->list_size; i++) { + Fd_Shell_Command *cmd = g_shell_config->list[i]; + o->add(cmd->name.c_str()); + if (cmd->storage == FD_STORE_USER) + o->icon(i+1, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + o->icon(i+1, w_settings_shell_fd_project->image()); + } + } } else { - g_shell_command = o->value(); + // int prev_selected = w_settings_shell_list_selected; + w_settings_shell_list_selected = 0; + int selected = w_settings_shell_list->value(); + if (selected) { + if (w_settings_shell_list->selected(selected)) + w_settings_shell_list_selected = selected; + } + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); } } -static void cb_save(Fl_Check_Button* o, void* v) { +Fl_Group *w_settings_shell_toolbox=(Fl_Group *)0; + +static void cb_w_settings_shell_toolbox(Fl_Group* o, void* v) { + if (v==LOAD) { + propagate_load(o, v); + } +} + +static void cb_8(Fl_Button*, void* v) { + if (v != LOAD) { + int selected = w_settings_shell_list_selected; + Fd_Shell_Command *cmd = new Fd_Shell_Command("new shell command"); + g_shell_config->insert(selected, cmd); + w_settings_shell_list->insert(selected+1, cmd->name.c_str()); + w_settings_shell_list->deselect(); + w_settings_shell_list->value(selected+1); + if (cmd->storage == FD_STORE_USER) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); + w_settings_shell_list->do_callback(); + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); + g_shell_config->rebuild_shell_menu(); + } +} + +Fl_Button *w_settings_shell_dup=(Fl_Button *)0; + +static void cb_w_settings_shell_dup(Fl_Button* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v==LOAD) { + if (selected) { + o->activate(); + } else { + o->deactivate(); + } + } else { + if (!selected) return; + Fd_Shell_Command *cmd = new Fd_Shell_Command(g_shell_config->list[selected-1]); + g_shell_config->insert(selected, cmd); + w_settings_shell_list->insert(selected+1, cmd->name.c_str()); + w_settings_shell_list->deselect(); + w_settings_shell_list->deselect(); + w_settings_shell_list->value(selected+1); + if (cmd->storage == FD_STORE_USER) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); + w_settings_shell_list->do_callback(); + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); + g_shell_config->rebuild_shell_menu(); + } +} + +Fl_Button *w_settings_shell_remove=(Fl_Button *)0; + +static void cb_w_settings_shell_remove(Fl_Button* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v==LOAD) { + if (selected) { + o->activate(); + } else { + o->deactivate(); + } + } else { + if (!selected) return; + g_shell_config->remove(selected-1); + w_settings_shell_list->remove(selected); + if (selected <= w_settings_shell_list->size()) + w_settings_shell_list->value(selected); + else + w_settings_shell_list->value(0); + w_settings_shell_list->do_callback(); + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); + g_shell_config->rebuild_shell_menu(); + } +} + +Fl_Menu_Button *w_settings_shell_menu=(Fl_Menu_Button *)0; + +static void cb_Import(Fl_Menu_*, void* v) { + if (v != LOAD) + Fd_Shell_Command_List::import_from_file(); +} + +static void cb_Export(Fl_Menu_*, void* v) { + if (v != LOAD) + Fd_Shell_Command_List::export_selected(); +} + +Fl_Menu_Item menu_w_settings_shell_menu[] = { + {"Import...", 0, (Fl_Callback*)cb_Import, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"Export selected...", 0, (Fl_Callback*)cb_Export, 0, 128, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"Import Example Scripts:", 0, 0, 0, 1, (uchar)FL_NORMAL_LABEL, 1, 10, 0}, + {"Compile with fltk-config", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"Build and run", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"Build with Xcode on macOS", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"Build with CMake", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +Fl_Button *w_settings_shell_play=(Fl_Button *)0; + +static void cb_w_settings_shell_play(Fl_Button* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v==LOAD) { + if (selected) { + o->activate(); + } else { + o->deactivate(); + } + } else { + if (!selected) return; + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->run(); + } +} + +Fl_Group *w_settings_shell_cmd=(Fl_Group *)0; + +static void cb_w_settings_shell_cmd(Fl_Group* o, void* v) { + if (v==LOAD) { + int selected = w_settings_shell_list_selected; + if (selected) { + o->activate(); + } else { + o->deactivate(); + } + propagate_load(o, v); + } +} + +static void cb_Name(Fl_Input* o, void* v) { + int selected = w_settings_shell_list_selected; if (v == LOAD) { - o->value(g_shell_save_fl); + if (selected) { + o->value(g_shell_config->list[selected-1]->name.c_str()); + } else { + o->value(""); + } } else { - g_shell_save_fl = o->value(); + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->name = o->value(); + w_settings_shell_list->text(selected, o->value()); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } } } -static void cb_save1(Fl_Check_Button* o, void* v) { +static void cb_Label(Fl_Input* o, void* v) { + int selected = w_settings_shell_list_selected; if (v == LOAD) { - o->value(g_shell_save_code); + if (selected) { + o->value(g_shell_config->list[selected-1]->label.c_str()); + } else { + o->value(""); + } } else { - g_shell_save_code = o->value(); + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->label = o->value(); + cmd->update_shell_menu(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } } } -static void cb_save2(Fl_Check_Button* o, void* v) { +static void cb_Shortcut(Fl_Shortcut_Button* o, void* v) { + int selected = w_settings_shell_list_selected; if (v == LOAD) { - o->value(g_shell_save_strings); + if (selected) { + o->value(g_shell_config->list[selected-1]->shortcut); + o->default_value(o->value()); + } else { + o->value(0); + } + } else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->shortcut = o->value(); + cmd->update_shell_menu(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } + } +} + +static void cb_Store(Fl_Choice* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v == LOAD) { + if (selected) { + Fd_Tool_Store ts = g_shell_config->list[selected-1]->storage; + o->value(o->find_item_with_argument((long)ts)); + } else { + o->value(o->find_item_with_argument((long)FD_STORE_USER)); + } } else { - g_shell_save_strings = o->value(); + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + Fd_Tool_Store ts = (Fd_Tool_Store)(o->mvalue()->argument()); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + cmd->storage = ts; + //w_settings_shell_list->text(selected, cmd->name.c_str()); + if (cmd->storage == FD_STORE_USER) + w_settings_shell_list->icon(selected, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + w_settings_shell_list->icon(selected, w_settings_shell_fd_project->image()); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } } } -Fl_Check_Button *shell_use_fl_button=(Fl_Check_Button *)0; +Fl_Menu_Item menu_Store[] = { + {"@fd_user User Setting", 0, 0, (void*)(FD_STORE_USER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"@fd_project Project File", 0, 0, (void*)(FD_STORE_PROJECT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {0,0,0,0,0,0,0,0,0} +}; -static void cb_shell_use_fl_button(Fl_Check_Button* o, void* v) { +static void cb_Condition(Fl_Choice* o, void* v) { + int selected = w_settings_shell_list_selected; if (v == LOAD) { - o->value(g_shell_use_fl_settings); + if (selected) { + int cond = g_shell_config->list[selected-1]->condition; + o->value(o->find_item_with_argument(cond)); + } else { + o->value(o->find_item_with_argument(0)); + } } else { - g_shell_use_fl_settings = o->value(); - fluid_prefs.set("shell_use_fl", g_shell_use_fl_settings); - if (g_shell_use_fl_settings) { - shell_settings_read(); + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int cond = (int)(o->mvalue()->argument()); + cmd->condition = cond; + g_shell_config->rebuild_shell_menu(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } + } +} + +Fl_Menu_Item menu_Condition[] = { + {"all platforms", 0, 0, (void*)(Fd_Shell_Command::ALWAYS), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"MS Windows only", 0, 0, (void*)(Fd_Shell_Command::WIN_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"Linux only", 0, 0, (void*)(Fd_Shell_Command::UX_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"macOS only", 0, 0, (void*)(Fd_Shell_Command::MAC_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"Linux and macOS", 0, 0, (void*)(Fd_Shell_Command::MAC_AND_UX_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"don\'t use", 0, 0, (void*)(Fd_Shell_Command::NEVER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +static void cb_Label1(Fl_Input* o, void* v) { + if (v == LOAD) { + // o->value(g_shell_command.c_str()); + } else { + // g_shell_command = o->value(); + } +} + +Fl_Text_Editor *w_settings_shell_command=(Fl_Text_Editor *)0; + +static void cb_w_settings_shell_command(Fl_Text_Editor* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v == LOAD) { + if (selected) { + o->buffer()->text(g_shell_config->list[selected-1]->command.c_str()); } else { - shell_prefs_get(); + o->buffer()->text(""); + } + } else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->command = o->buffer()->text(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } - w_settings_shell_tab->do_callback(w_settings_shell_tab, LOAD); } } -static void cb_save3(Fl_Button*, void* v) { - if (v != LOAD) - shell_prefs_set(); +Fl_Menu_Button *w_settings_shell_text_macros=(Fl_Menu_Button *)0; + +static void cb_w_settings_shell_text_macros(Fl_Menu_Button* o, void*) { + const Fl_Menu_Item *mi = o->mvalue(); + if (mi) { + char buffer[256]; + fl_strlcpy(buffer, mi->label(), 255); + int n = (int)strlen(buffer)-1; + if (buffer[n]=='@') buffer[n] = 0; + char *word = buffer; + if (word[0]=='@') word++; + if (w_settings_shell_command->buffer()->selected()) { + int start = 0, end = 0; + w_settings_shell_command->buffer()->selection_position(&start, &end); + w_settings_shell_command->buffer()->replace(start, end, word); + } else { + int pos = w_settings_shell_command->insert_position(); + w_settings_shell_command->buffer()->insert(pos, word); + } + w_settings_shell_command->do_callback(w_settings_shell_command, (void*)NULL); + } +} + +Fl_Menu_Item menu_w_settings_shell_text_macros[] = { + {"@@BASENAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@PROJECTFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@PROJECTFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@CODEFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@CODEFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@HEADERFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@HEADERFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@TEXTFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@TEXTFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + // Not yet implemented + {"@@FLTK_CONFIG@@", 0, 0, 0, 16, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {"@@TMPDIR@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +static void cb_square(Fl_Button*, void*) { + if (!script_panel) make_script_panel(); + script_input->buffer()->text(w_settings_shell_command->buffer()->text()); + script_panel->show(); + + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == script_panel_cancel) goto BREAK2; + else if (w == script_panel_ok) break; + else if (!w) Fl::wait(); + } + + w_settings_shell_command->buffer()->text(script_input->buffer()->text()); + w_settings_shell_command->do_callback(); + BREAK2: + script_panel->hide(); +} + +static void cb_save(Fl_Check_Button* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_PROJECT); + } else { + o->value(0); + } + } else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int v = o->value(); + if (v) { + cmd->flags |= Fd_Shell_Command::SAVE_PROJECT; + } else { + cmd->flags &= ~Fd_Shell_Command::SAVE_PROJECT; + } + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } + } +} + +static void cb_save1(Fl_Check_Button* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_SOURCECODE); + } else { + o->value(0); + } + } else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int v = o->value(); + if (v) { + cmd->flags |= Fd_Shell_Command::SAVE_SOURCECODE; + } else { + cmd->flags &= ~Fd_Shell_Command::SAVE_SOURCECODE; + } + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } + } +} + +static void cb_save2(Fl_Check_Button* o, void* v) { + int selected = w_settings_shell_list_selected; + if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_STRINGS); + } else { + o->value(0); + } + } else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int v = o->value(); + if (v) { + cmd->flags |= Fd_Shell_Command::SAVE_STRINGS; + } else { + cmd->flags &= ~Fd_Shell_Command::SAVE_STRINGS; + } + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } + } +} + +Fl_Box *w_settings_shell_fd_project=(Fl_Box *)0; + +static const unsigned char idata_fd_project[] = +{137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0, +115,122,122,244,0,0,1,110,105,67,67,80,105,99,99,0,0,40,145,117,145,187,75,195, +80,20,198,127,173,239,23,14,58,136,116,200,80,197,65,65,20,196,81,235,208,165, +72,169,21,172,186,180,49,109,133,164,13,73,139,136,171,224,226,80,112,16,93, +124,13,254,7,186,10,174,10,130,160,8,34,110,238,190,22,145,120,174,45,180,136, +189,225,230,252,248,238,253,14,39,95,192,31,49,117,203,109,156,2,43,87,112,98, +225,144,182,144,88,212,90,94,104,163,153,46,2,244,39,117,215,158,142,70,35,212, +93,159,119,248,84,189,29,81,189,234,223,251,119,117,172,24,174,14,190,86,225,9, +221,118,10,194,50,13,145,181,130,173,120,91,184,87,207,38,87,132,15,133,135,29, +25,80,248,74,233,169,50,63,43,206,148,249,93,177,19,143,205,128,95,245,212,50, +53,156,170,97,61,235,88,194,67,194,65,203,44,234,149,121,212,151,116,26,185, +249,57,169,253,178,3,184,196,8,19,66,35,69,145,85,76,10,140,72,205,73,102,255, +251,70,127,125,179,228,197,163,203,219,102,29,71,28,25,178,226,29,22,181,40,93, +13,169,105,209,13,121,76,214,85,238,127,243,116,211,227,99,229,238,157,33,104, +122,242,188,183,1,104,217,129,239,146,231,125,29,121,222,247,49,52,60,194,69, +174,234,207,75,78,147,31,162,151,170,90,240,0,186,55,225,236,178,170,165,118, +225,124,11,250,30,236,164,147,252,149,26,100,251,211,105,120,61,133,174,4,244, +220,64,251,82,57,171,202,57,39,247,16,223,144,95,116,13,123,251,48,40,247,187, +151,127,0,229,44,103,253,189,250,32,75,0,0,0,9,112,72,89,115,0,0,22,37,0,0,22, +37,1,73,82,36,240,0,0,1,13,116,69,88,116,82,97,119,32,112,114,111,102,105,108, +101,32,116,121,112,101,32,101,120,105,102,0,10,101,120,105,102,10,32,32,32,32, +32,49,49,52,10,52,53,55,56,54,57,54,54,48,48,48,48,52,57,52,57,50,97,48,48,48, +56,48,48,48,48,48,48,48,52,48,48,49,97,48,49,48,53,48,48,48,49,48,48,48,48,48, +48,51,101,48,48,48,48,48,48,49,98,48,49,48,53,48,48,48,49,48,48,48,48,48,48,10, +52,54,48,48,48,48,48,48,50,56,48,49,48,51,48,48,48,49,48,48,48,48,48,48,48,50, +48,48,48,48,48,48,54,57,56,55,48,52,48,48,48,49,48,48,48,48,48,48,52,101,48,48, +48,48,48,48,48,48,48,48,48,48,48,48,57,48,48,48,48,48,48,48,10,48,49,48,48,48, +48,48,48,57,48,48,48,48,48,48,48,48,49,48,48,48,48,48,48,48,50,48,48,48,50,97, +48,48,52,48,48,48,49,48,48,48,48,48,48,53,50,48,48,48,48,48,48,48,51,97,48,48, +52,48,48,48,49,48,48,48,48,48,48,56,48,48,48,10,48,48,48,48,48,48,48,48,48,48, +48,48,10,190,225,144,105,0,0,0,90,116,69,88,116,82,97,119,32,112,114,111,102, +105,108,101,32,116,121,112,101,32,105,112,116,99,0,10,105,112,116,99,10,32,32, +32,32,32,32,50,54,10,53,48,54,56,54,102,55,52,54,102,55,51,54,56,54,102,55,48, +50,48,51,51,50,101,51,48,48,48,51,56,52,50,52,57,52,100,48,52,48,52,48,48,48, +48,48,48,48,48,48,48,48,48,10,199,209,105,220,0,0,20,96,116,69,88,116,82,97, +119,32,112,114,111,102,105,108,101,32,116,121,112,101,32,120,109,112,0,10,120, +109,112,10,32,32,32,32,50,53,53,53,10,51,99,51,102,55,56,55,48,54,49,54,51,54, +98,54,53,55,52,50,48,54,50,54,53,54,55,54,57,54,101,51,100,50,50,101,102,98,98, +98,102,50,50,50,48,54,57,54,52,51,100,50,50,53,55,51,53,52,100,51,48,52,100,55, +48,52,51,54,53,54,56,54,57,10,52,56,55,97,55,50,54,53,53,51,55,97,52,101,53,52, +54,51,55,97,54,98,54,51,51,57,54,52,50,50,51,102,51,101,48,97,51,99,55,56,51, +97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,50,48,55,56,54,100,54,99,54,101, +55,51,51,97,55,56,10,51,100,50,50,54,49,54,52,54,102,54,50,54,53,51,97,54,101, +55,51,51,97,54,100,54,53,55,52,54,49,50,102,50,50,50,48,55,56,51,97,55,56,54, +100,55,48,55,52,54,98,51,100,50,50,53,56,52,100,53,48,50,48,52,51,54,102,55,50, +54,53,50,48,10,51,52,50,101,51,52,50,101,51,48,50,100,52,53,55,56,54,57,55,54, +51,50,50,50,51,101,48,97,50,48,51,99,55,50,54,52,54,54,51,97,53,50,52,52,52,54, +50,48,55,56,54,100,54,99,54,101,55,51,51,97,55,50,54,52,54,54,51,100,50,50,54, +56,10,55,52,55,52,55,48,51,97,50,102,50,102,55,55,55,55,55,55,50,101,55,55,51, +51,50,101,54,102,55,50,54,55,50,102,51,49,51,57,51,57,51,57,50,102,51,48,51,50, +50,102,51,50,51,50,50,100,55,50,54,52,54,54,50,100,55,51,55,57,54,101,55,52,10, +54,49,55,56,50,100,54,101,55,51,50,51,50,50,51,101,48,97,50,48,50,48,51,99,55, +50,54,52,54,54,51,97,52,52,54,53,55,51,54,51,55,50,54,57,55,48,55,52,54,57,54, +102,54,101,50,48,55,50,54,52,54,54,51,97,54,49,54,50,54,102,55,53,10,55,52,51, +100,50,50,50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51, +51,97,54,53,55,56,54,57,54,54,51,100,50,50,54,56,55,52,55,52,55,48,51,97,50, +102,50,102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,10,50,101,54,51, +54,102,54,100,50,102,54,53,55,56,54,57,54,54,50,102,51,49,50,101,51,48,50,102, +50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51,51,97,55, +52,54,57,54,54,54,54,51,100,50,50,54,56,55,52,55,52,55,48,10,51,97,50,102,50, +102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,50,101,54,51,54,102,54, +100,50,102,55,52,54,57,54,54,54,54,50,102,51,49,50,101,51,48,50,102,50,50,48,97, +50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53,48,10,54,57,55,56,54,53,54, +99,53,56,52,52,54,57,54,100,54,53,54,101,55,51,54,57,54,102,54,101,51,100,50, +50,51,56,51,50,50,50,48,97,50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53, +48,54,57,55,56,54,53,54,99,53,57,52,52,54,57,10,54,100,54,53,54,101,55,51,54, +57,54,102,54,101,51,100,50,50,51,49,51,50,51,56,50,50,48,97,50,48,50,48,50,48, +55,52,54,57,54,54,54,54,51,97,53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57, +54,102,54,101,53,53,54,101,54,57,55,52,10,51,100,50,50,51,50,50,50,48,97,50,48, +50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,57,53,50,54,53,55,51,54,102,54,99, +55,53,55,52,54,57,54,102,54,101,51,100,50,50,51,49,51,52,51,52,50,48,50,102,50, +48,51,49,50,50,48,97,50,48,10,50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,56, +53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57,54,102,54,101,51,100,50,50,51, +49,51,52,51,52,50,48,50,102,50,48,51,49,50,50,50,102,51,101,48,97,50,48,51,99, +50,102,55,50,54,52,10,54,54,51,97,53,50,52,52,52,54,51,101,48,97,51,99,50,102, +55,56,51,97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,51,101,48,97,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,10,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,48, +97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,10,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,10,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48, +97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,48,97,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,10,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,51,99,51,102,55,56,55,48,54,49, +54,51,54,98,54,53,55,52,50,48,54,53,54,101,54,52,51,100,50,50,55,55,50,50,51, +102,51,101,10,87,123,188,247,0,0,3,115,73,68,65,84,88,71,189,151,75,75,91,65,20, +199,79,110,222,169,52,180,203,22,186,239,210,47,80,236,206,126,5,177,17,151,46, +68,23,82,220,138,90,84,116,163,184,80,81,132,98,93,234,42,203,210,79,209,149, +32,213,68,164,165,165,129,230,97,94,246,252,166,157,246,246,102,154,132,230, +226,31,134,59,247,204,153,243,158,123,207,68,206,206,206,164,86,171,73,52,26, +149,68,34,17,175,84,42,215,123,123,123,15,119,118,118,164,23,26,141,134,164,211, +105,243,28,29,29,149,229,229,229,183,177,88,236,101,171,213,106,235,83,154,205, +166,120,158,39,145,72,196,12,23,188,106,181,42,201,100,82,110,111,111,69,149,55, +246,247,247,139,187,187,187,102,209,110,252,215,200,100,50,162,202,12,111,62, +159,151,211,211,211,49,85,252,70,135,231,212,230,64,44,149,74,201,205,205,141, +196,227,113,97,174,222,84,48,102,102,102,70,230,230,230,186,110,110,183,219,178, +177,177,33,219,219,219,198,129,133,133,5,188,30,27,31,31,71,78,78,89,90,93,5,40, +60,60,32,92,8,168,215,235,120,86,96,129,148,244,138,0,70,219,208,142,140,140, +144,66,89,89,89,145,163,163,163,49,221,255,90,195,31,65,62,60,200,7,240,48,39, +53,198,0,187,96,94,126,230,43,195,28,239,122,129,189,150,111,120,120,88,22,23, +23,13,109,105,105,73,142,143,143,95,169,242,247,42,51,107,249,144,79,202,49, +136,186,1,198,0,191,17,186,88,177,194,123,1,239,134,134,134,76,228,152,79,78,78, +202,250,250,186,137,232,218,218,154,156,156,156,60,211,72,92,43,235,115,60,247, +43,166,238,128,137,67,192,136,102,183,170,245,3,30,45,92,227,25,74,121,78,76, +76,152,72,112,2,168,137,195,195,195,148,210,223,169,226,23,208,40,92,210,203, +201,3,158,205,15,33,98,232,60,101,22,188,222,133,108,235,135,90,64,40,239,200, +154,154,154,50,17,96,190,185,185,73,77,80,224,121,93,127,130,62,12,97,15,48,6, +88,101,254,72,244,19,1,194,138,48,242,74,26,108,152,145,145,203,229,76,65,226, +212,234,234,170,28,28,28,96,228,71,235,168,69,44,24,110,221,156,237,39,255,22, +40,197,155,173,173,45,115,36,153,147,22,66,205,241,198,57,140,164,54,74,165,82, +99,122,122,250,47,71,141,235,129,40,164,131,133,249,47,16,242,96,85,227,29,133, +201,187,149,107,63,116,58,10,24,131,209,22,158,221,4,51,2,117,67,201,127,110, +187,1,190,249,249,121,185,188,188,148,98,177,40,87,87,87,102,126,126,126,110, +230,133,66,65,46,46,46,100,118,118,214,242,127,192,32,127,10,92,149,246,217,65, +11,11,159,130,4,151,1,53,7,45,44,60,8,18,92,6,60,114,208,194,66,35,72,112,25, +80,113,208,194,66,50,72,112,25,240,205,65,11,11,55,65,194,93,167,160,175,8,68, +29,180,176,224,142,0,103,211,254,163,245,140,86,59,247,253,31,252,95,216,95, +243,108,144,199,21,129,14,166,16,113,63,72,112,25,80,119,208,194,194,215,32,193, +101,64,104,41,112,160,28,36,220,117,10,238,5,9,119,157,130,14,125,46,3,254,252, +43,195,71,51,72,112,25,240,197,65,11,11,29,245,229,217,179,106,155,10,237,104, +154,253,180,228,253,2,153,246,142,161,207,36,223,26,123,155,2,30,139,86,33,237, +148,246,118,41,255,197,97,16,160,148,238,135,214,140,161,198,52,81,110,47,39, +224,119,71,196,176,157,45,253,28,173,211,160,176,109,25,45,25,50,213,193,199, +190,27,152,225,137,209,159,99,17,30,151,203,101,218,236,44,52,154,76,90,234,65, +128,34,228,250,90,246,136,255,29,196,176,206,118,175,58,79,232,226,83,24,236, +213,122,16,176,223,94,207,73,175,70,249,59,81,177,117,128,158,31,49,127,246,30, +207,181,170,20,0,0,0,0,73,69,78,68,174,66,96,130}; +static Fl_Image *image_fd_project() { + static Fl_Image *image = NULL; + if (!image) + image = new Fl_PNG_Image("fd_project.png", idata_fd_project, 6950); + return image; } -static void cb_Run(Fl_Return_Button*, void* v) { - if (v != LOAD) - do_shell_command(NULL, NULL); +Fl_Box *w_settings_shell_fd_user=(Fl_Box *)0; + +static const unsigned char idata_fd_user[] = +{137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0, +115,122,122,244,0,0,1,110,105,67,67,80,105,99,99,0,0,40,145,117,145,187,75,195, +80,20,198,127,173,239,23,14,58,136,116,200,80,197,65,65,20,196,81,235,208,165, +72,169,21,172,186,180,49,109,133,164,13,73,139,136,171,224,226,80,112,16,93, +124,13,254,7,186,10,174,10,130,160,8,34,110,238,190,22,145,120,174,45,180,136, +189,225,230,252,248,238,253,14,39,95,192,31,49,117,203,109,156,2,43,87,112,98, +225,144,182,144,88,212,90,94,104,163,153,46,2,244,39,117,215,158,142,70,35,212, +93,159,119,248,84,189,29,81,189,234,223,251,119,117,172,24,174,14,190,86,225,9, +221,118,10,194,50,13,145,181,130,173,120,91,184,87,207,38,87,132,15,133,135,29, +25,80,248,74,233,169,50,63,43,206,148,249,93,177,19,143,205,128,95,245,212,50, +53,156,170,97,61,235,88,194,67,194,65,203,44,234,149,121,212,151,116,26,185, +249,57,169,253,178,3,184,196,8,19,66,35,69,145,85,76,10,140,72,205,73,102,255, +251,70,127,125,179,228,197,163,203,219,102,29,71,28,25,178,226,29,22,181,40,93, +13,169,105,209,13,121,76,214,85,238,127,243,116,211,227,99,229,238,157,33,104, +122,242,188,183,1,104,217,129,239,146,231,125,29,121,222,247,49,52,60,194,69, +174,234,207,75,78,147,31,162,151,170,90,240,0,186,55,225,236,178,170,165,118, +225,124,11,250,30,236,164,147,252,149,26,100,251,211,105,120,61,133,174,4,244, +220,64,251,82,57,171,202,57,39,247,16,223,144,95,116,13,123,251,48,40,247,187, +151,127,0,229,44,103,253,189,250,32,75,0,0,0,9,112,72,89,115,0,0,22,37,0,0,22, +37,1,73,82,36,240,0,0,1,13,116,69,88,116,82,97,119,32,112,114,111,102,105,108, +101,32,116,121,112,101,32,101,120,105,102,0,10,101,120,105,102,10,32,32,32,32, +32,49,49,52,10,52,53,55,56,54,57,54,54,48,48,48,48,52,57,52,57,50,97,48,48,48, +56,48,48,48,48,48,48,48,52,48,48,49,97,48,49,48,53,48,48,48,49,48,48,48,48,48, +48,51,101,48,48,48,48,48,48,49,98,48,49,48,53,48,48,48,49,48,48,48,48,48,48,10, +52,54,48,48,48,48,48,48,50,56,48,49,48,51,48,48,48,49,48,48,48,48,48,48,48,50, +48,48,48,48,48,48,54,57,56,55,48,52,48,48,48,49,48,48,48,48,48,48,52,101,48,48, +48,48,48,48,48,48,48,48,48,48,48,48,57,48,48,48,48,48,48,48,10,48,49,48,48,48, +48,48,48,57,48,48,48,48,48,48,48,48,49,48,48,48,48,48,48,48,50,48,48,48,50,97, +48,48,52,48,48,48,49,48,48,48,48,48,48,53,50,48,48,48,48,48,48,48,51,97,48,48, +52,48,48,48,49,48,48,48,48,48,48,56,48,48,48,10,48,48,48,48,48,48,48,48,48,48, +48,48,10,190,225,144,105,0,0,0,90,116,69,88,116,82,97,119,32,112,114,111,102, +105,108,101,32,116,121,112,101,32,105,112,116,99,0,10,105,112,116,99,10,32,32, +32,32,32,32,50,54,10,53,48,54,56,54,102,55,52,54,102,55,51,54,56,54,102,55,48, +50,48,51,51,50,101,51,48,48,48,51,56,52,50,52,57,52,100,48,52,48,52,48,48,48, +48,48,48,48,48,48,48,48,48,10,199,209,105,220,0,0,20,96,116,69,88,116,82,97, +119,32,112,114,111,102,105,108,101,32,116,121,112,101,32,120,109,112,0,10,120, +109,112,10,32,32,32,32,50,53,53,53,10,51,99,51,102,55,56,55,48,54,49,54,51,54, +98,54,53,55,52,50,48,54,50,54,53,54,55,54,57,54,101,51,100,50,50,101,102,98,98, +98,102,50,50,50,48,54,57,54,52,51,100,50,50,53,55,51,53,52,100,51,48,52,100,55, +48,52,51,54,53,54,56,54,57,10,52,56,55,97,55,50,54,53,53,51,55,97,52,101,53,52, +54,51,55,97,54,98,54,51,51,57,54,52,50,50,51,102,51,101,48,97,51,99,55,56,51, +97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,50,48,55,56,54,100,54,99,54,101, +55,51,51,97,55,56,10,51,100,50,50,54,49,54,52,54,102,54,50,54,53,51,97,54,101, +55,51,51,97,54,100,54,53,55,52,54,49,50,102,50,50,50,48,55,56,51,97,55,56,54, +100,55,48,55,52,54,98,51,100,50,50,53,56,52,100,53,48,50,48,52,51,54,102,55,50, +54,53,50,48,10,51,52,50,101,51,52,50,101,51,48,50,100,52,53,55,56,54,57,55,54, +51,50,50,50,51,101,48,97,50,48,51,99,55,50,54,52,54,54,51,97,53,50,52,52,52,54, +50,48,55,56,54,100,54,99,54,101,55,51,51,97,55,50,54,52,54,54,51,100,50,50,54, +56,10,55,52,55,52,55,48,51,97,50,102,50,102,55,55,55,55,55,55,50,101,55,55,51, +51,50,101,54,102,55,50,54,55,50,102,51,49,51,57,51,57,51,57,50,102,51,48,51,50, +50,102,51,50,51,50,50,100,55,50,54,52,54,54,50,100,55,51,55,57,54,101,55,52,10, +54,49,55,56,50,100,54,101,55,51,50,51,50,50,51,101,48,97,50,48,50,48,51,99,55, +50,54,52,54,54,51,97,52,52,54,53,55,51,54,51,55,50,54,57,55,48,55,52,54,57,54, +102,54,101,50,48,55,50,54,52,54,54,51,97,54,49,54,50,54,102,55,53,10,55,52,51, +100,50,50,50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51, +51,97,54,53,55,56,54,57,54,54,51,100,50,50,54,56,55,52,55,52,55,48,51,97,50, +102,50,102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,10,50,101,54,51, +54,102,54,100,50,102,54,53,55,56,54,57,54,54,50,102,51,49,50,101,51,48,50,102, +50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51,51,97,55, +52,54,57,54,54,54,54,51,100,50,50,54,56,55,52,55,52,55,48,10,51,97,50,102,50, +102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,50,101,54,51,54,102,54, +100,50,102,55,52,54,57,54,54,54,54,50,102,51,49,50,101,51,48,50,102,50,50,48,97, +50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53,48,10,54,57,55,56,54,53,54, +99,53,56,52,52,54,57,54,100,54,53,54,101,55,51,54,57,54,102,54,101,51,100,50, +50,51,56,51,50,50,50,48,97,50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53, +48,54,57,55,56,54,53,54,99,53,57,52,52,54,57,10,54,100,54,53,54,101,55,51,54, +57,54,102,54,101,51,100,50,50,51,49,51,50,51,56,50,50,48,97,50,48,50,48,50,48, +55,52,54,57,54,54,54,54,51,97,53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57, +54,102,54,101,53,53,54,101,54,57,55,52,10,51,100,50,50,51,50,50,50,48,97,50,48, +50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,57,53,50,54,53,55,51,54,102,54,99, +55,53,55,52,54,57,54,102,54,101,51,100,50,50,51,49,51,52,51,52,50,48,50,102,50, +48,51,49,50,50,48,97,50,48,10,50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,56, +53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57,54,102,54,101,51,100,50,50,51, +49,51,52,51,52,50,48,50,102,50,48,51,49,50,50,50,102,51,101,48,97,50,48,51,99, +50,102,55,50,54,52,10,54,54,51,97,53,50,52,52,52,54,51,101,48,97,51,99,50,102, +55,56,51,97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,51,101,48,97,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,10,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,48, +97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,10,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,10,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48, +97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,48,97,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,10,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, +48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, +50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,51,99,51,102,55,56,55,48,54,49, +54,51,54,98,54,53,55,52,50,48,54,53,54,101,54,52,51,100,50,50,55,55,50,50,51, +102,51,101,10,87,123,188,247,0,0,9,241,73,68,65,84,88,71,109,87,105,144,85,197, +21,254,186,239,242,222,155,25,102,88,12,14,46,227,16,96,12,26,80,118,103,16, +113,3,5,89,203,10,70,75,42,106,170,48,196,16,141,154,20,18,177,8,41,21,149,82, +81,244,71,48,166,42,75,37,96,22,29,5,9,155,131,37,139,16,65,113,153,25,71,8,66, +153,165,148,137,226,204,91,238,210,55,223,233,251,30,49,58,77,53,115,223,237, +190,167,207,249,206,57,223,57,173,218,59,223,128,163,92,104,147,32,138,12,84, +162,225,58,62,100,36,137,66,38,147,65,177,88,4,31,225,186,46,130,56,134,210,9, +188,140,139,158,82,30,78,198,65,20,26,238,5,60,237,91,57,242,157,231,184,8,75,1, +148,82,118,130,223,12,168,27,152,62,127,97,104,3,23,9,52,226,242,76,228,173,50, +118,81,169,4,249,124,15,5,198,86,160,85,138,135,185,78,22,189,61,37,104,30,104, +98,5,87,103,184,158,227,51,191,113,249,206,24,132,97,152,202,41,79,101,13,74, +240,229,225,26,83,131,68,203,193,49,12,2,24,45,31,184,246,35,199,113,64,120,104, +177,139,222,82,137,104,228,16,169,88,187,137,250,238,137,79,62,251,246,238,93, +187,250,83,232,137,113,227,199,71,77,77,77,71,78,22,78,222,149,209,94,41,227, +249,68,165,68,153,148,65,52,42,255,250,26,174,67,200,211,161,211,153,104,139, +136,60,151,104,133,235,106,68,38,132,118,29,132,145,25,250,139,103,158,217,186, +105,227,214,97,199,143,253,131,240,41,56,70,67,211,13,67,134,12,198,236,249,215, +220,178,112,225,245,187,170,171,252,233,132,58,53,216,162,233,244,121,184,12, +213,217,222,97,31,100,183,5,138,10,40,229,88,248,5,21,223,23,69,138,242,46,179, +252,222,159,183,183,190,176,121,104,130,44,178,153,254,152,56,102,10,98,198,196, +161,183,246,163,55,255,31,120,185,24,87,207,188,20,15,220,191,242,128,49,193, +196,40,14,98,71,149,229,81,137,218,218,218,20,213,47,12,87,39,97,89,1,5,35,112, +241,3,109,53,151,169,24,3,69,56,158,118,215,172,121,114,127,235,11,155,134,122, +110,45,150,46,125,16,45,205,151,211,184,156,85,160,95,181,135,109,59,94,194,170, +71,238,69,235,11,127,197,160,1,3,198,222,241,163,239,63,79,9,179,147,10,242, +125,123,128,56,19,70,9,26,9,52,135,24,136,66,137,138,184,196,103,122,194,247, +125,245,234,206,221,109,191,122,246,119,163,20,170,112,255,202,53,184,184,249, +106,6,99,21,181,118,224,185,89,20,243,6,151,77,189,6,203,151,61,4,159,10,62,251, +203,223,98,223,190,191,141,75,143,48,167,142,234,35,6,233,70,30,46,43,137,157, +113,249,131,116,138,117,68,166,186,189,189,115,50,19,18,115,103,45,192,248,177, +23,35,10,178,60,184,14,90,101,9,105,22,97,192,248,40,41,76,110,158,134,185,179, +175,227,59,31,7,14,188,233,126,249,176,190,178,160,18,129,68,168,156,50,246,111, +100,115,93,16,160,207,146,55,15,190,131,160,148,96,204,133,205,40,246,42,248,78, +53,24,151,20,232,160,144,15,80,83,221,143,252,193,12,9,52,206,251,198,88,196, +92,123,243,224,161,56,149,92,65,160,239,161,157,47,40,165,202,81,43,239,44,26, +212,56,8,130,248,224,129,3,240,189,44,134,15,111,66,198,175,161,229,220,39,123, +153,1,53,53,57,20,11,198,198,144,239,229,48,98,68,19,60,47,131,183,223,126,183, +88,62,162,143,99,255,55,180,48,147,107,35,228,203,27,211,223,76,195,184,177, +177,129,86,149,112,244,232,17,166,98,17,145,216,38,228,198,45,226,127,215,35, +123,122,224,90,47,142,29,63,76,18,42,161,190,190,254,36,18,221,135,220,175,156, +162,203,169,167,210,116,41,127,36,40,72,124,184,218,137,167,78,157,130,108,149, +135,182,157,91,200,7,12,80,29,17,58,11,144,245,171,226,239,48,250,156,73,219, +131,215,118,109,227,122,140,25,51,102,100,42,178,83,37,250,118,133,85,47,34,158, +9,179,65,38,148,87,230,1,199,42,101,146,200,204,152,57,237,125,147,228,177, +243,181,205,120,175,99,31,81,233,229,222,34,21,76,200,142,204,29,174,105,175, +136,119,59,247,98,123,91,171,85,104,250,244,43,125,77,6,53,166,98,28,229,39,95, +85,66,71,41,251,83,63,42,65,14,168,40,18,89,10,117,108,38,12,31,209,120,83,115, +203,120,148,130,147,184,231,222,219,177,105,243,6,120,126,36,52,129,124,177,100, +41,124,71,219,75,88,198,181,56,233,193,228,201,147,208,216,216,56,75,228,168, +50,11,138,187,84,31,222,176,172,35,100,33,22,11,92,177,74,103,197,119,36,33,81, +111,207,83,79,175,217,187,224,186,121,40,20,63,197,99,143,63,136,205,91,90,89, +17,149,240,4,182,110,219,132,135,30,89,137,124,161,27,243,230,207,196,186,103, +158,218,67,22,125,79,170,171,84,80,97,191,40,138,208,91,232,65,108,34,235,182, +34,43,101,41,40,165,65,104,161,150,169,211,103,85,174,15,162,152,148,226,32,40, +18,137,112,206,178,101,75,183,141,190,224,124,107,49,139,55,74,20,98,40,208, +247,61,6,102,128,81,163,206,199,138,21,247,173,47,20,10,45,130,105,38,227,217, +170,88,98,33,75,203,112,130,79,79,118,227,147,238,19,164,238,188,157,172,39,14, +9,141,126,42,79,139,136,69,37,101,66,177,192,243,60,233,11,62,102,74,62,76,82, +162,50,9,38,76,152,96,149,148,67,46,188,112,12,171,90,6,29,29,93,193,231,159,23, +158,20,223,107,126,28,70,37,155,214,242,189,252,22,20,4,101,73,83,249,93,118, +129,197,223,22,159,116,166,164,45,127,197,255,217,108,214,30,24,4,17,118,239, +126,61,137,194,4,35,207,29,133,65,3,79,39,180,202,90,87,83,93,135,97,67,207,101, +63,224,153,3,111,28,202,184,174,239,136,229,41,145,41,203,41,34,75,179,204,139, +65,50,108,191,192,227,221,83,197,226,212,72,35,213,214,114,250,174,187,187,155, +188,190,79,255,229,207,47,206,223,183,247,157,135,227,64,161,101,210,101,164,94, +32,173,90,160,146,53,152,48,126,10,142,28,237,204,254,224,182,59,159,187,100, +202,164,127,206,155,63,235,195,150,150,139,158,173,170,170,122,217,36,113,94,24, +95,14,15,67,246,29,236,92,114,185,156,85,66,181,119,118,88,6,252,127,69,82,37, +94,106,221,56,106,245,234,71,175,232,62,209,51,203,113,170,91,76,224,231,38,76, +184,20,75,190,119,23,206,58,123,56,203,116,10,181,75,234,62,246,81,39,158,88, +187,10,239,180,239,71,18,247,218,56,169,98,149,252,241,79,238,196,220,185,179, +47,247,60,231,21,81,34,117,133,177,127,5,25,213,222,222,14,169,136,142,231,218, +128,50,73,32,10,12,88,187,246,233,59,215,173,251,245,45,42,169,61,99,120,227,88, +76,155,190,0,83,155,175,68,255,65,131,105,56,59,7,82,95,28,146,176,24,55,137, +229,112,33,167,8,255,254,248,24,118,182,109,196,43,109,47,163,189,243,32,15,138, +177,232,214,155,112,251,29,183,77,85,137,121,53,45,72,58,45,76,68,80,189,253, +214,33,194,209,207,194,33,41,215,211,243,233,232,229,203,151,255,126,203,150,29, +231,185,172,120,75,22,255,20,211,167,221,72,70,172,163,94,14,164,159,8,36,152,0, +219,204,74,200,136,44,9,48,41,227,174,71,106,87,228,6,213,139,23,95,124,14,79, +174,125,136,27,3,92,50,181,217,172,121,124,245,24,173,205,33,203,158,182,81,165, +225,75,126,184,132,86,211,227,180,202,209,222,153,119,223,125,207,235,219,183, +239,110,168,171,61,3,43,239,123,156,254,190,10,85,85,167,161,80,136,88,130,93, +27,88,68,144,169,71,146,226,193,177,73,27,78,66,12,135,235,113,28,165,5,149, +194,217,39,226,155,163,70,99,207,174,93,248,224,112,151,58,124,164,107,241,244, +171,166,29,103,237,56,40,116,45,25,161,125,95,160,15,108,239,199,96,187,97,103, +219,158,129,190,219,31,171,87,173,195,216,11,46,99,233,29,192,146,27,157,138, +222,82,41,141,232,56,182,201,99,93,32,214,136,95,77,148,240,119,134,41,153,35, +186,213,136,131,12,198,140,190,24,143,174,94,135,154,220,215,176,99,251,107,120, +125,239,254,7,136,182,170,196,154,14,216,239,101,115,210,5,71,151,175,88,249, +179,165,33,133,44,188,97,49,154,190,62,142,66,171,73,48,20,200,86,91,14,9,73,54, +174,207,190,136,133,73,44,141,227,52,88,45,205,10,141,11,125,115,198,180,44,138, +121,71,64,127,148,242,62,70,142,156,136,57,115,174,167,66,46,86,63,242,196,32, +130,214,84,9,119,45,36,81,40,244,158,182,97,195,134,223,124,208,245,193,192,179, +207,26,134,111,93,187,144,13,8,157,29,123,105,59,109,42,221,140,177,129,26,210, +223,18,197,158,167,109,129,137,152,86,202,94,92,202,118,73,185,230,118,135,37, +211,247,170,17,20,20,22,222,120,11,59,231,6,116,117,29,118,159,127,190,117,69, +84,142,35,29,209,145,142,155,61,255,15,235,255,116,70,93,221,233,184,249,59, +139,104,5,153,138,157,175,133,88,167,80,11,2,162,172,237,106,89,5,227,40,96,239, +79,74,54,129,205,0,197,12,136,19,42,39,237,16,247,243,106,192,192,78,121,223, +146,26,207,91,116,235,98,42,31,99,195,31,215,79,114,41,75,134,155,48,178,185, +195,59,114,248,56,130,162,143,230,139,166,216,194,164,43,209,29,167,85,76,243, +191,48,76,155,28,199,241,108,76,164,205,108,74,90,70,114,154,123,36,150,4,21, +113,179,40,171,29,9,204,34,41,187,26,227,199,93,100,255,190,223,113,204,72,44, +249,76,101,22,35,15,135,187,62,26,98,34,31,67,234,207,177,27,148,244,134,210, +116,136,134,101,4,36,215,229,224,180,175,55,246,112,197,158,80,131,190,86,25,72, +95,85,25,210,97,185,90,89,235,131,82,104,175,114,48,164,97,93,139,51,235,155, +104,168,151,251,232,248,103,20,202,119,212,86,31,61,122,108,149,4,80,67,67,131, +189,136,228,195,30,114,127,129,26,74,235,205,128,67,234,83,200,83,249,222,152, +118,58,94,249,89,242,46,172,108,42,95,195,180,101,87,47,35,233,202,106,232,196, +168,98,176,15,30,124,26,254,254,161,170,233,234,234,194,208,198,122,81,52,202, +53,156,51,196,44,186,245,230,127,13,169,111,200,38,186,23,253,6,120,82,231,221, +176,196,226,159,208,145,112,107,172,97,9,97,81,9,159,217,14,33,166,242,18,73, +230,4,103,29,223,243,217,94,114,184,238,68,118,63,97,36,82,174,152,47,212,204, +238,14,243,174,189,2,19,155,135,117,203,225,246,210,218,222,241,22,3,134,23,84, +238,147,74,103,27,19,11,113,26,120,114,249,176,150,90,139,203,237,112,5,133,83, +163,124,159,80,105,166,84,154,25,123,221,51,105,57,150,247,65,216,203,236,81, +116,89,108,93,41,107,255,5,119,155,194,247,64,241,254,70,0,0,0,0,73,69,78,68, +174,66,96,130}; +static Fl_Image *image_fd_user() { + static Fl_Image *image = NULL; + if (!image) + image = new Fl_PNG_Image("fd_user.png", idata_fd_user, 8612); + return image; } Fl_Group *w_settings_i18n_tab=(Fl_Group *)0; @@ -1011,6 +2091,9 @@ static void cb_i18n_pos_set_input(Fl_Int_Input* o, void* v) { } static void cb_Close(Fl_Button*, void*) { + if (g_shell_config) + g_shell_config->write(fluid_prefs, FD_STORE_USER); + g_layout_list.write(fluid_prefs, FD_STORE_USER); settings_window->hide(); } @@ -1527,50 +2610,153 @@ ped using octal notation `\\0123`. If this option is checked, Fluid will write\ w_settings_shell_tab->labelsize(11); w_settings_shell_tab->callback((Fl_Callback*)cb_w_settings_shell_tab); w_settings_shell_tab->hide(); - { Fl_Input* o = new Fl_Input(100, 78, 220, 20, "Command:"); - o->tooltip("external shell command"); - o->labelfont(1); - o->labelsize(11); - o->textfont(4); - o->textsize(11); - o->callback((Fl_Callback*)cb_Command); - } // Fl_Input* o - { Fl_Check_Button* o = new Fl_Check_Button(100, 98, 220, 20, "save .fl project file"); - o->tooltip("save the project to the .fl file before running the command"); - o->down_box(FL_DOWN_BOX); - o->labelsize(11); - o->callback((Fl_Callback*)cb_save); - } // Fl_Check_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(100, 118, 220, 19, "save source code"); - o->tooltip("generate the source code and header file before running the command"); - o->down_box(FL_DOWN_BOX); - o->labelsize(11); - o->callback((Fl_Callback*)cb_save1); - } // Fl_Check_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(100, 137, 220, 20, "save i18n strings"); - o->tooltip("save the internationalisation string before running the command"); - o->down_box(FL_DOWN_BOX); - o->labelsize(11); - o->callback((Fl_Callback*)cb_save2); - } // Fl_Check_Button* o - { shell_use_fl_button = new Fl_Check_Button(100, 194, 220, 19, "save settings in .fl project files"); - shell_use_fl_button->tooltip("check to read and write shell command from and to .fl files"); - shell_use_fl_button->down_box(FL_DOWN_BOX); - shell_use_fl_button->labelsize(11); - shell_use_fl_button->callback((Fl_Callback*)cb_shell_use_fl_button); - shell_use_fl_button->deactivate(); - } // Fl_Check_Button* shell_use_fl_button - { Fl_Button* o = new Fl_Button(100, 218, 115, 20, "save as default"); - o->tooltip("update the Fluid app settings for external shell commands to the current sett\ -ings"); - o->labelsize(11); - o->callback((Fl_Callback*)cb_save3); - } // Fl_Button* o - { Fl_Return_Button* o = new Fl_Return_Button(100, 162, 100, 20, "Run"); - o->tooltip("save selected files and run the command"); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Run); - } // Fl_Return_Button* o + { w_settings_shell_list = new Fl_Browser(100, 90, 220, 110, "Shell \ncommand \nlist:"); + w_settings_shell_list->type(3); + w_settings_shell_list->labelfont(1); + w_settings_shell_list->labelsize(11); + w_settings_shell_list->textsize(13); + w_settings_shell_list->callback((Fl_Callback*)cb_w_settings_shell_list); + w_settings_shell_list->align(Fl_Align(FL_ALIGN_LEFT)); + } // Fl_Browser* w_settings_shell_list + { w_settings_shell_toolbox = new Fl_Group(100, 200, 220, 22); + w_settings_shell_toolbox->callback((Fl_Callback*)cb_w_settings_shell_toolbox); + { Fl_Button* o = new Fl_Button(100, 200, 24, 22, "+"); + o->labelsize(11); + o->callback((Fl_Callback*)cb_8); + } // Fl_Button* o + { w_settings_shell_dup = new Fl_Button(124, 200, 24, 22, "++"); + w_settings_shell_dup->labelsize(11); + w_settings_shell_dup->callback((Fl_Callback*)cb_w_settings_shell_dup); + w_settings_shell_dup->deactivate(); + } // Fl_Button* w_settings_shell_dup + { w_settings_shell_remove = new Fl_Button(148, 200, 24, 22, "-"); + w_settings_shell_remove->labelsize(11); + w_settings_shell_remove->callback((Fl_Callback*)cb_w_settings_shell_remove); + w_settings_shell_remove->deactivate(); + } // Fl_Button* w_settings_shell_remove + { w_settings_shell_menu = new Fl_Menu_Button(172, 200, 24, 22); + w_settings_shell_menu->labelsize(11); + w_settings_shell_menu->textsize(11); + w_settings_shell_menu->menu(menu_w_settings_shell_menu); + } // Fl_Menu_Button* w_settings_shell_menu + { w_settings_shell_play = new Fl_Button(270, 200, 50, 22, "Run"); + w_settings_shell_play->labelsize(11); + w_settings_shell_play->callback((Fl_Callback*)cb_w_settings_shell_play); + w_settings_shell_play->deactivate(); + } // Fl_Button* w_settings_shell_play + w_settings_shell_toolbox->end(); + } // Fl_Group* w_settings_shell_toolbox + { w_settings_shell_cmd = new Fl_Group(10, 235, 320, 291); + w_settings_shell_cmd->callback((Fl_Callback*)cb_w_settings_shell_cmd); + { Fl_Input* o = new Fl_Input(100, 246, 220, 20, "Name:"); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)cb_Name); + o->when(FL_WHEN_RELEASE | FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY); + } // Fl_Input* o + { Fl_Input* o = new Fl_Input(100, 272, 220, 20, "Label:"); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)cb_Label); + } // Fl_Input* o + { Fl_Shortcut_Button* o = new Fl_Shortcut_Button(100, 297, 130, 20, "Shortcut"); + o->box(FL_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->callback((Fl_Callback*)cb_Shortcut); + o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); + o->when(FL_WHEN_RELEASE); + } // Fl_Shortcut_Button* o + { Fl_Choice* o = new Fl_Choice(100, 322, 130, 20, "Store:"); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)cb_Store); + o->menu(menu_Store); + } // Fl_Choice* o + { Fl_Choice* o = new Fl_Choice(100, 348, 130, 20, "Condition:"); + o->down_box(FL_BORDER_BOX); + o->labelfont(1); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)cb_Condition); + o->menu(menu_Condition); + } // Fl_Choice* o + { Fl_Input* o = new Fl_Input(230, 348, 90, 20, "Label:"); + o->labelfont(1); + o->labelsize(11); + o->textfont(4); + o->textsize(11); + o->callback((Fl_Callback*)cb_Label1); + o->hide(); + } // Fl_Input* o + { Fl_Text_Editor* o = w_settings_shell_command = new Fl_Text_Editor(100, 373, 196, 80, "Shell script:"); + w_settings_shell_command->labelfont(1); + w_settings_shell_command->labelsize(11); + w_settings_shell_command->textfont(4); + w_settings_shell_command->textsize(12); + w_settings_shell_command->callback((Fl_Callback*)cb_w_settings_shell_command); + w_settings_shell_command->align(Fl_Align(FL_ALIGN_LEFT)); + o->buffer(new Fl_Text_Buffer); + } // Fl_Text_Editor* w_settings_shell_command + { Fl_Group* o = new Fl_Group(296, 373, 24, 44); + { w_settings_shell_text_macros = new Fl_Menu_Button(296, 373, 24, 22); + w_settings_shell_text_macros->labelsize(11); + w_settings_shell_text_macros->textsize(11); + w_settings_shell_text_macros->callback((Fl_Callback*)cb_w_settings_shell_text_macros); + w_settings_shell_text_macros->menu(menu_w_settings_shell_text_macros); + } // Fl_Menu_Button* w_settings_shell_text_macros + { Fl_Button* o = new Fl_Button(296, 395, 24, 22, "@square"); + o->tooltip("open big code editor"); + o->labelsize(11); + o->labelcolor(FL_BACKGROUND_COLOR); + o->callback((Fl_Callback*)cb_square); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Check_Button* o = new Fl_Check_Button(100, 458, 220, 20, "save .fl project file"); + o->tooltip("save the project to the .fl file before running the command"); + o->down_box(FL_DOWN_BOX); + o->labelsize(11); + o->callback((Fl_Callback*)cb_save); + } // Fl_Check_Button* o + { Fl_Check_Button* o = new Fl_Check_Button(100, 478, 220, 19, "save source code"); + o->tooltip("generate the source code and header file before running the command"); + o->down_box(FL_DOWN_BOX); + o->labelsize(11); + o->callback((Fl_Callback*)cb_save1); + } // Fl_Check_Button* o + { Fl_Check_Button* o = new Fl_Check_Button(100, 497, 220, 20, "save i18n strings"); + o->tooltip("save the internationalisation strings before running the command"); + o->down_box(FL_DOWN_BOX); + o->labelsize(11); + o->callback((Fl_Callback*)cb_save2); + } // Fl_Check_Button* o + w_settings_shell_cmd->end(); + } // Fl_Group* w_settings_shell_cmd + { Fl_Box* o = w_settings_shell_fd_project = new Fl_Box(20, 70, 16, 15); + w_settings_shell_fd_project->bind_image( image_fd_project() ); + w_settings_shell_fd_project->labelsize(11); + w_settings_shell_fd_project->hide(); + w_settings_shell_fd_project->deactivate(); + o->image()->scale(16, 16); + } // Fl_Box* w_settings_shell_fd_project + { Fl_Box* o = w_settings_shell_fd_user = new Fl_Box(20, 70, 16, 15); + w_settings_shell_fd_user->bind_image( image_fd_user() ); + w_settings_shell_fd_user->labelsize(11); + w_settings_shell_fd_user->hide(); + w_settings_shell_fd_user->deactivate(); + o->image()->scale(16, 16); + } // Fl_Box* w_settings_shell_fd_user o->image()->scale(36, 24); w_settings_shell_tab->end(); } // Fl_Group* w_settings_shell_tab @@ -1676,7 +2862,6 @@ le FLTK_GETTEXT_FOUND"); o->labelsize(11); o->callback((Fl_Callback*)cb_Close); } // Fl_Button* o - settings_window->set_non_modal(); settings_window->end(); } // Fl_Double_Window* settings_window w_settings_tabs->do_callback(w_settings_tabs, LOAD); diff --git a/fluid/alignment_panel.fl b/fluid/alignment_panel.fl index da80df3a4..ef9d48455 100644 --- a/fluid/alignment_panel.fl +++ b/fluid/alignment_panel.fl @@ -4,7 +4,7 @@ header_name {.h} code_name {.cxx} snap { ver 1 - current_suite FLTK + current_suite {FLUID (based on FLTK)} current_preset 0 suite { name {FLUID (based on FLTK)} @@ -91,6 +91,9 @@ decl {\#include <FL/fl_ask.H>} {private global decl {\#include <string.h>} {private global } +decl {\#include "../src/flstring.h"} {private global +} + decl {void init_scheme(void);} { comment {// initialize the scheme from preferences} public global } @@ -104,11 +107,49 @@ decl {extern void i18n_cb(Fl_Choice *,void *);} {public local decl {void scheme_cb(Fl_Scheme_Choice *, void *);} {public local } +decl {int w_settings_shell_list_selected;} {public local +} + +Function {make_script_panel()} {open +} { + Fl_Window script_panel { + label {Shell Script Editor} + callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) + return; // ignore Escape +script_panel->hide(); // otherwise hide..} open + xywh {764 319 540 180} type Double labelsize 11 resizable + code0 {o->size_range(200, 150);} modal visible + } { + Fl_Text_Editor script_input { + xywh {10 10 520 130} box DOWN_BOX labelsize 11 when 13 textfont 4 textsize 11 resizable + code0 {script_input->buffer(new Fl_Text_Buffer);} + } + Fl_Group {} {open + xywh {10 150 520 20} labelsize 11 + } { + Fl_Return_Button script_panel_ok { + label OK + xywh {400 150 60 20} labelsize 11 hotspot + } + Fl_Button script_panel_cancel { + label Cancel + xywh {470 150 60 20} labelsize 11 + } + Fl_Box {} { + xywh {10 150 380 20} labelsize 11 resizable + } + } + } + code {// Enable line numbers +script_input->linenumber_width(60); +script_input->linenumber_size(script_input->Fl_Text_Display::textsize());} {} +} + Function {make_settings_window()} {open } { Fl_Window settings_window { label {FLUID Settings} open - xywh {423 204 340 580} type Double align 80 non_modal visible + xywh {392 362 340 580} type Double align 80 visible } { Fl_Tabs w_settings_tabs { callback {propagate_load(o, v);} open @@ -758,73 +799,528 @@ g_layout_list.update_dialogs();} } Fl_Group w_settings_shell_tab { label Shell - callback {propagate_load(o, v);} + callback {propagate_load(o, v);} open image {icons/shell_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide code0 {o->image()->scale(36, 24);} } { - Fl_Input {} { - label {Command:} + Fl_Browser w_settings_shell_list { + label {Shell +command +list:} callback {if (v == LOAD) { - o->value(g_shell_command.c_str()); + // load from g_shell_config + if (g_shell_config) { + o->clear(); + w_settings_shell_list_selected = 0; + for (int i=0; i<g_shell_config->list_size; i++) { + Fd_Shell_Command *cmd = g_shell_config->list[i]; + o->add(cmd->name.c_str()); + if (cmd->storage == FD_STORE_USER) + o->icon(i+1, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + o->icon(i+1, w_settings_shell_fd_project->image()); + } + } } else { - g_shell_command = o->value(); +// int prev_selected = w_settings_shell_list_selected; + w_settings_shell_list_selected = 0; + int selected = w_settings_shell_list->value(); + if (selected) { + if (w_settings_shell_list->selected(selected)) + w_settings_shell_list_selected = selected; + } + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); }} - tooltip {external shell command} xywh {100 78 220 20} labelfont 1 labelsize 11 textfont 4 textsize 11 + xywh {100 90 220 110} type Multi labelfont 1 labelsize 11 align 4 textsize 13 } - Fl_Check_Button {} { - label {save .fl project file} - callback {if (v == LOAD) { - o->value(g_shell_save_fl); + Fl_Group w_settings_shell_toolbox { + callback {if (v==LOAD) { + propagate_load(o, v); +}} open + xywh {100 200 220 22} + } { + Fl_Button {} { + label {+} + callback {if (v != LOAD) { + int selected = w_settings_shell_list_selected; + Fd_Shell_Command *cmd = new Fd_Shell_Command("new shell command"); + g_shell_config->insert(selected, cmd); + w_settings_shell_list->insert(selected+1, cmd->name.c_str()); + w_settings_shell_list->deselect(); + w_settings_shell_list->value(selected+1); + if (cmd->storage == FD_STORE_USER) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); + w_settings_shell_list->do_callback(); + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); + g_shell_config->rebuild_shell_menu(); +}} + xywh {100 200 24 22} labelsize 11 + } + Fl_Button w_settings_shell_dup { + label {++} + callback {int selected = w_settings_shell_list_selected; +if (v==LOAD) { + if (selected) { + o->activate(); + } else { + o->deactivate(); + } } else { - g_shell_save_fl = o->value(); + if (!selected) return; + Fd_Shell_Command *cmd = new Fd_Shell_Command(g_shell_config->list[selected-1]); + g_shell_config->insert(selected, cmd); + w_settings_shell_list->insert(selected+1, cmd->name.c_str()); + w_settings_shell_list->deselect(); + w_settings_shell_list->deselect(); + w_settings_shell_list->value(selected+1); + if (cmd->storage == FD_STORE_USER) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); + w_settings_shell_list->do_callback(); + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); + g_shell_config->rebuild_shell_menu(); }} - tooltip {save the project to the .fl file before running the command} xywh {100 98 220 20} down_box DOWN_BOX labelsize 11 - } - Fl_Check_Button {} { - label {save source code} - callback {if (v == LOAD) { - o->value(g_shell_save_code); + xywh {124 200 24 22} labelsize 11 deactivate + } + Fl_Button w_settings_shell_remove { + label {-} + callback {int selected = w_settings_shell_list_selected; +if (v==LOAD) { + if (selected) { + o->activate(); + } else { + o->deactivate(); + } } else { - g_shell_save_code = o->value(); + if (!selected) return; + g_shell_config->remove(selected-1); + w_settings_shell_list->remove(selected); + if (selected <= w_settings_shell_list->size()) + w_settings_shell_list->value(selected); + else + w_settings_shell_list->value(0); + w_settings_shell_list->do_callback(); + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); + g_shell_config->rebuild_shell_menu(); }} - tooltip {generate the source code and header file before running the command} xywh {100 118 220 19} down_box DOWN_BOX labelsize 11 - } - Fl_Check_Button {} { - label {save i18n strings} - callback {if (v == LOAD) { - o->value(g_shell_save_strings); + xywh {148 200 24 22} labelsize 11 deactivate + } + Fl_Menu_Button w_settings_shell_menu {open + xywh {172 200 24 22} labelsize 11 textsize 11 + } { + MenuItem {} { + label {Import...} + callback {if (v != LOAD) + Fd_Shell_Command_List::import_from_file();} + xywh {90 90 100 20} labelsize 11 + } + MenuItem {} { + label {Export selected...} + callback {if (v != LOAD) + Fd_Shell_Command_List::export_selected();} + xywh {10 10 100 20} labelsize 11 divider + } + MenuItem {} { + label {Import Example Scripts:} + xywh {20 20 100 20} labelfont 1 labelsize 10 deactivate + } + MenuItem {} { + label {Compile with fltk-config} + xywh {30 30 100 20} labelsize 11 + } + MenuItem {} { + label {Build and run} + xywh {40 40 100 20} labelsize 11 + } + MenuItem {} { + label {Build with Xcode on macOS} + xywh {50 50 100 20} labelsize 11 + } + MenuItem {} { + label {Build with CMake} + xywh {60 60 100 20} labelsize 11 + } + } + Fl_Button w_settings_shell_play { + label Run + callback {int selected = w_settings_shell_list_selected; +if (v==LOAD) { + if (selected) { + o->activate(); + } else { + o->deactivate(); + } } else { - g_shell_save_strings = o->value(); + if (!selected) return; + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->run(); }} - tooltip {save the internationalisation string before running the command} xywh {100 137 220 20} down_box DOWN_BOX labelsize 11 + xywh {270 200 50 22} labelsize 11 deactivate + } } - Fl_Check_Button shell_use_fl_button { - label {save settings in .fl project files} - callback {if (v == LOAD) { - o->value(g_shell_use_fl_settings); + Fl_Group w_settings_shell_cmd { + callback {if (v==LOAD) { + int selected = w_settings_shell_list_selected; + if (selected) { + o->activate(); + } else { + o->deactivate(); + } + propagate_load(o, v); +}} open + xywh {10 235 320 291} + } { + Fl_Input {} { + label {Name:} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->name.c_str()); + } else { + o->value(""); + } } else { - g_shell_use_fl_settings = o->value(); - fluid_prefs.set("shell_use_fl", g_shell_use_fl_settings); - if (g_shell_use_fl_settings) { - shell_settings_read(); + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->name = o->value(); + w_settings_shell_list->text(selected, o->value()); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} + xywh {100 246 220 20} labelfont 1 labelsize 11 when 13 textfont 4 textsize 11 + } + Fl_Input {} { + label {Label:} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->label.c_str()); } else { - shell_prefs_get(); + o->value(""); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->label = o->value(); + cmd->update_shell_menu(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } - w_settings_shell_tab->do_callback(w_settings_shell_tab, LOAD); }} - tooltip {check to read and write shell command from and to .fl files} xywh {100 194 220 19} down_box DOWN_BOX labelsize 11 deactivate + xywh {100 272 220 20} labelfont 1 labelsize 11 textfont 4 textsize 11 + } + Fl_Button {} { + label Shortcut + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->shortcut); + o->default_value(o->value()); + } else { + o->value(0); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->shortcut = o->value(); + cmd->update_shell_menu(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} + xywh {100 297 130 20} labelsize 11 align 16 + code0 {\#include <FL/Fl_Shortcut_Button.H>} + class Fl_Shortcut_Button + } + Fl_Choice {} { + label {Store:} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + Fd_Tool_Store ts = g_shell_config->list[selected-1]->storage; + o->value(o->find_item_with_argument((long)ts)); + } else { + o->value(o->find_item_with_argument((long)FD_STORE_USER)); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + Fd_Tool_Store ts = (Fd_Tool_Store)(o->mvalue()->argument()); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + cmd->storage = ts; + //w_settings_shell_list->text(selected, cmd->name.c_str()); + if (cmd->storage == FD_STORE_USER) + w_settings_shell_list->icon(selected, w_settings_shell_fd_user->image()); + else if (cmd->storage == FD_STORE_PROJECT) + w_settings_shell_list->icon(selected, w_settings_shell_fd_project->image()); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} open + xywh {100 322 130 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 + } { + MenuItem {} { + label {@fd_user User Setting} + user_data FD_STORE_USER user_data_type long + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {@fd_project Project File} + user_data FD_STORE_PROJECT user_data_type long + xywh {0 0 100 20} labelsize 11 + } + } + Fl_Choice {} { + label {Condition:} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + int cond = g_shell_config->list[selected-1]->condition; + o->value(o->find_item_with_argument(cond)); + } else { + o->value(o->find_item_with_argument(0)); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int cond = (int)(o->mvalue()->argument()); + cmd->condition = cond; + g_shell_config->rebuild_shell_menu(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} open + xywh {100 348 130 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 + } { + MenuItem {} { + label {all platforms} + user_data {Fd_Shell_Command::ALWAYS} user_data_type long + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {MS Windows only} + user_data {Fd_Shell_Command::WIN_ONLY} user_data_type long + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {Linux only} + user_data {Fd_Shell_Command::UX_ONLY} user_data_type long + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {macOS only} + user_data {Fd_Shell_Command::MAC_ONLY} user_data_type long + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {Linux and macOS} + user_data {Fd_Shell_Command::MAC_AND_UX_ONLY} user_data_type long + xywh {0 0 100 20} labelsize 11 + } + MenuItem {} { + label {don't use} + user_data {Fd_Shell_Command::NEVER} user_data_type long + xywh {0 0 100 20} labelsize 11 + } + } + Fl_Input {} { + label {Label:} + callback {if (v == LOAD) { +// o->value(g_shell_command.c_str()); +} else { +// g_shell_command = o->value(); +}} + xywh {230 348 90 20} labelfont 1 labelsize 11 textfont 4 textsize 11 hide + } + Fl_Text_Editor w_settings_shell_command { + label {Shell script:} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + o->buffer()->text(g_shell_config->list[selected-1]->command.c_str()); + } else { + o->buffer()->text(""); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + cmd->command = o->buffer()->text(); + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} + xywh {100 373 196 80} labelfont 1 labelsize 11 align 4 textfont 4 textsize 12 + code0 {o->buffer(new Fl_Text_Buffer);} + } + Fl_Group {} {open + xywh {296 373 24 44} + } { + Fl_Menu_Button w_settings_shell_text_macros { + callback {const Fl_Menu_Item *mi = o->mvalue(); +if (mi) { + char buffer[256]; + fl_strlcpy(buffer, mi->label(), 255); + int n = (int)strlen(buffer)-1; + if (buffer[n]=='@') buffer[n] = 0; + char *word = buffer; + if (word[0]=='@') word++; + if (w_settings_shell_command->buffer()->selected()) { + int start = 0, end = 0; + w_settings_shell_command->buffer()->selection_position(&start, &end); + w_settings_shell_command->buffer()->replace(start, end, word); + } else { + int pos = w_settings_shell_command->insert_position(); + w_settings_shell_command->buffer()->insert(pos, word); + } + w_settings_shell_command->do_callback(w_settings_shell_command, (void*)NULL); +}} open + xywh {296 373 24 22} labelsize 11 textsize 11 + } { + MenuItem {} { + label {@@BASENAME@@} + xywh {80 80 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@PROJECTFILE_PATH@@} + xywh {0 0 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@PROJECTFILE_NAME@@} + xywh {10 10 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@CODEFILE_PATH@@} + xywh {20 20 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@CODEFILE_NAME@@} + xywh {30 30 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@HEADERFILE_PATH@@} + xywh {40 40 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@HEADERFILE_NAME@@} + xywh {50 50 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@TEXTFILE_PATH@@} + xywh {60 60 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@TEXTFILE_NAME@@} + xywh {70 70 100 20} labelfont 4 labelsize 11 + } + MenuItem {} { + label {@@FLTK_CONFIG@@} + comment {Not yet implemented} + xywh {70 70 100 20} labelfont 4 labelsize 11 hide + } + MenuItem {} { + label {@@TMPDIR@@} + xywh {70 70 100 20} labelfont 4 labelsize 11 + } + } + Fl_Button {} { + label {@square} + callback {if (!script_panel) make_script_panel(); +script_input->buffer()->text(w_settings_shell_command->buffer()->text()); +script_panel->show(); + +for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == script_panel_cancel) goto BREAK2; + else if (w == script_panel_ok) break; + else if (!w) Fl::wait(); +} + +w_settings_shell_command->buffer()->text(script_input->buffer()->text()); +w_settings_shell_command->do_callback(); +BREAK2: +script_panel->hide();} + tooltip {open big code editor} xywh {296 395 24 22} labelsize 11 labelcolor 49 + } + } + Fl_Check_Button {} { + label {save .fl project file} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_PROJECT); + } else { + o->value(0); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int v = o->value(); + if (v) { + cmd->flags |= Fd_Shell_Command::SAVE_PROJECT; + } else { + cmd->flags &= ~Fd_Shell_Command::SAVE_PROJECT; + } + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} + tooltip {save the project to the .fl file before running the command} xywh {100 458 220 20} down_box DOWN_BOX labelsize 11 + } + Fl_Check_Button {} { + label {save source code} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_SOURCECODE); + } else { + o->value(0); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int v = o->value(); + if (v) { + cmd->flags |= Fd_Shell_Command::SAVE_SOURCECODE; + } else { + cmd->flags &= ~Fd_Shell_Command::SAVE_SOURCECODE; + } + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} + tooltip {generate the source code and header file before running the command} xywh {100 478 220 19} down_box DOWN_BOX labelsize 11 + } + Fl_Check_Button {} { + label {save i18n strings} + callback {int selected = w_settings_shell_list_selected; +if (v == LOAD) { + if (selected) { + o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_STRINGS); + } else { + o->value(0); + } +} else { + if (selected) { + Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; + int v = o->value(); + if (v) { + cmd->flags |= Fd_Shell_Command::SAVE_STRINGS; + } else { + cmd->flags &= ~Fd_Shell_Command::SAVE_STRINGS; + } + if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + } +}} + tooltip {save the internationalisation strings before running the command} xywh {100 497 220 20} down_box DOWN_BOX labelsize 11 + } } - Fl_Button {} { - label {save as default} - callback {if (v != LOAD) - shell_prefs_set();} - tooltip {update the Fluid app settings for external shell commands to the current settings} xywh {100 218 115 20} labelsize 11 + Fl_Box w_settings_shell_fd_project { + image {pixmaps/fd_project.png} compress_image 1 bind_image 1 bind_deimage 1 xywh {20 70 16 15} labelsize 11 hide deactivate + code0 {o->image()->scale(16, 16);} } - Fl_Return_Button {} { - label Run - callback {if (v != LOAD) - do_shell_command(NULL, NULL);} - tooltip {save selected files and run the command} xywh {100 162 100 20} labelsize 11 + Fl_Box w_settings_shell_fd_user { + image {pixmaps/fd_user.png} compress_image 1 bind_image 1 bind_deimage 1 xywh {20 70 16 15} labelsize 11 hide deactivate + code0 {o->image()->scale(16, 16);} } } Fl_Group w_settings_i18n_tab { @@ -953,7 +1449,10 @@ g_layout_list.update_dialogs();} } Fl_Button {} { label Close - callback {settings_window->hide();} + callback {if (g_shell_config) + g_shell_config->write(fluid_prefs, FD_STORE_USER); +g_layout_list.write(fluid_prefs, FD_STORE_USER); +settings_window->hide();} tooltip {Close this dialog.} xywh {230 550 100 20} labelsize 11 } } diff --git a/fluid/alignment_panel.h b/fluid/alignment_panel.h index a084917b3..932398ee5 100644 --- a/fluid/alignment_panel.h +++ b/fluid/alignment_panel.h @@ -35,14 +35,23 @@ void init_scheme(void); extern struct Fl_Menu_Item *dbmanager_item; extern void i18n_cb(Fl_Choice *,void *); extern void scheme_cb(Fl_Scheme_Choice *, void *); +extern int w_settings_shell_list_selected; #include <FL/Fl_Double_Window.H> +extern Fl_Double_Window *script_panel; +#include <FL/Fl_Text_Editor.H> +extern Fl_Text_Editor *script_input; +#include <FL/Fl_Group.H> +#include <FL/Fl_Return_Button.H> +extern Fl_Return_Button *script_panel_ok; +#include <FL/Fl_Button.H> +extern Fl_Button *script_panel_cancel; +#include <FL/Fl_Box.H> +Fl_Double_Window* make_script_panel(); extern Fl_Double_Window *settings_window; #include <FL/Fl_Tabs.H> extern Fl_Tabs *w_settings_tabs; -#include <FL/Fl_Group.H> extern void scheme_cb(Fl_Scheme_Choice*, void*); extern Fl_Scheme_Choice *scheme_choice; -#include <FL/Fl_Box.H> #include <FL/Fl_Check_Button.H> extern Fl_Check_Button *tooltips_button; extern Fl_Check_Button *completion_button; @@ -68,7 +77,6 @@ extern Fl_Check_Button *avoid_early_includes_button; extern Fl_Group *w_settings_layout_tab; #include <FL/Fl_Choice.H> extern Fl_Choice *layout_choice; -#include <FL/Fl_Button.H> #include <FL/Fl_Menu_Button.H> extern Fl_Menu_Button *w_layout_menu; #include <FL/Fl_Native_File_Chooser.H> @@ -78,8 +86,19 @@ extern Fl_Button *preset_choice[3]; #include <FL/Fl_Value_Input.H> extern Fl_Menu_Item fontmenu_w_default[]; extern Fl_Group *w_settings_shell_tab; -extern Fl_Check_Button *shell_use_fl_button; -#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Browser.H> +extern Fl_Browser *w_settings_shell_list; +extern Fl_Group *w_settings_shell_toolbox; +extern Fl_Button *w_settings_shell_dup; +extern Fl_Button *w_settings_shell_remove; +extern Fl_Menu_Button *w_settings_shell_menu; +extern Fl_Button *w_settings_shell_play; +extern Fl_Group *w_settings_shell_cmd; +#include <FL/Fl_Shortcut_Button.H> +extern Fl_Text_Editor *w_settings_shell_command; +extern Fl_Menu_Button *w_settings_shell_text_macros; +extern Fl_Box *w_settings_shell_fd_project; +extern Fl_Box *w_settings_shell_fd_user; extern Fl_Group *w_settings_i18n_tab; extern void i18n_type_cb(Fl_Choice*, void*); extern Fl_Choice *i18n_type_chooser; @@ -102,6 +121,10 @@ extern Fl_Menu_Item *w_layout_menu_storage[4]; #define w_layout_menu_load (menu_w_layout_menu+5) #define w_layout_menu_save (menu_w_layout_menu+6) #define w_layout_menu_delete (menu_w_layout_menu+7) +extern Fl_Menu_Item menu_w_settings_shell_menu[]; +extern Fl_Menu_Item menu_Store[]; +extern Fl_Menu_Item menu_Condition[]; +extern Fl_Menu_Item menu_w_settings_shell_text_macros[]; extern Fl_Menu_Item menu_i18n_type_chooser[]; extern Fl_Double_Window *shell_run_window; #include <FL/Fl_Simple_Terminal.H> diff --git a/fluid/file.cxx b/fluid/file.cxx index 163b41dee..d93a71a1a 100644 --- a/fluid/file.cxx +++ b/fluid/file.cxx @@ -137,7 +137,7 @@ int Fd_Project_Reader::open_read(const char *s) { fin = stdin; fname = "stdin"; } else { - FILE *f = fl_fopen(s,"r"); + FILE *f = fl_fopen(s, "r"); if (!f) return 0; fin = f; @@ -325,29 +325,12 @@ void Fd_Project_Reader::read_children(Fl_Type *p, int paste, Strategy strategy, goto CONTINUE; } - if (strcmp(c, "win_shell_cmd")==0) { - if (shell_settings_windows.command) - free((void*)shell_settings_windows.command); - shell_settings_windows.command = fl_strdup(read_word()); - goto CONTINUE; - } else if (strcmp(c, "win_shell_flags")==0) { - shell_settings_windows.flags = atoi(read_word()); - goto CONTINUE; - } else if (strcmp(c, "linux_shell_cmd")==0) { - if (shell_settings_linux.command) - free((void*)shell_settings_linux.command); - shell_settings_linux.command = fl_strdup(read_word()); - goto CONTINUE; - } else if (strcmp(c, "linux_shell_flags")==0) { - shell_settings_linux.flags = atoi(read_word()); - goto CONTINUE; - } else if (strcmp(c, "mac_shell_cmd")==0) { - if (shell_settings_macos.command) - free((void*)shell_settings_macos.command); - shell_settings_macos.command = fl_strdup(read_word()); - goto CONTINUE; - } else if (strcmp(c, "mac_shell_flags")==0) { - shell_settings_macos.flags = atoi(read_word()); + if (strcmp(c, "shell_commands")==0) { + if (g_shell_config) { + g_shell_config->read(this); + } else { + read_word(); + } goto CONTINUE; } } @@ -431,7 +414,10 @@ int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy st } } selection_changed(Fl_Type::current); - shell_settings_read(); + if (g_shell_config) { + g_shell_config->rebuild_shell_menu(); + g_shell_config->update_settings_dialog(); + } int ret = close_read(); undo_resume(); return ret; @@ -816,23 +802,8 @@ int Fd_Project_Writer::write_project(const char *filename, int selected_only) { write_string("\nheader_name"); write_word(g_project.header_file_name.c_str()); write_string("\ncode_name"); write_word(g_project.code_file_name.c_str()); g_layout_list.write(this); -#if 0 - // https://github.com/fltk/fltk/issues/328 - // Project wide settings require a redesign. - shell_settings_write(); - if (shell_settings_windows.command) { - write_string("\nwin_shell_cmd"); write_word(shell_settings_windows.command); - write_string("\nwin_shell_flags"); write_string("%d", shell_settings_windows.flags); - } - if (shell_settings_linux.command) { - write_string("\nlinux_shell_cmd"); write_word(shell_settings_linux.command); - write_string("\nlinux_shell_flags"); write_string("%d", shell_settings_linux.flags); - } - if (shell_settings_macos.command) { - write_string("\nmac_shell_cmd"); write_word(shell_settings_macos.command); - write_string("\nmac_shell_flags"); write_string("%d", shell_settings_macos.flags); - } -#endif + if (g_shell_config) + g_shell_config->write(this); } for (Fl_Type *p = Fl_Type::first; p;) { diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx index 9533ecc5d..545a691ec 100644 --- a/fluid/fluid.cxx +++ b/fluid/fluid.cxx @@ -172,6 +172,9 @@ Fl_String g_code_filename_arg; Fl_String g_header_filename_arg; Fl_String g_launch_path; +Fl_String tmpdir_path; +bool tmpdir_create_called = false; + /** \var int Fluid_Project::header_file_set If set, command line overrides header file name in .fl file. */ @@ -311,10 +314,6 @@ void Fluid_Project::reset() { code_file_set = 0; header_file_name = ".h"; code_file_name = ".cxx"; - - g_layout_list.remove_all(FD_STORE_PROJECT); - g_layout_list.current_suite(0); - g_layout_list.current_preset(0); } void Fluid_Project::update_settings_dialog() { @@ -324,6 +323,113 @@ void Fluid_Project::update_settings_dialog() { } } +// make sure that a path name ends with a forward slash +static Fl_String end_with_slash(const Fl_String &str) { + char last = str[str.size()-1]; + if (last !='/' && last != '\\') + return str + "/"; + else + return str; +} + +/** Generate a path to a directory for temporary data storage. + The path is stored in g_tmpdir. + */ +static void create_tmpdir() { + if (tmpdir_create_called) + return; + tmpdir_create_called = true; + + char buf[128]; +#if _WIN32 + // The usual temp file locations on Windows are + // %system%\Windows\Temp + // %userprofiles%\AppData\Local + // usually resolving into + // C:/Windows/Temp/ + // C:\Users\<username>\AppData\Local\Temp + fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId()); + Fl_String name = buf; + wchar_t tempdirW[FL_PATH_MAX+1]; + char tempdir[FL_PATH_MAX+1]; + unsigned len = GetTempPathW(FL_PATH_MAX, tempdirW); + if (len == 0) { + strcpy(tempdir, "c:/windows/temp/"); + } else { + unsigned wn = fl_utf8fromwc(tempdir, FL_PATH_MAX, tempdirW, len); + tempdir[wn] = 0; + } + Fl_String path = tempdir; + end_with_slash(path); + path += name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; +#else + fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", getpid()); + Fl_String name = buf; + Fl_String path = fl_getenv("TMPDIR"); + if (!path.empty()) { + end_with_slash(path); + path += name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; + } + if (tmpdir_path.empty()) { + path = Fl_String("/tmp/") + name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; + } +#endif + if (tmpdir_path.empty()) { + char pbuf[FL_PATH_MAX+1]; + fluid_prefs.get_userdata_path(pbuf, FL_PATH_MAX); + path = Fl_String(pbuf); + end_with_slash(path); + path += name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; + } + if (tmpdir_path.empty()) + fl_alert("Can't create directory for temporary data storage."); +} + +/** Delete the temporary directory that was created in set_tmpdir. */ +static void delete_tmpdir() { + // was a temporary directory created + if (!tmpdir_create_called) + return; + if (tmpdir_path.empty()) + return; + + // first delete all files that may still be left in the temp directory + struct dirent **de; + int n_de = fl_filename_list(tmpdir_path.c_str(), &de); + if (n_de >= 0) { + for (int i=0; i<n_de; i++) { + Fl_String path = tmpdir_path + de[i]->d_name; + fl_unlink(path.c_str()); + } + fl_filename_free_list(&de, n_de); + } + + // then delete the directory itself + if (fl_rmdir(tmpdir_path.c_str()) < 0) { + fl_alert("WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); + } +} + +/** + Return the path to a temporary directory for this instance of FLUID. + Fluid will do its best to clear and delete this directory when exiting. + \return the path to the temporary directory, ending in a '/', or and empty + string is no directory could be created. + */ +const Fl_String &get_tmpdir() { + if (!tmpdir_create_called) + create_tmpdir(); + return tmpdir_path; +} + /** Give the user the opportunity to save a project before clearing it. @@ -397,7 +503,7 @@ void enter_project_dir() { // store the current working directory for later app_work_dir = fl_getcwd(); // set the current directory to the path of our .fl file - Fl_String project_path = fl_filename_path(fl_filename_absolute(Fl_String(filename))); + Fl_String project_path = fl_filename_path(fl_filename_absolute(filename)); if (fl_chdir(project_path.c_str()) == -1) { fprintf(stderr, "** Fluid internal error: enter_project_dir() can't chdir to %s: %s\n", project_path.c_str(), strerror(errno)); @@ -733,6 +839,8 @@ void exit_cb(Fl_Widget *,void *) { if (help_dialog) delete help_dialog; + if (g_shell_config) + g_shell_config->write(fluid_prefs, FD_STORE_USER); g_layout_list.write(fluid_prefs, FD_STORE_USER); undo_clear(); @@ -742,6 +850,7 @@ void exit_cb(Fl_Widget *,void *) { // and cleans up editor tmp files. Then remove fluid tmpdir /last/. g_project.reset(); ExternalCodeEditor::tmpdir_clear(); + delete_tmpdir(); exit(0); } @@ -989,15 +1098,6 @@ void apple_open_cb(const char *c) { } #endif // __APPLE__ -// make sure that a path nae ends with a forward slash -static Fl_String end_with_slash(const Fl_String &str) { - char last = str[str.size()-1]; - if (last !='/' && last != '\\') - return str + "/"; - else - return str; -} - /** Get the absolute path of the project file, for example `/Users/matt/dev/`. */ @@ -1585,10 +1685,7 @@ Fl_Menu_Item Main_Menu[] = { {"Dialog", 0, select_layout_preset_cb, (void*)1, FL_MENU_RADIO }, {"Toolbox", 0, select_layout_preset_cb, (void*)2, FL_MENU_RADIO }, {0}, -{"&Shell",0,0,0,FL_SUBMENU}, - {"Execute &Command...",FL_ALT+'x',(Fl_Callback *)show_shell_window}, - {"Execute &Again...",FL_ALT+'g',(Fl_Callback *)do_shell_command}, - {0}, +{"&Shell", 0, Fd_Shell_Command_List::menu_marker, (void*)Fd_Shell_Command_List::default_menu, FL_SUBMENU_POINTER}, {"&Help",0,0,0,FL_SUBMENU}, {"&Rapid development with FLUID...",0,help_cb}, {"&FLTK Programmers Manual...",0,manual_cb, 0, FL_MENU_DIVIDER}, @@ -1710,7 +1807,6 @@ void make_main_window() { fluid_prefs.get("show_guides", show_guides, 1); fluid_prefs.get("show_restricted", show_restricted, 1); fluid_prefs.get("show_comments", show_comments, 1); - shell_prefs_get(); make_shell_window(); } @@ -1740,6 +1836,9 @@ void make_main_window() { if (!batch_mode) { load_history(); + g_shell_config = new Fd_Shell_Command_List; + // TODO: load example commands if this is the very first time we use this +// g_shell_config->restore_defaults(); make_settings_window(); } } @@ -1851,6 +1950,7 @@ void set_filename(const char *c) { set_modflag(modflag); } + /** Set the "modified" flag and update the title of the main window. @@ -2044,6 +2144,8 @@ int main(int argc,char **argv) { main_window->show(argc,argv); toggle_widgetbin_cb(0,0); toggle_sourceview_cb(0,0); + if (g_shell_config) + g_shell_config->read(fluid_prefs, FD_STORE_USER); g_layout_list.read(fluid_prefs, FD_STORE_USER); if (!c && openlast_button->value() && absolute_history[0][0]) { // Open previous file when no file specified... diff --git a/fluid/fluid.h b/fluid/fluid.h index 024dc61ff..402194edd 100644 --- a/fluid/fluid.h +++ b/fluid/fluid.h @@ -28,6 +28,8 @@ #define MENUHEIGHT 25 #define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT) +// ---- types + class Fl_Double_Window; class Fl_Window; class Fl_Menu_Bar; @@ -36,6 +38,19 @@ class Fl_Choice; class Fl_Button; class Fl_Check_Button; +/** + Indicate the storage location for tools like layout suites and shell macros. + \see class Fd_Shell_Command, class Fd_Layout_Suite + */ +typedef enum { + FD_STORE_INTERNAL, ///< stored inside FLUID app + FD_STORE_USER, ///< suite is stored in the user wide FLUID settings + FD_STORE_PROJECT, ///< suite is stored within the current .fl project file + FD_STORE_FILE ///< store suite in external file +} Fd_Tool_Store; + +// ---- global variables + extern int force_parent; extern Fl_Preferences fluid_prefs; @@ -71,9 +86,6 @@ extern Fl_Check_Button *guides_button; extern int modflag; -extern void enter_project_dir(); -extern void leave_project_dir(); - extern int update_file; // fluid -u extern int compile_file; // fluid -c extern int compile_strings; // fluic -cs @@ -81,7 +93,11 @@ extern int batch_mode; extern int pasteoffset; -// ---- project settings +extern Fl_String g_code_filename_arg; +extern Fl_String g_header_filename_arg; +extern Fl_String g_launch_path; + +// ---- project class declaration class Fluid_Project { public: @@ -123,16 +139,15 @@ public: extern Fluid_Project g_project; -extern Fl_String g_code_filename_arg; -extern Fl_String g_header_filename_arg; -extern Fl_String g_launch_path; - - // ---- public functions +extern void enter_project_dir(); +extern void leave_project_dir(); extern void set_filename(const char *c); extern void set_modflag(int mf, int mfc=-1); +extern const Fl_String &get_tmpdir(); + // ---- public callback functions extern void save_cb(Fl_Widget *, void *v); diff --git a/fluid/pixmaps/fd_project.png b/fluid/pixmaps/fd_project.png Binary files differnew file mode 100644 index 000000000..6288496c0 --- /dev/null +++ b/fluid/pixmaps/fd_project.png diff --git a/fluid/pixmaps/fd_user.png b/fluid/pixmaps/fd_user.png Binary files differnew file mode 100644 index 000000000..503cc54a2 --- /dev/null +++ b/fluid/pixmaps/fd_user.png diff --git a/fluid/shell_command.cxx b/fluid/shell_command.cxx index cd764ca24..c557c6e54 100644 --- a/fluid/shell_command.cxx +++ b/fluid/shell_command.cxx @@ -1,7 +1,7 @@ // // FLUID main entry for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2021 by Bill Spitzak and others. +// Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -14,125 +14,122 @@ // https://www.fltk.org/bugs.php // +// in progress: +// FLUID comes with example shell commands to build the current project file +// and run the project. This is accomplished by calling `fltk-config` on the +// files generated by FLUID, and by calling the executable directly. +// +// If the user wants more complex commands, he can add or modify them in the +// "Shell" settings panel. Modified shell commands are saved with the .fl +// file. + +// The Shell panel has a list of shell commands in the upper half. Under the +// list are buttons to add, duplicate, and delete shell commands. A popup +// menu offers import and export functionality and a list of sample scripts. +// We may want to add up and down buttons, so the user can change the +// order of commands. + +// Selecting any shell command in the list fills in and activates a list of +// options in the lower half of the panel. Those settings are: +// - Name: the name of the shell command in the list +// - Label: the label in the pulldown menu (could be the same as name?) +// - Shortcut: shortcut key to launch the command +// - Storage: where to store this shell command +// - Condition: pulldown menu to make the entry conditional for various +// target platforms, for example, a "Windows only" entry would only be added +// to the Shell menu on a Windows machine. Other options could be: +// - Linux only, macOS only, never (to make a list header!?), inactive? +// - Command: a multiline input for the actual shell command +// - Variables: a pulldown menu that insert variable names like $<sourcefile> +// - options to save project, code, and strings before running +// - test-run button + +// TODO: add @APPDIR@? +// TODO: get a macro to find `fltk-config` @FLTK_CONFIG@ +// TODO: add an input field so the user can insert their preferred file and path for fltk-config (user setting) +// `fltk-config` is actually tricky to find +// for live builds, we could check the program launch directory +// if we know where build/Xcode/bin/Debug/fluid is, we +// may or may not find ./build/Xcode/fltk-config +// on macOS with homebrew, we find /opt/homebrew/bin/fltk-config but the user +// can set their own install path. +// We can query the shell path, but that requires knowing the users shell (echo $SHELL). +// We can run the shell as a login shell with `-l`, so the user $PTH is set: /bin/bash -l -c 'fltk-config' +// The shell should output the path of the fltk-config that it found and why it is using that one. +// This can also output the fltk-config version. +// TODO: add a bunch of sensible sample shell commands +// TODO: when this new feature is used for the very first time, import two or three samples as initial user setting +// TODO: make the settings dialog resizable +// TODO: make g_shell_config static, not a pointer, but don't load anything in batch mode + +// FEATURE: Fd_Tool_Store icons are currently redundant with @file and @save and could be improved +// FEATURE: hostname, username, getenv support? +// FEATURE: ad the files ./fluid.prefs and ./fluid.user.prefs as tool locations + +/* + Some ideas: + + default shell is in $SHELL on linux and macOS + + On macOS, we can write Apple Scripts: + + #!/usr/bin/env osascript + say "@BASENAME@" + + osascript <<EOD + say "spark" + EOD + + osascript <<EOD + tell application "Xcode" + build workspace document 1 + end tell + EOD + */ + #include "shell_command.h" #include "fluid.h" +#include "file.h" #include "alignment_panel.h" #include <FL/Fl_Double_Window.H> +#include <FL/Fl_Menu_Bar.H> #include <FL/fl_message.H> #include <FL/fl_string_functions.h> #include <errno.h> +static Fl_String fltk_config_cmd; static Fl_Process s_proc; -/// Shell settings in the .fl file -Shell_Settings shell_settings_windows = { }; -Shell_Settings shell_settings_linux = { }; -Shell_Settings shell_settings_macos = { }; - -/// Current shell command, stored in .fl file for each platform, and in app prefs -Fl_String g_shell_command; - -/// Save .fl file before running, stored in .fl file for each platform, and in app prefs -int g_shell_save_fl = 1; - -/// Save code file before running, stored in .fl file for each platform, and in app prefs -int g_shell_save_code = 1; - -/// Save strings file before running, stored in .fl file for each platform, and in app prefs -int g_shell_save_strings = 0; - -/// Use these settings from .fl files, stored in app prefs -int g_shell_use_fl_settings = 1; -/** - Read the default shell settings from the app preferences. +/** \class Fl_Process + Launch an external shell command. */ -void shell_prefs_get() -{ - fluid_prefs.get("shell_command", g_shell_command, "echo \"Custom Shell Command\""); - fluid_prefs.get("shell_savefl", g_shell_save_fl, 1); - fluid_prefs.get("shell_writecode", g_shell_save_code, 1); - fluid_prefs.get("shell_writemsgs", g_shell_save_strings, 0); - fluid_prefs.get("shell_use_fl", g_shell_use_fl_settings, 1); -} /** - Write the current shell settings to the app preferences. + Create a process manager */ -void shell_prefs_set() -{ - fluid_prefs.set("shell_command", g_shell_command); - fluid_prefs.set("shell_savefl", g_shell_save_fl); - fluid_prefs.set("shell_writecode", g_shell_save_code); - fluid_prefs.set("shell_writemsgs", g_shell_save_strings); - fluid_prefs.set("shell_use_fl", g_shell_use_fl_settings); +Fl_Process::Fl_Process() { + _fpt= NULL; } /** - Copy shell settings from the .fl buffer if use_fl_settings is set. + Destroy the project manager. */ -void shell_settings_read() -{ - if (g_shell_use_fl_settings==0) - return; -#if defined(_WIN32) - Shell_Settings &shell_settings = shell_settings_windows; -#elif defined(__APPLE__) - Shell_Settings &shell_settings = shell_settings_macos; -#else - Shell_Settings &shell_settings = shell_settings_linux; -#endif - g_shell_command = shell_settings.command; - g_shell_save_fl = ((shell_settings.flags&1)==1); - g_shell_save_code = ((shell_settings.flags&2)==2); - g_shell_save_strings = ((shell_settings.flags&4)==4); +Fl_Process::~Fl_Process() { + // TODO: check what we need to do if a task is still running + if (_fpt) close(); } /** - Copy current shell settings to the .fl buffer if use_fl_settings is set. - */ -void shell_settings_write() -{ - if (g_shell_use_fl_settings==0) - return; -#if defined(_WIN32) - Shell_Settings &shell_settings = shell_settings_windows; -#elif defined(__APPLE__) - Shell_Settings &shell_settings = shell_settings_macos; -#else - Shell_Settings &shell_settings = shell_settings_linux; -#endif - if (shell_settings.command) - free((void*)shell_settings.command); - shell_settings.command = NULL; - if (!g_shell_command.empty()) - shell_settings.command = fl_strdup(g_shell_command.c_str()); - shell_settings.flags = 0; - if (g_shell_save_fl) - shell_settings.flags |= 1; - if (g_shell_save_code) - shell_settings.flags |= 2; - if (g_shell_save_strings) - shell_settings.flags |= 4; -} + Open a process. -/** \class Fl_Process - \todo Explain. + \param[in] cmd the shell command that we want to run + \param[in] mode "r" or "w" for creating a stream that can read or write + \return a stream that is redirected from the shell command stdout */ - -Fl_Process::Fl_Process() { - _fpt= NULL; -} - -Fl_Process::~Fl_Process() { - if (_fpt) close(); -} - -// FIXME: popen needs the UTF-8 equivalent fl_popen -// portable open process: FILE * Fl_Process::popen(const char *cmd, const char *mode) { #if defined(_WIN32) && !defined(__CYGWIN__) // PRECONDITIONS @@ -174,6 +171,9 @@ FILE * Fl_Process::popen(const char *cmd, const char *mode) { #endif } +/** + Close the current process. + */ int Fl_Process::close() { #if defined(_WIN32) && !defined(__CYGWIN__) if (_fpt) { @@ -192,11 +192,22 @@ int Fl_Process::close() { #endif } -// non-null if file is open +/** + non-null if file is open. + + \return the current file descriptor of the process' stdout + */ FILE *Fl_Process::desc() const { return _fpt; } +/** + Receive a single line from the current process. + + \param[out] line buffer to receive the line + \param[in] s size of the provided buffer + \return NULL if an error occurred, otherwise a pointer to the string + */ char *Fl_Process::get_line(char * line, size_t s) const { return _fpt ? fgets(line, (int)s, _fpt) : NULL; } @@ -237,31 +248,33 @@ void Fl_Process::clean_close(HANDLE& h) { #endif +/** + Prepare FLUID for running a shell command according to the command flags. -// Shell command support... - -static bool prepare_shell_command() { + \param[in] flags set various flags to save the project, code, and string before running the command + \return false if the previous command is still running + */ +static bool prepare_shell_command(int flags) { // settings_window->hide(); if (s_proc.desc()) { fl_alert("Previous shell command still running!"); return false; } - if (g_shell_command.empty()) { - fl_alert("No shell command entered!"); - return false; - } - if (g_shell_save_fl) { + if (flags & Fd_Shell_Command::SAVE_PROJECT) { save_cb(0, 0); } - if (g_shell_save_code) { + if (flags & Fd_Shell_Command::SAVE_SOURCECODE) { write_code_files(); } - if (g_shell_save_strings) { + if (flags & Fd_Shell_Command::SAVE_STRINGS) { write_strings_cb(0, 0); } return true; } +/** + Called by the file handler when the command is finished. + */ void shell_proc_done() { shell_run_terminal->append("... END SHELL COMMAND ...\n"); shell_run_button->activate(); @@ -293,8 +306,56 @@ void shell_pipe_cb(FL_SOCKET, void*) { } } -void do_shell_command(Fl_Return_Button*, void*) { - if (!prepare_shell_command()) return; +/** Find the script `fltk-config` that most closely relates to this version of FLUID. + This is not implemented yet. + */ +//static void find_fltk_config() { +// +//} + +static void expand_macro(Fl_String &cmd, const Fl_String ¯o, const Fl_String &content) { + for (int i=0;;) { + i = cmd.find(macro, i); + if (i==Fl_String::npos) break; + cmd.replace(i, macro.size(), content); + } +} + +static void expand_macros(Fl_String &cmd) { + expand_macro(cmd, "@BASENAME@", g_project.basename()); + expand_macro(cmd, "@PROJECTFILE_PATH@", g_project.projectfile_path()); + expand_macro(cmd, "@PROJECTFILE_NAME@", g_project.projectfile_name()); + expand_macro(cmd, "@CODEFILE_PATH@", g_project.codefile_path()); + expand_macro(cmd, "@CODEFILE_NAME@", g_project.codefile_name()); + expand_macro(cmd, "@HEADERFILE_PATH@", g_project.headerfile_path()); + expand_macro(cmd, "@HEADERFILE_NAME@", g_project.headerfile_name()); + expand_macro(cmd, "@TEXTFILE_PATH@", g_project.stringsfile_path()); + expand_macro(cmd, "@TEXTFILE_NAME@", g_project.stringsfile_name()); +// TODO: implement finding the script `fltk-config` for all platforms +// if (cmd.find("@FLTK_CONFIG@") != Fl_String::npos) { +// find_fltk_config(); +// expand_macro(cmd, "@FLTK_CONFIG@", fltk_config_cmd.c_str()); +// } + if (cmd.find("@TMPDIR@") != Fl_String::npos) + expand_macro(cmd, "@TMPDIR@", get_tmpdir()); +} + +/** + Prepare for and run a shell command. + + \param[in] cmd the command that is sent to `/bin/sh -c ...` or `cmd.exe` on Windows machines + \param[in] flags various flags in preparation of the command + */ +void run_shell_command(const Fl_String &cmd, int flags) { + if (cmd.empty()) { + fl_alert("No shell command entered!"); + return; + } + + if (!prepare_shell_command(flags)) return; + + Fl_String expanded_cmd = cmd; + expand_macros(expanded_cmd); if (!shell_run_window->visible()) { Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos"); @@ -310,10 +371,10 @@ void do_shell_command(Fl_Return_Button*, void*) { } // Show the output window and clear things... - shell_run_terminal->printf("\033[0;32m%s\033[0m\n", g_shell_command.c_str()); - shell_run_window->label(g_shell_command.c_str()); + shell_run_terminal->printf("\033[0;32m%s\033[0m\n", expanded_cmd.c_str()); + shell_run_window->label(expanded_cmd.c_str()); - if (s_proc.popen((char *)g_shell_command.c_str()) == NULL) { + if (s_proc.popen((char *)expanded_cmd.c_str()) == NULL) { shell_run_terminal->printf("\033[1;31mUnable to run shell command: %s\033[0m\n", strerror(errno)); shell_run_window->label("FLUID Shell"); @@ -329,28 +390,553 @@ void do_shell_command(Fl_Return_Button*, void*) { } /** - Show a dialog box to run an external shell command. + Create an empty shell command structure. + */ +Fd_Shell_Command::Fd_Shell_Command() +: shortcut(0), + storage(FD_STORE_USER), + condition(0), + flags(0), + shell_menu_item_(NULL) +{ +} + +/** + Copy the aspects of a shell command dataset into a new shell command. + + \param[in] rhs copy from this prototype + */ +Fd_Shell_Command::Fd_Shell_Command(const Fd_Shell_Command *rhs) +: name(rhs->name), + label(rhs->label), + shortcut(rhs->shortcut), + storage(rhs->storage), + condition(rhs->condition), + condition_data(rhs->condition_data), + command(rhs->command), + flags(rhs->flags), + shell_menu_item_(NULL) +{ +} + +/** + Create a default storage for a shell command and how it is accessible in FLUID. + + \param[in] name is used as a stand-in for the command name and label + */ +Fd_Shell_Command::Fd_Shell_Command(const Fl_String &in_name) +: name(in_name), + label(in_name), + shortcut(0), + storage(FD_STORE_USER), + condition(Fd_Shell_Command::ALWAYS), + command("echo \"Hello, FLUID!\""), + flags(Fd_Shell_Command::SAVE_PROJECT|Fd_Shell_Command::SAVE_SOURCECODE), + shell_menu_item_(NULL) +{ +} + +/** + Create a storage for a shell command and how it is accessible in FLUID. + + \param[in] in_name name of this command in the command list in the settings panel + \param[in] in_label label text in the main pulldown menu + \param[in] in_shortcut a keyboard shortcut that will also appear in the main menu + \param[in] in_storage storage location for this command + \param[in] in_condition commands can be hidden for certain platforms by setting a condition + \param[in] in_condition_data more details for future conditions, i.e. per user, per host, etc. + \param[in] in_command the shell command that we want to run + \param[in] in_flags some flags to tell FLUID to save the project, code, or strings before running the command + */ +Fd_Shell_Command::Fd_Shell_Command(const Fl_String &in_name, + const Fl_String &in_label, + Fl_Shortcut in_shortcut, + Fd_Tool_Store in_storage, + int in_condition, + const Fl_String &in_condition_data, + const Fl_String &in_command, + int in_flags) +: name(in_name), + label(in_label), + shortcut(in_shortcut), + storage(in_storage), + condition(in_condition), + condition_data(in_condition_data), + command(in_command), + flags(in_flags), + shell_menu_item_(NULL) +{ +} + +/** + Run this command now. + + Will open the Shell Panel and execute the command if no other command is + currently running. + */ +void Fd_Shell_Command::run() { + if (!command.empty()) + run_shell_command(command, flags); +} + +/** + Update the shell submenu in main menu with the shortcut and a copy of the label. + */ +void Fd_Shell_Command::update_shell_menu() { + if (shell_menu_item_) { + const char *old_label = shell_menu_item_->label(); // can be NULL + const char *new_label = label.c_str(); // never NULL + if (!old_label || (old_label && strcmp(old_label, new_label))) { + if (old_label) ::free((void*)old_label); + shell_menu_item_->label(fl_strdup(new_label)); + } + shell_menu_item_->shortcut(shortcut); + } +} + +/** + Check if the set condition is met. + + \return true if this command appears in the main menu + */ +bool Fd_Shell_Command::is_active() { + switch (condition) { + case ALWAYS: return true; + case NEVER: return false; +#ifdef _WIN32 + case MAC_ONLY: return false; + case UX_ONLY: return false; + case WIN_ONLY: return true; + case MAC_AND_UX_ONLY: return false; +#elif defined(__APPLE__) + case MAC_ONLY: return true; + case UX_ONLY: return false; + case WIN_ONLY: return false; + case MAC_AND_UX_ONLY: return true; +#else + case MAC_ONLY: return false; + case UX_ONLY: return true; + case WIN_ONLY: return false; + case MAC_AND_UX_ONLY: return true; +#endif + case USER_ONLY: return false; // TODO: get user name + case HOST_ONLY: return false; // TODO: get host name + case ENV_ONLY: { + const char *value = fl_getenv(condition_data.c_str()); + if (value && *value) return true; + return false; + } + } + return false; +} + +void Fd_Shell_Command::read(Fl_Preferences &prefs) { + int tmp; + prefs.get("name", name, "<unnamed>"); + prefs.get("label", label, "<no label>"); + prefs.get("shortcut", tmp, 0); + shortcut = (Fl_Shortcut)tmp; + prefs.get("storage", tmp, -1); + if (tmp != -1) storage = (Fd_Tool_Store)tmp; + prefs.get("condition", condition, ALWAYS); + prefs.get("condition_data", condition_data, ""); + prefs.get("command", command, ""); + prefs.get("flags", flags, 0); +} + +void Fd_Shell_Command::write(Fl_Preferences &prefs, bool save_location) { + prefs.set("name", name); + prefs.set("label", label); + if (shortcut != 0) prefs.set("shortcut", (int)shortcut); + if (save_location) prefs.set("storage", (int)storage); + if (condition != ALWAYS) prefs.set("condition", condition); + if (!condition_data.empty()) prefs.set("condition_data", condition_data); + if (!command.empty()) prefs.set("command", command); + if (flags != 0) prefs.set("flags", flags); +} + +void Fd_Shell_Command::read(class Fd_Project_Reader *in) { + const char *c = in->read_word(1); + if (strcmp(c, "{")!=0) return; // expecting start of group + storage = FD_STORE_PROJECT; + for (;;) { + c = in->read_word(1); + if (strcmp(c, "}")==0) break; // end of command list + else if (strcmp(c, "name")==0) + name = in->read_word(); + else if (strcmp(c, "label")==0) + label = in->read_word(); + else if (strcmp(c, "shortcut")==0) + shortcut = in->read_int(); + else if (strcmp(c, "condition")==0) + condition = in->read_int(); + else if (strcmp(c, "condition_data")==0) + condition_data = in->read_word(); + else if (strcmp(c, "command")==0) + command = in->read_word(); + else if (strcmp(c, "flags")==0) + flags = in->read_int(); + else + in->read_word(); // skip an unknown word + } +} + +void Fd_Shell_Command::write(class Fd_Project_Writer *out) { + out->write_string("\n command {"); + out->write_string("\n name "); out->write_word(name.c_str()); + out->write_string("\n label "); out->write_word(label.c_str()); + if (shortcut) out->write_string("\n shortcut %d", shortcut); + if (condition) out->write_string("\n condition %d", condition); + if (!condition_data.empty()) { + out->write_string("\n condition_data "); out->write_word(condition_data.c_str()); + } + if (!command.empty()) { + out->write_string("\n command "); out->write_word(command.c_str()); + } + if (flags) out->write_string("\n flags %d", flags); + out->write_string("\n }"); +} + + +/** + Manage a list of shell commands and their parameters. + */ +Fd_Shell_Command_List::Fd_Shell_Command_List() +: list(NULL), + list_size(0), + list_capacity(0), + shell_menu_(NULL) +{ +} + +/** + Release all shell commands and destroy this class. + */ +Fd_Shell_Command_List::~Fd_Shell_Command_List() { + clear(); +} + +/** + Return the shell command at the given index. + + \param[in] index must be between 0 and list_size-1 + \return a pointer to the shell command data + */ +Fd_Shell_Command *Fd_Shell_Command_List::at(int index) const { + return list[index]; +} + +/** + Clear all shell commands. + */ +void Fd_Shell_Command_List::clear() { + if (list) { + for (int i=0; i<list_size; i++) { + delete list[i]; + } + ::free(list); + list_size = 0; + list_capacity = 0; + list = 0; + } +} + +/** + remove all shell commands of the given storage location from the list. + */ +void Fd_Shell_Command_List::clear(Fd_Tool_Store storage) { + for (int i=list_size-1; i>=0; i--) { + if (list[i]->storage == storage) { + remove(i); + } + } +} - Copies the current settings into the dialog box. +/** + Read shell configuration from a preferences group. + */ +void Fd_Shell_Command_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { + // import the old shell commands from previous user settings + if (&fluid_prefs == &prefs) { + int version; + prefs.get("shell_commands_version", version, 0); + if (version == 0) { + int save_fl, save_code, save_strings; + Fd_Shell_Command *cmd = new Fd_Shell_Command(); + cmd->storage = FD_STORE_USER; + cmd->name = "Sample Shell Command"; + cmd->label = "Sample Shell Command"; + cmd->shortcut = FL_ALT+'g'; + fluid_prefs.get("shell_command", cmd->command, "echo \"Sample Shell Command\""); + fluid_prefs.get("shell_savefl", save_fl, 1); + fluid_prefs.get("shell_writecode", save_code, 1); + fluid_prefs.get("shell_writemsgs", save_strings, 0); + if (save_fl) cmd->flags |= Fd_Shell_Command::SAVE_PROJECT; + if (save_code) cmd->flags |= Fd_Shell_Command::SAVE_SOURCECODE; + if (save_strings) cmd->flags |= Fd_Shell_Command::SAVE_STRINGS; + add(cmd); + } + version = 1; + prefs.set("shell_commands_version", version); + } + Fl_Preferences shell_commands(prefs, "shell_commands"); + int n = shell_commands.groups(); + for (int i=0; i<n; i++) { + Fl_Preferences cmd_prefs(shell_commands, Fl_Preferences::Name(i)); + Fd_Shell_Command *cmd = new Fd_Shell_Command(); + cmd->storage = FD_STORE_USER; + cmd->read(cmd_prefs); + add(cmd); + } +} - This dialog box offers a field for a command line and three check buttons - to generate and save various files before the command is run. +/** + Write shell configuration to a preferences group. + */ +void Fd_Shell_Command_List::write(Fl_Preferences &prefs, Fd_Tool_Store storage) { + Fl_Preferences shell_commands(prefs, "shell_commands"); + shell_commands.delete_all_groups(); + int index = 0; + for (int i=0; i<list_size; i++) { + if (list[i]->storage == FD_STORE_USER) { + Fl_Preferences cmd(shell_commands, Fl_Preferences::Name(index++)); + list[i]->write(cmd); + } + } +} - If the fourth checkbox, "use settings in .fl design files" is checked, - all shell settings will be store in the current .fl file, and they will - be read and restored when the .fl is loaded again. +/** + Read shell configuration from a project file. + */ +void Fd_Shell_Command_List::read(Fd_Project_Reader *in) { + const char *c = in->read_word(1); + if (strcmp(c, "{")!=0) return; // expecting start of group + clear(FD_STORE_PROJECT); + for (;;) { + c = in->read_word(1); + if (strcmp(c, "}")==0) break; // end of command list + else if (strcmp(c, "command")==0) { + Fd_Shell_Command *cmd = new Fd_Shell_Command(); + add(cmd); + cmd->read(in); + } else { + in->read_word(); // skip an unknown group + } + } +} - Fluid will save different shell settings for different operating system as - it is common that a different OS requires a different shell command. +/** + Write shell configuration to a project file. + */ +void Fd_Shell_Command_List::write(Fd_Project_Writer *out) { + int n_in_project_file = 0; + for (int i=0; i<list_size; i++) { + if (list[i]->storage == FD_STORE_PROJECT) + n_in_project_file++; + } + if (n_in_project_file > 0) { + out->write_string("\nshell_commands {"); + for (int i=0; i<list_size; i++) { + if (list[i]->storage == FD_STORE_PROJECT) + list[i]->write(out); + } + out->write_string("\n}"); + } +} - Fluid comes with default shell settings. Pressing the "save as default" button - will store the current setting in the Fluid app settings and are used for new - designs, or if the "use settings..." box is not checked. +/** + Add a previously created shell command to the end of the list. - Fluid app settings are saved per user and per machine. + \param[in] cmd a pointer to the command that we want to add */ -void show_shell_window() { +void Fd_Shell_Command_List::add(Fd_Shell_Command *cmd) { + if (list_size == list_capacity) { + list_capacity += 16; + list = (Fd_Shell_Command**)::realloc(list, list_capacity * sizeof(Fd_Shell_Command**)); + } + list[list_size++] = cmd; +} + +/** + Insert a newly created shell command at the given position in the list. + + \param[in] index must be between 0 and list_size-1 + \param[in] cmd a pointer to the command that we want to add + */ +void Fd_Shell_Command_List::insert(int index, Fd_Shell_Command *cmd) { + if (list_size == list_capacity) { + list_capacity += 16; + list = (Fd_Shell_Command**)::realloc(list, list_capacity * sizeof(Fd_Shell_Command**)); + } + ::memmove(list+index+1, list+index, (list_size-index)*sizeof(Fd_Shell_Command**)); + list_size++; + list[index] = cmd; +} + +/** + Remove and delete the command at the given index. + + \param[in] index must be between 0 and list_size-1 + */ +void Fd_Shell_Command_List::remove(int index) { + delete list[index]; + list_size--; + ::memmove(list+index, list+index+1, (list_size-index)*sizeof(Fd_Shell_Command**)); +} + +/** + This is called whenever the user clicks a shell command menu in the main menu. + + \param[in] u cast tp long to get the index of the shell command + */ +void menu_shell_cmd_cb(Fl_Widget*, void *u) { + long index = (long)(fl_intptr_t)u; + g_shell_config->list[index]->run(); +} + +/** + This is called when the user selects the menu to edit the shell commands. + It pops up the setting panel at the shell settings tab. + */ +void menu_shell_customize_cb(Fl_Widget*, void*) { settings_window->show(); w_settings_tabs->value(w_settings_shell_tab); } +/** + Rebuild the entire shell submenu from scratch and replace the old menu. + */ +void Fd_Shell_Command_List::rebuild_shell_menu() { + static Fl_Menu_Item *shell_submenu = NULL; + if (!shell_submenu) + shell_submenu = (Fl_Menu_Item*)main_menubar->find_item(menu_marker); + + int i, j, num_active_items = 0; + // count the active commands + for (i=0; i<list_size; i++) { + if (list[i]->is_active()) num_active_items++; + } + // allocate a menu item array + Fl_Menu_Item *mi = (Fl_Menu_Item*)::calloc(num_active_items+2, sizeof(Fl_Menu_Item)); + // set the menu item pointer for all active commands + for (i=j=0; i<list_size; i++) { + Fd_Shell_Command *cmd = list[i]; + if (cmd->is_active()) { + cmd->shell_menu_item_ = mi + j; + mi[j].callback(menu_shell_cmd_cb); + mi[j].argument(i); + cmd->update_shell_menu(); + j++; + } + } + if (j>0) mi[j-1].flags |= FL_MENU_DIVIDER; + mi[j].label(fl_strdup("Customize...")); + mi[j].shortcut(FL_ALT+'x'); + mi[j].callback(menu_shell_customize_cb); + // replace the old menu array with the new one + Fl_Menu_Item *mi_old = shell_menu_; + shell_menu_ = mi; + shell_submenu->user_data(shell_menu_); + // free all resources from the old menu + if (mi_old && (mi_old != default_menu)) { + for (i=0; ; i++) { + const char *label = mi_old[i].label(); + if (!label) break; + ::free((void*)label); + } + ::free(mi_old); + } +} + +/** + Tell the settings dialog to query this list and update its GUI elements. + */ +void Fd_Shell_Command_List::update_settings_dialog() { + if (w_settings_shell_tab) + w_settings_shell_tab->do_callback(w_settings_shell_tab, LOAD); +} + +/** + The default shell submenu in batch mode. + */ +Fl_Menu_Item Fd_Shell_Command_List::default_menu[] = { + { "Customize...", FL_ALT+'x', menu_shell_customize_cb }, + { NULL } +}; + +/** + Used to find the shell submenu within the main menu tree. + */ +void Fd_Shell_Command_List::menu_marker(Fl_Widget*, void*) { + // intentionally left empty +} + +/** + Export all selected shell commands to an external file. + + Verify that g_shell_config and w_settings_shell_list are not NULL. Open a + file chooser and export all items that are selected in w_settings_shell_list + into an external file. + */ +void Fd_Shell_Command_List::export_selected() { + if (!g_shell_config || (g_shell_config->list_size == 0)) return; + if (!w_settings_shell_list) return; + + Fl_Native_File_Chooser dialog; + dialog.title("Export selected shell commands:"); + dialog.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + dialog.filter("FLUID Files\t*.flcmd\n"); + dialog.directory(g_project.projectfile_path().c_str()); + dialog.preset_file((g_project.basename() + ".flcmd").c_str()); + if (dialog.show() != 0) return; + + Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", NULL, (Fl_Preferences::Root)(Fl_Preferences::C_LOCALE|Fl_Preferences::CLEAR)); + Fl_Preferences shell_commands(file, "shell_commands"); + int i, index = 0, n = w_settings_shell_list->size(); + for (i = 0; i < n; i++) { + if (w_settings_shell_list->selected(i+1)) { + Fl_Preferences cmd(shell_commands, Fl_Preferences::Name(index++)); + g_shell_config->list[i]->write(cmd, true); + } + } +} + +/** + Import shell commands from an external file and add them to the list. + + Verify that g_shell_config and w_settings_shell_list are not NULL. Open a + file chooser and import all items. + */ +void Fd_Shell_Command_List::import_from_file() { + if (!g_shell_config || (g_shell_config->list_size == 0)) return; + if (!w_settings_shell_list) return; + + Fl_Native_File_Chooser dialog; + dialog.title("Import shell commands:"); + dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); + dialog.filter("FLUID Files\t*.flcmd\n"); + dialog.directory(g_project.projectfile_path().c_str()); + dialog.preset_file((g_project.basename() + ".flcmd").c_str()); + if (dialog.show() != 0) return; + + Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", NULL, Fl_Preferences::C_LOCALE); + Fl_Preferences shell_commands(file, "shell_commands"); + int i, n = shell_commands.groups(); + for (i = 0; i < n; i++) { + Fl_Preferences cmd_prefs(shell_commands, Fl_Preferences::Name(i)); + Fd_Shell_Command *cmd = new Fd_Shell_Command(); + cmd->storage = FD_STORE_USER; + cmd->read(cmd_prefs); + g_shell_config->add(cmd); + } + w_settings_shell_list->do_callback(w_settings_shell_list, LOAD); + w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); + w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); + g_shell_config->rebuild_shell_menu(); +} + +/** + A pointer to the list of shell commands if we are not in batch mode. + */ +Fd_Shell_Command_List *g_shell_config = NULL; + diff --git a/fluid/shell_command.h b/fluid/shell_command.h index cfd7b6579..ea39375f2 100644 --- a/fluid/shell_command.h +++ b/fluid/shell_command.h @@ -1,7 +1,7 @@ // // FLUID main entry for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2021 by Bill Spitzak and others. +// Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -17,11 +17,13 @@ #ifndef _FLUID_SHELL_COMMAND_H #define _FLUID_SHELL_COMMAND_H -#include <stdio.h> -#include <stdlib.h> +#include "fluid.h" #include <FL/Fl_String.H> +#include <FL/Enumerations.H> +#include <stdio.h> +#include <stdlib.h> #if defined(_WIN32) && !defined(__CYGWIN__) # include <direct.h> # include <windows.h> @@ -33,29 +35,10 @@ # include <unistd.h> #endif -void show_shell_window(); -void do_shell_command(class Fl_Return_Button*, void*); - -typedef struct { - char *command; - int flags; -} Shell_Settings; - -extern Shell_Settings shell_settings_windows; -extern Shell_Settings shell_settings_linux; -extern Shell_Settings shell_settings_macos; - -extern Fl_String g_shell_command; -extern int g_shell_save_fl; -extern int g_shell_save_code; -extern int g_shell_save_strings; -extern int g_shell_use_fl_settings; - -void shell_prefs_get(); -void shell_prefs_set(); -void shell_settings_read(); -void shell_settings_write(); +struct Fl_Menu_Item; +class Fl_Widget; +void run_shell_command(const Fl_String &cmd, int flags); class Fl_Process { public: @@ -88,4 +71,71 @@ protected: FILE * _fpt; }; +class Fd_Shell_Command { +public: + enum { ALWAYS, NEVER, MAC_ONLY, UX_ONLY, WIN_ONLY, MAC_AND_UX_ONLY, USER_ONLY, HOST_ONLY, ENV_ONLY }; // conditions + enum { SAVE_PROJECT = 1, SAVE_SOURCECODE = 2, SAVE_STRINGS = 4, SAVE_ALL = 7 }; // flags + Fd_Shell_Command(); + Fd_Shell_Command(const Fd_Shell_Command *rhs); + Fd_Shell_Command(const Fl_String &in_name); + Fd_Shell_Command(const Fl_String &in_name, + const Fl_String &in_label, + Fl_Shortcut in_shortcut, + Fd_Tool_Store in_storage, + int in_condition, + const Fl_String &in_condition_data, + const Fl_String &in_command, + int in_flags); + Fl_String name; + Fl_String label; + Fl_Shortcut shortcut; + Fd_Tool_Store storage; + int condition; // always, hide, windows only, linux only, mac only, user, machine + Fl_String condition_data; // user name, machine name + Fl_String command; + int flags; // save_project, save_code, save_string, ... + Fl_Menu_Item *shell_menu_item_; + void run(); + void read(Fl_Preferences &prefs); + void write(Fl_Preferences &prefs, bool save_location = false); + void read(class Fd_Project_Reader*); + void write(class Fd_Project_Writer*); + void update_shell_menu(); + bool is_active(); +}; + +class Fd_Shell_Command_List { +public: + Fd_Shell_Command **list; + int list_size; + int list_capacity; + Fl_Menu_Item *shell_menu_; +public: + Fd_Shell_Command_List(); + ~Fd_Shell_Command_List(); + Fd_Shell_Command *at(int index) const; + void add(Fd_Shell_Command *cmd); + void insert(int index, Fd_Shell_Command *cmd); + void remove(int index); + void clear(); + void clear(Fd_Tool_Store store); +// void move_up(); +// void move_down(); +// int load(const Fl_String &filename); +// int save(const Fl_String &filename); + void read(Fl_Preferences &prefs, Fd_Tool_Store storage); + void write(Fl_Preferences &prefs, Fd_Tool_Store storage); + void read(class Fd_Project_Reader*); + void write(class Fd_Project_Writer*); + void rebuild_shell_menu(); + void update_settings_dialog(); + + static Fl_Menu_Item default_menu[]; + static void menu_marker(Fl_Widget*, void*); + static void export_selected(); + static void import_from_file(); +}; + +extern Fd_Shell_Command_List *g_shell_config; + #endif // _FLUID_SHELL_COMMAND_H diff --git a/fluid/sourceview_panel.cxx b/fluid/sourceview_panel.cxx index 2cd008f85..64d7c6b0d 100644 --- a/fluid/sourceview_panel.cxx +++ b/fluid/sourceview_panel.cxx @@ -87,17 +87,17 @@ void update_sourceview_cb(class Fl_Button*, void*) { if (!sv_source_filename) { sv_source_filename = (char*)malloc(FL_PATH_MAX); - fluid_prefs.getUserdataPath(sv_source_filename, FL_PATH_MAX); + fl_strlcpy(sv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(sv_source_filename, "source_view_tmp.cxx", FL_PATH_MAX); } if (!sv_header_filename) { sv_header_filename = (char*)malloc(FL_PATH_MAX); - fluid_prefs.getUserdataPath(sv_header_filename, FL_PATH_MAX); + fl_strlcpy(sv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX); } if (!sv_design_filename) { sv_design_filename = (char*)malloc(FL_PATH_MAX); - fluid_prefs.getUserdataPath(sv_design_filename, FL_PATH_MAX); + fl_strlcpy(sv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(sv_design_filename, "source_view_tmp.fl", FL_PATH_MAX); } @@ -108,8 +108,9 @@ void update_sourceview_cb(class Fl_Button*, void*) { sv_project->scroll(top, 0); } else if (sv_strings->visible_r()) { static const char *exts[] = { ".txt", ".po", ".msg" }; - char fn[FL_PATH_MAX]; - fluid_prefs.getUserdataPath(fn, FL_PATH_MAX); + char fn[FL_PATH_MAX+1]; + fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcat(fn, "strings", FL_PATH_MAX); fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]); write_strings(fn); int top = sv_strings->top_line(); diff --git a/fluid/sourceview_panel.fl b/fluid/sourceview_panel.fl index e78224677..61f6242a9 100644 --- a/fluid/sourceview_panel.fl +++ b/fluid/sourceview_panel.fl @@ -102,17 +102,17 @@ and load those into the Code Viewer widgets.} open return_type void if (!sv_source_filename) { sv_source_filename = (char*)malloc(FL_PATH_MAX); - fluid_prefs.getUserdataPath(sv_source_filename, FL_PATH_MAX); + fl_strlcpy(sv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(sv_source_filename, "source_view_tmp.cxx", FL_PATH_MAX); } if (!sv_header_filename) { sv_header_filename = (char*)malloc(FL_PATH_MAX); - fluid_prefs.getUserdataPath(sv_header_filename, FL_PATH_MAX); + fl_strlcpy(sv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX); } if (!sv_design_filename) { sv_design_filename = (char*)malloc(FL_PATH_MAX); - fluid_prefs.getUserdataPath(sv_design_filename, FL_PATH_MAX); + fl_strlcpy(sv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(sv_design_filename, "source_view_tmp.fl", FL_PATH_MAX); } @@ -123,8 +123,9 @@ and load those into the Code Viewer widgets.} open return_type void sv_project->scroll(top, 0); } else if (sv_strings->visible_r()) { static const char *exts[] = { ".txt", ".po", ".msg" }; - char fn[FL_PATH_MAX]; - fluid_prefs.getUserdataPath(fn, FL_PATH_MAX); + char fn[FL_PATH_MAX+1]; + fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcat(fn, "strings", FL_PATH_MAX); fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]); write_strings(fn); int top = sv_strings->top_line(); diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx index 93b29db45..c7a47881f 100644 --- a/src/Fl_Preferences.cxx +++ b/src/Fl_Preferences.cxx @@ -233,7 +233,9 @@ Fl_Preferences::Root Fl_Preferences::filename( char *buffer, size_t buffer_size, <tt>\<null\>/Library/Preferences/\$(vendor)/\$(application).prefs</tt>, which would silently fail to create a preference file. - \param[in] root can be \c USER_L or \c SYSTEM_L for user specific or system wide preferences + \param[in] root can be \c USER_L or \c SYSTEM_L for user specific or system + wide preferences, add the CLEAR flag to start with a clean set of + preferences instead of reading them from the database \param[in] vendor unique text describing the company or author of this file, must be a valid filepath segment \param[in] application unique text describing the application, must be a valid filepath segment @@ -246,19 +248,41 @@ Fl_Preferences::Fl_Preferences( Root root, const char *vendor, const char *appli } /** - \brief Use this constructor to create or read a preference file at an - arbitrary position in the file system. + \brief Deprecated: Use this constructor to create or read a preference file at an + arbitrary position in the file system. + + This constructor should no longer be used because the generated database uses + the current locale, making it impossible to exchange floating point settings + between machines with different language settings. - The file name is generated in the form <tt>\$(path)/\$(application).prefs</tt>. - If \p application is \c NULL, \p path is taken literally as the file path and name. + Use `Fl_Preferences(path, vendor, application, C_LOCALE)` in new projects and + `Fl_Preferences(path, vendor, application, 0)` if you must keep backward + compatibility. - \param[in] path path to the directory that contains the preference file - \param[in] vendor unique text describing the company or author of this file, must be a valid filepath segment - \param[in] application unique text describing the application, must be a valid filepath segment + \see Fl_Preferences( const char *path, const char *vendor, const char *application, Root flags ) */ Fl_Preferences::Fl_Preferences( const char *path, const char *vendor, const char *application ) { node = new Node( "." ); - rootNode = new RootNode( this, path, vendor, application ); + rootNode = new RootNode( this, path, vendor, application, (Root)0 ); + node->setRoot(rootNode); +} + +/** + \brief Use this constructor to create or read a preference file at an + arbitrary position in the file system. + + The file name is generated in the form <tt>\$(path)/\$(application).prefs</tt>. + If \p application is \c NULL, \p path is taken literally as the file path and name. + + \param[in] path path to the directory that contains the preference file + \param[in] vendor unique text describing the company or author of this file, must be a valid filepath segment + \param[in] application unique text describing the application, must be a valid filename or NULL + \param[in] set C_LOCALE to make the preferences file independent of the current locale, + add the CLEAR flag to start with a clean set of preferences instead of reading from the database + */ +Fl_Preferences::Fl_Preferences( const char *path, const char *vendor, const char *application, Root flags ) { + node = new Node( "." ); + rootNode = new RootNode( this, path, vendor, application, flags ); node->setRoot(rootNode); } @@ -1168,23 +1192,24 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, Root root, const char filename_(0L), vendor_(0L), application_(0L), - root_type_(root) + root_type_((Root)(root & ~CLEAR)) { char *filename = Fl::system_driver()->preference_rootnode(prefs, root, vendor, application); filename_ = filename ? fl_strdup(filename) : 0L; vendor_ = fl_strdup(vendor); application_ = fl_strdup(application); - read(); + if ( (root & CLEAR) == 0 ) + read(); } // create the root node // - construct the name of the file that will hold our preferences -Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, const char *vendor, const char *application ) +Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, const char *vendor, const char *application, Root flags ) : prefs_(prefs), filename_(0L), vendor_(0L), application_(0L), - root_type_(Fl_Preferences::USER) + root_type_( (Root)(USER | (flags & C_LOCALE) )) { if (!vendor) @@ -1199,7 +1224,8 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, con } vendor_ = fl_strdup(vendor); application_ = fl_strdup(application); - read(); + if ( (flags & CLEAR) == 0 ) + read(); } // create a root node that exists only on RAM and can not be read or written to diff --git a/src/filename_absolute.cxx b/src/filename_absolute.cxx index 70b86fcf7..0d0155df1 100644 --- a/src/filename_absolute.cxx +++ b/src/filename_absolute.cxx @@ -367,3 +367,4 @@ Fl_String fl_getcwd() { fl_getcwd(buffer, FL_PATH_MAX); return Fl_String(buffer); } + diff --git a/test/tree.fl b/test/tree.fl index a48be0284..cb2c8803e 100644 --- a/test/tree.fl +++ b/test/tree.fl @@ -392,7 +392,7 @@ tree->clear_changed();} open tooltip {Test tree} xywh {15 22 320 539} box DOWN_BOX color 55 selection_color 15 class Fl_Tree } {} - Fl_Group {} {open selected + Fl_Group {} {open xywh {350 5 681 556} code0 {o->resizable(0);} } { @@ -780,7 +780,7 @@ Fl::visible_focus(onoff);} } } Fl_Group {} { - label {Test Operations} + label {Test Operations} open selected tooltip {These controls only affect the defaults for new items that are created. These test the Fl_Tree_Prefs methods.} xywh {350 435 330 125} box GTK_DOWN_BOX color 47 labelsize 12 } { Fl_Group showitem_box { @@ -847,7 +847,7 @@ tree->redraw();} callback {const char *filename = fl_file_chooser("Select a Preferences style Database", "Preferences(*.prefs)", 0L); if (filename) { tree->clear(); - Fl_Preferences prefs(filename, 0L, 0L); + Fl_Preferences prefs(filename, 0L, 0L, Fl_Preferences::C_LOCALE); tree->load(prefs); tree->redraw(); }} diff --git a/test/unittest_core.cxx b/test/unittest_core.cxx index 6091dd7b4..ad60d172c 100644 --- a/test/unittest_core.cxx +++ b/test/unittest_core.cxx @@ -278,7 +278,7 @@ TEST(fl_filename, relative) { r = fl_filename_relative("../foo.txt", base); EXPECT_STREQ(r.c_str(), "../foo.txt"); return true; - } +} TEST(fl_filename, absolute) { Fl_String base = "/var/tmp/somedir"; @@ -293,6 +293,7 @@ TEST(fl_filename, absolute) { return true; } + bool cb1a_ok = false, cb1b_ok = false, cb1c_ok = false; int cb1_alloc = 0; class MyString : public Fl_String { |
