From 15ad447e2a0301b2aa4ea350615ae71f0e5e5ef5 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Sat, 8 Mar 2025 00:14:09 +0100 Subject: Fluid: last incremental chage, restructuring --- fluid/CMakeLists.txt | 16 +- fluid/app/Fd_Snap_Action.cxx | 15 +- fluid/app/Fd_Snap_Action.h | 12 +- fluid/app/Fluid_Image.cxx | 23 +- fluid/app/Fluid_Image.h | 18 +- fluid/app/fluid.cxx | 251 +--- fluid/app/fluid.h | 85 +- fluid/app/mergeback.cxx | 16 +- fluid/app/project.cxx | 2302 +----------------------------- fluid/app/project.h | 116 +- fluid/app/shell_command.cxx | 12 +- fluid/app/shell_command.h | 17 +- fluid/app/undo.cxx | 14 +- fluid/io/Code_Writer.cxx | 79 +- fluid/io/Code_Writer.h | 18 +- fluid/io/Project_Reader.cxx | 266 +--- fluid/io/Project_Reader.h | 45 +- fluid/io/Project_Writer.cxx | 771 +--------- fluid/io/Project_Writer.h | 61 +- fluid/nodes/Fl_Button_Type.cxx | 7 +- fluid/nodes/Fl_Button_Type.h | 4 +- fluid/nodes/Fl_Function_Type.cxx | 67 +- fluid/nodes/Fl_Function_Type.h | 66 +- fluid/nodes/Fl_Grid_Type.cxx | 17 +- fluid/nodes/Fl_Grid_Type.h | 12 +- fluid/nodes/Fl_Group_Type.cxx | 15 +- fluid/nodes/Fl_Group_Type.h | 10 +- fluid/nodes/Fl_Menu_Type.cxx | 28 +- fluid/nodes/Fl_Menu_Type.h | 18 +- fluid/nodes/Fl_Type.cxx | 38 +- fluid/nodes/Fl_Type.h | 42 +- fluid/nodes/Fl_Widget_Type.cxx | 28 +- fluid/nodes/Fl_Widget_Type.h | 18 +- fluid/nodes/Fl_Window_Type.cxx | 24 +- fluid/nodes/Fl_Window_Type.h | 16 +- fluid/panels/codeview_panel.cxx | 8 +- fluid/panels/codeview_panel.fl | 12 +- fluid/panels/settings_panel.cxx | 1 + fluid/panels/settings_panel.fl | 5 +- fluid/panels/settings_panel.h | 2 +- fluid/panels/template_panel.cxx | 2 +- fluid/panels/template_panel.fl | 2 +- fluid/tools/ExternalCodeEditor_UNIX.cxx | 1 + fluid/tools/ExternalCodeEditor_WIN32.cxx | 1 + fluid/tools/autodoc.cxx | 1 + fluid/tools/filename.cxx | 4 +- fluid/tools/filename.h | 8 +- 47 files changed, 573 insertions(+), 4021 deletions(-) (limited to 'fluid') diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt index e4977a8ce..40f6e3589 100644 --- a/fluid/CMakeLists.txt +++ b/fluid/CMakeLists.txt @@ -28,10 +28,12 @@ set(CPPFILES app/fluid.cxx app/Fluid_Image.cxx app/mergeback.cxx + app/project.cxx app/shell_command.cxx app/undo.cxx - io/code.cxx - io/file.cxx + io/Code_Writer.cxx + io/Project_Writer.cxx + io/Project_Reader.cxx nodes/factory.cxx nodes/Fl_Button_Type.cxx nodes/Fl_Function_Type.cxx @@ -49,7 +51,7 @@ set(CPPFILES panels/widget_panel.cxx rsrcs/pixmaps.cxx tools/autodoc.cxx - tools/fluid_filename.cxx + tools/filename.cxx widgets/Code_Editor.cxx widgets/Code_Viewer.cxx widgets/Text_Viewer.cxx @@ -66,11 +68,13 @@ set(HEADERFILES app/Fd_Snap_Action.h app/fluid.h app/Fluid_Image.h + app/project.h app/mergeback.h app/shell_command.h app/undo.h - io/code.h - io/file.h + io/Code_Writer.h + io/Project_Writer.h + io/Project_Reader.h nodes/factory.h nodes/Fl_Button_Type.h nodes/Fl_Function_Type.h @@ -89,7 +93,7 @@ set(HEADERFILES rsrcs/comments.h rsrcs/pixmaps.h tools/autodoc.h - tools/fluid_filename.h + tools/filename.h widgets/Code_Editor.h widgets/Code_Viewer.h widgets/Text_Viewer.h diff --git a/fluid/app/Fd_Snap_Action.cxx b/fluid/app/Fd_Snap_Action.cxx index c093af1ff..0a407ac8d 100644 --- a/fluid/app/Fd_Snap_Action.cxx +++ b/fluid/app/Fd_Snap_Action.cxx @@ -16,7 +16,8 @@ #include "app/Fd_Snap_Action.h" -#include "io/file.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" #include "nodes/Fl_Group_Type.h" #include "panels/settings_panel.h" @@ -227,7 +228,7 @@ void Fd_Layout_Preset::read(Fl_Preferences &prefs) { /** Write presets to an .fl project file. */ -void Fd_Layout_Preset::write(Fd_Project_Writer *out) { +void Fd_Layout_Preset::write(fld::io::Project_Writer *out) { out->write_string(" preset { 1\n"); // preset format version out->write_string(" %d %d %d %d %d %d\n", left_window_margin, right_window_margin, @@ -249,7 +250,7 @@ void Fd_Layout_Preset::write(Fd_Project_Writer *out) { /** Read presets from an .fl project file. */ -void Fd_Layout_Preset::read(Fd_Project_Reader *in) { +void Fd_Layout_Preset::read(fld::io::Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { @@ -346,7 +347,7 @@ void Fd_Layout_Suite::read(Fl_Preferences &prefs) { /** Write a presets suite to an .fl project file. */ -void Fd_Layout_Suite::write(Fd_Project_Writer *out) { +void Fd_Layout_Suite::write(fld::io::Project_Writer *out) { out->write_string(" suite {\n"); out->write_string(" name "); out->write_word(name_); out->write_string("\n"); for (int i = 0; i < 3; ++i) { @@ -358,7 +359,7 @@ void Fd_Layout_Suite::write(Fd_Project_Writer *out) { /** Read a presets suite from an .fl project file. */ -void Fd_Layout_Suite::read(Fd_Project_Reader *in) { +void Fd_Layout_Suite::read(fld::io::Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { @@ -713,7 +714,7 @@ void Fd_Layout_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { /** Write Suite and Layout selection and project layout data to an .fl project file. */ -void Fd_Layout_List::write(Fd_Project_Writer *out) { +void Fd_Layout_List::write(fld::io::Project_Writer *out) { // Don't write the Snap field if no custom layout was used if ((current_suite()==0) && (current_preset()==0)) { int nSuite = 0; @@ -736,7 +737,7 @@ void Fd_Layout_List::write(Fd_Project_Writer *out) { /** Read Suite and Layout selection and project layout data from an .fl project file. */ -void Fd_Layout_List::read(Fd_Project_Reader *in) { +void Fd_Layout_List::read(fld::io::Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { diff --git a/fluid/app/Fd_Snap_Action.h b/fluid/app/Fd_Snap_Action.h index 50b520319..0c98b56b8 100644 --- a/fluid/app/Fd_Snap_Action.h +++ b/fluid/app/Fd_Snap_Action.h @@ -67,8 +67,8 @@ public: void write(Fl_Preferences &prefs); void read(Fl_Preferences &prefs); - void write(Fd_Project_Writer*); - void read(Fd_Project_Reader*); + void write(fld::io::Project_Writer*); + void read(fld::io::Project_Reader*); int textsize_not_null(); }; @@ -91,8 +91,8 @@ public: 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 write(fld::io::Project_Writer*); + void read(fld::io::Project_Reader*); void update_label(); void storage(Fd_Tool_Store s) { storage_ = s; update_label(); } void name(const char *n); @@ -139,8 +139,8 @@ public: int save(const std::string &filename); 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*); + void write(fld::io::Project_Writer*); + void read(fld::io::Project_Reader*); int add(Fd_Layout_Suite*); void remove(int index); void remove_all(Fd_Tool_Store storage); diff --git a/fluid/app/Fluid_Image.cxx b/fluid/app/Fluid_Image.cxx index d25f17023..a79ac6c35 100644 --- a/fluid/app/Fluid_Image.cxx +++ b/fluid/app/Fluid_Image.cxx @@ -17,11 +17,12 @@ #include "app/Fluid_Image.h" #include "app/fluid.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "nodes/Fl_Group_Type.h" #include "nodes/Fl_Window_Type.h" -#include "tools/fluid_filename.h" +#include "tools/filename.h" #include #include @@ -49,7 +50,7 @@ void Fluid_Image::deimage(Fl_Widget *o) { /** Write the contents of the name() file as binary source code. \param fmt short name of file contents for error message \return 0 if the file could not be opened or read */ -size_t Fluid_Image::write_static_binary(Fd_Code_Writer& f, const char* fmt) { +size_t Fluid_Image::write_static_binary(fld::io::Code_Writer& f, const char* fmt) { size_t nData = 0; enter_project_dir(); FILE *in = fl_fopen(name(), "rb"); @@ -75,7 +76,7 @@ size_t Fluid_Image::write_static_binary(Fd_Code_Writer& f, const char* fmt) { /** Write the contents of the name() file as textual source code. \param fmt short name of file contents for error message \return 0 if the file could not be opened or read */ -size_t Fluid_Image::write_static_text(Fd_Code_Writer& f, const char* fmt) { +size_t Fluid_Image::write_static_text(fld::io::Code_Writer& f, const char* fmt) { size_t nData = 0; enter_project_dir(); FILE *in = fl_fopen(name(), "rb"); @@ -98,7 +99,7 @@ size_t Fluid_Image::write_static_text(Fd_Code_Writer& f, const char* fmt) { return nData; } -void Fluid_Image::write_static_rgb(Fd_Code_Writer& f, const char* idata_name) { +void Fluid_Image::write_static_rgb(fld::io::Code_Writer& f, const char* idata_name) { // Write image data... f.write_c("\n"); f.write_c_once("#include \n"); @@ -119,7 +120,7 @@ void Fluid_Image::write_static_rgb(Fd_Code_Writer& f, const char* idata_name) { \param compressed write data in the original compressed file format */ -void Fluid_Image::write_static(Fd_Code_Writer& f, int compressed) { +void Fluid_Image::write_static(fld::io::Code_Writer& f, int compressed) { if (!img) return; const char *idata_name = f.unique_id(this, "idata", fl_filename_name(name()), 0); function_name_ = f.unique_id(this, "image", fl_filename_name(name()), 0); @@ -241,14 +242,14 @@ void Fluid_Image::write_static(Fd_Code_Writer& f, int compressed) { } } -void Fluid_Image::write_file_error(Fd_Code_Writer& f, const char *fmt) { +void Fluid_Image::write_file_error(fld::io::Code_Writer& f, const char *fmt) { f.write_c("#warning Cannot read %s file \"%s\": %s\n", fmt, name(), strerror(errno)); enter_project_dir(); f.write_c("// Searching in path \"%s\"\n", fl_getcwd(0, FL_PATH_MAX)); leave_project_dir(); } -void Fluid_Image::write_initializer(Fd_Code_Writer& f, const char *type_name, const char *format, ...) { +void Fluid_Image::write_initializer(fld::io::Code_Writer& f, const char *type_name, const char *format, ...) { /* Outputs code that returns (and initializes if needed) an Fl_Image as follows: static Fl_Image *'function_name_'() { static Fl_Image *image = NULL; @@ -271,7 +272,7 @@ void Fluid_Image::write_initializer(Fd_Code_Writer& f, const char *type_name, co va_end(ap); } -void Fluid_Image::write_code(Fd_Code_Writer& f, int bind, const char *var, int inactive) { +void Fluid_Image::write_code(fld::io::Code_Writer& f, int bind, const char *var, int inactive) { /* Outputs code that attaches an image to an Fl_Widget or Fl_Menu_Item. This code calls a function output before by Fluid_Image::write_initializer() */ if (img) { @@ -281,7 +282,7 @@ void Fluid_Image::write_code(Fd_Code_Writer& f, int bind, const char *var, int i } } -void Fluid_Image::write_inline(Fd_Code_Writer& f, int inactive) { +void Fluid_Image::write_inline(fld::io::Code_Writer& f, int inactive) { if (img) f.write_c("%s()", function_name_); } diff --git a/fluid/app/Fluid_Image.h b/fluid/app/Fluid_Image.h index e3b5faaac..f095e83ce 100644 --- a/fluid/app/Fluid_Image.h +++ b/fluid/app/Fluid_Image.h @@ -21,7 +21,7 @@ #ifndef FLUID_IMAGE_H #define FLUID_IMAGE_H -#include "io/code.h" +#include "io/Code_Writer.h" #include @@ -34,9 +34,9 @@ class Fluid_Image { protected: Fluid_Image(const char *name); // no public constructor ~Fluid_Image(); // no public destructor - size_t write_static_binary(Fd_Code_Writer& f, const char* fmt); - size_t write_static_text(Fd_Code_Writer& f, const char* fmt); - void write_static_rgb(Fd_Code_Writer& f, const char* idata_name); + size_t write_static_binary(fld::io::Code_Writer& f, const char* fmt); + size_t write_static_text(fld::io::Code_Writer& f, const char* fmt); + void write_static_rgb(fld::io::Code_Writer& f, const char* idata_name); public: int written; static Fluid_Image* find(const char *); @@ -44,11 +44,11 @@ public: void increment(); void image(Fl_Widget *); // set the image of this widget void deimage(Fl_Widget *); // set the deimage of this widget - void write_static(Fd_Code_Writer& f, int compressed); - void write_initializer(Fd_Code_Writer& f, const char *type_name, const char *format, ...); - void write_code(Fd_Code_Writer& f, int bind, const char *var, int inactive = 0); - void write_inline(Fd_Code_Writer& f, int inactive = 0); - void write_file_error(Fd_Code_Writer& f, const char *fmt); + void write_static(fld::io::Code_Writer& f, int compressed); + void write_initializer(fld::io::Code_Writer& f, const char *type_name, const char *format, ...); + void write_code(fld::io::Code_Writer& f, int bind, const char *var, int inactive = 0); + void write_inline(fld::io::Code_Writer& f, int inactive = 0); + void write_file_error(fld::io::Code_Writer& f, const char *fmt); const char *name() const {return name_;} }; diff --git a/fluid/app/fluid.cxx b/fluid/app/fluid.cxx index 8bef5ab9f..efccc5a86 100644 --- a/fluid/app/fluid.cxx +++ b/fluid/app/fluid.cxx @@ -16,10 +16,12 @@ #include "app/fluid.h" +#include "app/project.h" #include "app/mergeback.h" #include "app/undo.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "nodes/Fl_Type.h" #include "nodes/Fl_Function_Type.h" #include "nodes/Fl_Group_Type.h" @@ -136,9 +138,6 @@ Fl_Menu_Item *restricted_item = NULL; //////////////////////////////////////////////////////////////// -/// Filename of the current .fl project file -static const char *filename = NULL; - /// Set if the current design has been modified compared to the associated .fl design file. int modflag = 0; @@ -195,78 +194,13 @@ int pasteoffset = 0; /// Paste offset incrementing at every paste command. static int ipasteoffset = 0; -// ---- project settings - -/// The current project, possibly a new, empty roject -Fluid_Project g_project; - -/** - Initialize a new project. - */ -Fluid_Project::Fluid_Project() : - i18n_type(FD_I18N_NONE), - include_H_from_C(1), - use_FL_COMMAND(0), - utf8_in_src(0), - avoid_early_includes(0), - header_file_set(0), - code_file_set(0), - write_mergeback_data(0), - header_file_name(".h"), - code_file_name(".cxx") -{ } - -/** - Clear all project resources. - Not implemented. - */ -Fluid_Project::~Fluid_Project() { -} - -/** - Reset all project setting to create a new empty project. - */ -void Fluid_Project::reset() { - ::delete_all(); - i18n_type = FD_I18N_NONE; - - i18n_gnu_include = ""; - i18n_gnu_conditional = ""; - i18n_gnu_function = "gettext"; - i18n_gnu_static_function = "gettext_noop"; - - i18n_pos_include = ""; - i18n_pos_conditional = ""; - i18n_pos_file = ""; - i18n_pos_set = "1"; - - include_H_from_C = 1; - use_FL_COMMAND = 0; - utf8_in_src = 0; - avoid_early_includes = 0; - header_file_set = 0; - code_file_set = 0; - header_file_name = ".h"; - code_file_name = ".cxx"; - write_mergeback_data = 0; -} - -/** - Tell the project and i18n tab of the settings dialog to refresh themselves. - */ -void Fluid_Project::update_settings_dialog() { - if (settings_window) { - w_settings_project_tab->do_callback(w_settings_project_tab, LOAD); - w_settings_i18n_tab->do_callback(w_settings_i18n_tab, LOAD); - } -} /** Make sure that a path name ends with a forward slash. \param[in] str directory or path name \return a new string, ending with a '/' */ -static std::string end_with_slash(const std::string &str) { +std::string end_with_slash(const std::string &str) { char last = str[str.size()-1]; if (last !='/' && last != '\\') return str + "/"; @@ -457,14 +391,14 @@ void enter_project_dir() { // check if we are already in the project dir and do nothing if so if (in_project_dir>1) return; // check if there is an active project, and do nothing if there is none - if (!filename || !*filename) { + if (!g_project.proj_filename || !*g_project.proj_filename) { fprintf(stderr, "** Fluid internal error: enter_project_dir() no filename set\n"); return; } // store the current working directory for later app_work_dir = fl_getcwd_str(); // set the current directory to the path of our .fl file - std::string project_path = fl_filename_path_str(fl_filename_absolute_str(filename)); + std::string project_path = fl_filename_path_str(fl_filename_absolute_str(g_project.proj_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)); @@ -601,7 +535,7 @@ static void external_editor_timer(void*) { void save_cb(Fl_Widget *, void *v) { flush_text_widgets(); Fl_Native_File_Chooser fnfc; - const char *c = filename; + const char *c = g_project.proj_filename; if (v || !c || !*c) { fnfc.title("Save To:"); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); @@ -617,7 +551,7 @@ void save_cb(Fl_Widget *, void *v) { if (v != (void *)2) set_filename(c); } - if (!write_file(c)) { + if (!fld::io::write_file(c)) { fl_alert("Error writing %s: %s", c, strerror(errno)); return; } @@ -693,7 +627,7 @@ void save_template_cb(Fl_Widget *, void *) { "Replace", NULL, c) == 0) return; } - if (!write_file(filename)) { + if (!fld::io::write_file(filename)) { fl_alert("Error writing %s: %s", filename, strerror(errno)); return; } @@ -748,11 +682,11 @@ void revert_cb(Fl_Widget *,void *) { "Cancel", "Revert", NULL)) return; } undo_suspend(); - if (!read_file(filename, 0)) { + if (!fld::io::read_file(g_project.proj_filename, 0)) { undo_resume(); widget_browser->rebuild(); g_project.update_settings_dialog(); - fl_message("Can't read %s: %s", filename, strerror(errno)); + fl_message("Can't read %s: %s", g_project.proj_filename, strerror(errno)); return; } widget_browser->rebuild(); @@ -943,13 +877,13 @@ bool new_project_from_template() { fclose(outfile); undo_suspend(); - read_file(cutfname(1), 0); + fld::io::read_file(cutfname(1), 0); fl_unlink(cutfname(1)); undo_resume(); } else { // No instance name, so read the template without replacements... undo_suspend(); - read_file(tname, 0); + fld::io::read_file(tname, 0); undo_resume(); } } @@ -976,8 +910,8 @@ std::string open_project_filechooser(const std::string &title) { dialog.title(title.c_str()); dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); dialog.filter("FLUID Files\t*.f[ld]\n"); - if (filename) { - std::string current_project_file = filename; + if (g_project.proj_filename) { + std::string current_project_file = g_project.proj_filename; dialog.directory(fl_filename_path_str(current_project_file).c_str()); dialog.preset_file(fl_filename_name_str(current_project_file).c_str()); } @@ -1010,18 +944,18 @@ bool merge_project_file(const std::string &filename_arg) { } const char *c = new_filename.c_str(); - const char *oldfilename = filename; - filename = NULL; + const char *oldfilename = g_project.proj_filename; + g_project.proj_filename = NULL; set_filename(c); if (is_a_merge) undo_checkpoint(); undo_suspend(); - if (!read_file(c, is_a_merge)) { + if (!fld::io::read_file(c, is_a_merge)) { undo_resume(); widget_browser->rebuild(); g_project.update_settings_dialog(); fl_message("Can't read %s: %s", c, strerror(errno)); - free((void *)filename); - filename = oldfilename; + free((void *)g_project.proj_filename); + g_project.proj_filename = oldfilename; if (main_window) set_modflag(modflag); return false; } @@ -1081,111 +1015,6 @@ void apple_open_cb(const char *c) { } #endif // __APPLE__ -/** - Get the absolute path of the project file, for example `/Users/matt/dev/`. - \return the path ending in '/' - */ -std::string Fluid_Project::projectfile_path() const { - return end_with_slash(fl_filename_absolute_str(fl_filename_path_str(filename), g_launch_path)); -} - -/** - Get the project file name including extension, for example `test.fl`. - \return the file name without path - */ -std::string Fluid_Project::projectfile_name() const { - return fl_filename_name(filename); -} - -/** - Get the absolute path of the generated C++ code file, for example `/Users/matt/dev/src/`. - \return the path ending in '/' - */ -std::string Fluid_Project::codefile_path() const { - std::string path = fl_filename_path_str(code_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); - else - return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); -} - -/** - Get the generated C++ code file name including extension, for example `test.cxx`. - \return the file name without path - */ -std::string Fluid_Project::codefile_name() const { - std::string name = fl_filename_name_str(code_file_name); - if (name.empty()) { - return fl_filename_setext_str(fl_filename_name(filename), ".cxx"); - } else if (name[0] == '.') { - return fl_filename_setext_str(fl_filename_name(filename), code_file_name); - } else { - return name; - } -} - -/** - Get the absolute path of the generated C++ header file, for example `/Users/matt/dev/src/`. - \return the path ending in '/' - */ -std::string Fluid_Project::headerfile_path() const { - std::string path = fl_filename_path_str(header_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); - else - return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); -} - -/** - Get the generated C++ header file name including extension, for example `test.cxx`. - \return the file name without path - */ -std::string Fluid_Project::headerfile_name() const { - std::string name = fl_filename_name_str(header_file_name); - if (name.empty()) { - return fl_filename_setext_str(fl_filename_name_str(filename), ".h"); - } else if (name[0] == '.') { - return fl_filename_setext_str(fl_filename_name_str(filename), header_file_name); - } else { - return name; - } -} - -/** - Get the absolute path of the generated i18n strings file, for example `/Users/matt/dev/`. - Although it may be more useful to put the text file into the same directory - with the source and header file, historically, the text is always saved with - the project file in interactive mode, and in the FLUID launch directory in - batch mode. - \return the path ending in '/' - */ -std::string Fluid_Project::stringsfile_path() const { - if (batch_mode) - return g_launch_path; - else - return projectfile_path(); -} - -/** - Get the generated i18n text file name including extension, for example `test.po`. - \return the file name without path - */ -std::string Fluid_Project::stringsfile_name() const { - switch (i18n_type) { - default: return fl_filename_setext_str(fl_filename_name(filename), ".txt"); - case FD_I18N_GNU: return fl_filename_setext_str(fl_filename_name(filename), ".po"); - case FD_I18N_POSIX: return fl_filename_setext_str(fl_filename_name(filename), ".msg"); - } -} - -/** - Get the name of the project file without the filename extension. - \return the file name without path or extension - */ -std::string Fluid_Project::basename() const { - return fl_filename_setext_str(fl_filename_name(filename), ""); -} - /** Generate the C++ source and header filenames and write those files. @@ -1210,13 +1039,13 @@ int write_code_files(bool dont_show_completion_dialog) { // -- handle user interface issues flush_text_widgets(); - if (!filename) { + if (!g_project.proj_filename) { save_cb(0,0); - if (!filename) return 1; + if (!g_project.proj_filename) return 1; } // -- generate the file names with absolute paths - Fd_Code_Writer f; + fld::io::Code_Writer f; std::string code_filename = g_project.codefile_path() + g_project.codefile_name(); std::string header_filename = g_project.headerfile_path() + g_project.headerfile_name(); @@ -1312,9 +1141,9 @@ void mergeback_cb(Fl_Widget *, void *) { */ void write_strings_cb(Fl_Widget *, void *) { flush_text_widgets(); - if (!filename) { + if (!g_project.proj_filename) { save_cb(0,0); - if (!filename) return; + if (!g_project.proj_filename) return; } std::string filename = g_project.stringsfile_path() + g_project.stringsfile_name(); int x = write_strings(filename); @@ -1354,7 +1183,7 @@ void copy_cb(Fl_Widget*, void*) { } flush_text_widgets(); ipasteoffset = 10; - if (!write_file(cutfname(),1)) { + if (!fld::io::write_file(cutfname(),1)) { fl_message("Can't write %s: %s", cutfname(), strerror(errno)); return; } @@ -1369,7 +1198,7 @@ void cut_cb(Fl_Widget *, void *) { return; } flush_text_widgets(); - if (!write_file(cutfname(),1)) { + if (!fld::io::write_file(cutfname(),1)) { fl_message("Can't write %s: %s", cutfname(), strerror(errno)); return; } @@ -1422,7 +1251,7 @@ void paste_cb(Fl_Widget*, void*) { //strategy = Strategy::FROM_FILE_AS_FIRST_CHILD; } } - if (!read_file(cutfname(), 1, strategy)) { + if (!fld::io::read_file(cutfname(), 1, strategy)) { widget_browser->rebuild(); fl_message("Can't read %s: %s", cutfname(), strerror(errno)); } @@ -1464,7 +1293,7 @@ void duplicate_cb(Fl_Widget*, void*) { Fl_Type::current = new_insert; // write the selected widgets to a file: - if (!write_file(cutfname(1),1)) { + if (!fld::io::write_file(cutfname(1),1)) { fl_message("Can't write %s: %s", cutfname(1), strerror(errno)); return; } @@ -1473,7 +1302,7 @@ void duplicate_cb(Fl_Widget*, void*) { pasteoffset = 0; undo_checkpoint(); undo_suspend(); - if (!read_file(cutfname(1), 1, Strategy::FROM_FILE_AFTER_CURRENT)) { + if (!fld::io::read_file(cutfname(1), 1, Strategy::FROM_FILE_AFTER_CURRENT)) { fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); } fl_unlink(cutfname(1)); @@ -1625,7 +1454,7 @@ void print_menu_cb(Fl_Widget *, void *) { fl_draw(date, w - (int)fl_width(date), fl_height()); // Get the base filename... - std::string basename = fl_filename_name_str(std::string(filename)); + std::string basename = fl_filename_name_str(std::string(g_project.proj_filename)); fl_draw(basename.c_str(), 0, fl_height()); // print centered and scaled to fit in the page @@ -2027,11 +1856,11 @@ void update_history(const char *flname) { \param[in] c the new absolute filename and path */ void set_filename(const char *c) { - if (filename) free((void *)filename); - filename = c ? fl_strdup(c) : NULL; + if (g_project.proj_filename) free((void *)g_project.proj_filename); + g_project.proj_filename = c ? fl_strdup(c) : NULL; - if (filename && !batch_mode) - update_history(filename); + if (g_project.proj_filename && !batch_mode) + update_history(g_project.proj_filename); set_modflag(modflag); } @@ -2072,8 +1901,8 @@ void set_modflag(int mf, int mfc) { if (main_window) { std::string basename; - if (!filename) basename = "Untitled.fl"; - else basename = fl_filename_name_str(std::string(filename)); + if (!g_project.proj_filename) basename = "Untitled.fl"; + else basename = fl_filename_name_str(std::string(g_project.proj_filename)); code_ext = fl_filename_ext(g_project.code_file_name.c_str()); char mod_star = modflag ? '*' : ' '; char mod_c_star = modflag_c ? '*' : ' '; @@ -2266,7 +2095,7 @@ int fluid_main(int argc,char **argv) { } } undo_suspend(); - if (c && !read_file(c,0)) { + if (c && !fld::io::read_file(c,0)) { if (batch_mode) { fprintf(stderr,"%s : %s\n", c, strerror(errno)); exit(1); @@ -2289,7 +2118,7 @@ int fluid_main(int argc,char **argv) { } if (update_file) { // fluid -u - write_file(c,0); + fld::io::write_file(c,0); if (!compile_file) exit(0); } diff --git a/fluid/app/fluid.h b/fluid/app/fluid.h index 9b4394637..686047a72 100644 --- a/fluid/app/fluid.h +++ b/fluid/app/fluid.h @@ -14,10 +14,10 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_FLUID_H -#define _FLUID_FLUID_H +#ifndef FLUID_APP_FLUID_H +#define FLUID_APP_FLUID_H -#include "tools/fluid_filename.h" +#include "tools/filename.h" #include #include @@ -99,82 +99,6 @@ extern std::string g_launch_path; extern std::string g_autodoc_path; -// ---- project class declaration - -/** - Enumeration of available internationalization types. - */ -typedef enum { - FD_I18N_NONE = 0, ///< No i18n, all strings are litearals - FD_I18N_GNU, ///< GNU gettext internationalization - FD_I18N_POSIX ///< Posix catgets internationalization -} Fd_I18n_Type; - -/** - Data and settings for a FLUID project file. - */ -class Fluid_Project { -public: - Fluid_Project(); - ~Fluid_Project(); - void reset(); - void update_settings_dialog(); - - std::string projectfile_path() const; - std::string projectfile_name() const; - std::string codefile_path() const; - std::string codefile_name() const; - std::string headerfile_path() const; - std::string headerfile_name() const; - std::string stringsfile_path() const; - std::string stringsfile_name() const; - std::string basename() const; - - /// One of the available internationalization types. - Fd_I18n_Type i18n_type; - /// Include file for GNU i18n, writes an #include statement into the source - /// file. This is usually `` or `"gettext.h"` for GNU gettext. - std::string i18n_gnu_include; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_gnu_conditional; - /// For the gettext/intl.h options, this is the function that translates text - /// at runtime. This is usually "gettext" or "_". - std::string i18n_gnu_function; - /// For the gettext/intl.h options, this is the function that marks the translation - /// of text at initialisation time. This is usually "gettext_noop" or "N_". - std::string i18n_gnu_static_function; - - /// Include file for Posix i18n, write a #include statement into the source - /// file. This is usually `` for Posix catgets. - std::string i18n_pos_include; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_pos_conditional; - /// Name of the nl_catd database - std::string i18n_pos_file; - /// Message set ID for the catalog. - std::string i18n_pos_set; - - /// If set, generate code to include the header file form the c++ file - int include_H_from_C; - /// If set, handle keyboard shortcut Ctrl on macOS using Cmd instead - int use_FL_COMMAND; - /// Clear if UTF-8 characters in statics texts are written as escape sequences - int utf8_in_src; - /// If set, will not be included from the header code before anything else - int avoid_early_includes; - /// If set, command line overrides header file name in .fl file. - int header_file_set; - /// If set, command line overrides source code file name in .fl file. - int code_file_set; - int write_mergeback_data; - /// Hold the default extension for header files, or the entire filename if set via command line. - std::string header_file_name; - /// Hold the default extension for source code files, or the entire filename if set via command line. - std::string code_file_name; -}; - -extern Fluid_Project g_project; - // ---- public functions extern int fluid_main(int argc,char **argv); @@ -186,6 +110,7 @@ extern void set_filename(const char *c); extern void set_modflag(int mf, int mfc=-1); extern const std::string &get_tmpdir(); +extern std::string end_with_slash(const std::string &str); // ---- public callback functions @@ -205,5 +130,5 @@ inline int fd_min(int a, int b) { return (a < b ? a : b); } inline int fd_max(int a, int b) { return (a > b ? a : b); } inline int fd_min(int a, int b, int c) { return fd_min(a, fd_min(b, c)); } -#endif // _FLUID_FLUID_H +#endif // FLUID_APP_FLUID_H diff --git a/fluid/app/mergeback.cxx b/fluid/app/mergeback.cxx index f914f6e1e..e0eafe500 100644 --- a/fluid/app/mergeback.cxx +++ b/fluid/app/mergeback.cxx @@ -21,7 +21,7 @@ #include "app/fluid.h" #include "app/undo.h" -#include "io/code.h" +#include "io/Code_Writer.h" #include "nodes/Fl_Function_Type.h" #include "nodes/Fl_Widget_Type.h" @@ -92,7 +92,7 @@ extern void redraw_browser(); Returns 0 if nothing changed, and 1 if it merged any changes back, and -1 if there were conflicts. - \note this function is currently part of Fd_Code_Writer to get easy access + \note this function is currently part of fld::io::Code_Writer to get easy access to our crc32 code that also wrote the code file originally. \param[in] s path and filename of the source code file @@ -242,7 +242,7 @@ void Fd_Mergeback::analyse_callback(unsigned long code_crc, unsigned long tag_cr Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_true_widget()) { std::string cb = tp->callback(); cb += "\n"; - unsigned long project_crc = Fd_Code_Writer::block_crc(cb.c_str()); + unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str()); // check if the code and project crc are the same, so this modification was already applied if (project_crc!=code_crc) { num_changed_code++; @@ -264,7 +264,7 @@ void Fd_Mergeback::analyse_code(unsigned long code_crc, unsigned long tag_crc, i Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_a(ID_Code)) { std::string code = tp->name(); code += "\n"; - unsigned long project_crc = Fd_Code_Writer::block_crc(code.c_str()); + unsigned long project_crc = fld::io::Code_Writer::block_crc(code.c_str()); // check if the code and project crc are the same, so this modification was already applied if (project_crc!=code_crc) { num_changed_code++; @@ -321,7 +321,7 @@ int Fd_Mergeback::analyse() { const char *tag = strstr(line, "//~fl~"); if (!tag) { // if this line has no tag, add the contents to the CRC and continue - code_crc = Fd_Code_Writer::block_crc(line, -1, code_crc, &line_start); + code_crc = fld::io::Code_Writer::block_crc(line, -1, code_crc, &line_start); } else { // if this line has a tag, read all tag data int tag_type = -1, uid = 0; @@ -357,7 +357,7 @@ int Fd_Mergeback::apply_callback(long block_end, long block_start, unsigned long Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_true_widget()) { std::string cb = tp->callback(); cb += "\n"; - unsigned long project_crc = Fd_Code_Writer::block_crc(cb.c_str()); + unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str()); if (project_crc!=code_crc) { tp->callback(read_and_unindent_block(block_start, block_end).c_str()); return 1; @@ -373,7 +373,7 @@ int Fd_Mergeback::apply_code(long block_end, long block_start, unsigned long cod Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_a(ID_Code)) { std::string cb = tp->name(); cb += "\n"; - unsigned long project_crc = Fd_Code_Writer::block_crc(cb.c_str()); + unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str()); if (project_crc!=code_crc) { tp->name(read_and_unindent_block(block_start, block_end).c_str()); return 1; @@ -409,7 +409,7 @@ int Fd_Mergeback::apply() { const char *tag = strstr(line, "//~fl~"); if (!tag) { // if this line has no tag, add the contents to the CRC and continue - code_crc = Fd_Code_Writer::block_crc(line, -1, code_crc, &line_start); + code_crc = fld::io::Code_Writer::block_crc(line, -1, code_crc, &line_start); block_end = ::ftell(code); } else { // if this line has a tag, read all tag data diff --git a/fluid/app/project.cxx b/fluid/app/project.cxx index 2ce91adc4..f369680e5 100644 --- a/fluid/app/project.cxx +++ b/fluid/app/project.cxx @@ -14,187 +14,10 @@ // https://www.fltk.org/bugs.php // -#include "app/fluid.h" +#include "app/project.h" -#include "app/mergeback.h" -#include "app/undo.h" -#include "io/Project_Reader.h" -#include "io/Project_Writer.h" -#include "io/Code_Writer.h" #include "nodes/Fl_Type.h" -#include "nodes/Fl_Function_Type.h" -#include "nodes/Fl_Group_Type.h" -#include "nodes/Fl_Window_Type.h" -#include "nodes/factory.h" #include "panels/settings_panel.h" -#include "panels/function_panel.h" -#include "panels/codeview_panel.h" -#include "panels/template_panel.h" -#include "panels/about_panel.h" -#include "rsrcs/pixmaps.h" -#include "app/shell_command.h" -#include "tools/autodoc.h" -#include "widgets/Node_Browser.h" - -#include -#ifdef __APPLE__ -#include // for fl_open_callback -#endif -#include -#include -#include -#include -#include -#include -#include // setlocale().. -#include "../src/flstring.h" - -extern "C" -{ -#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) -# include -# ifdef HAVE_PNG_H -# include -# else -# include -# endif // HAVE_PNG_H -#endif // HAVE_LIBPNG && HAVE_LIBZ -} - -/// \defgroup globals Fluid Global Variables, Functions and Callbacks -/// \{ - -// -// Globals.. -// - -/// FLUID-wide help dialog. -static Fl_Help_Dialog *help_dialog = NULL; - -/// Main app window menu bar. -Fl_Menu_Bar *main_menubar = NULL; - -/// Main app window. -Fl_Window *main_window; - -/// Fluid application preferences, always accessible, will be flushed when app closes. -Fl_Preferences fluid_prefs(Fl_Preferences::USER_L, "fltk.org", "fluid"); - -/// Show guides in the design window when positioning widgets, saved in app preferences. -int show_guides = 1; - -/// Show areas of restricted use in overlay plane. -/// Restricted areas are widget that overlap each other, widgets that are outside -/// of their parent's bounds (except children of Scroll groups), and areas -/// within an Fl_Tile that are not covered by children. -int show_restricted = 1; - -/// Show a ghosted outline for groups that have very little contrast. -/// This makes groups with NO_BOX or FLAT_BOX better editable. -int show_ghosted_outline = 1; - -/// Show widget comments in the browser, saved in app preferences. -int show_comments = 1; - -/// Use external editor for editing Fl_Code_Type, saved in app preferences. -int G_use_external_editor = 0; - -/// Debugging help for external Fl_Code_Type editor. -int G_debug = 0; - -/// Run this command to load an Fl_Code_Type into an external editor, save in app preferences. -char G_external_editor_command[512]; - - -// File history info... - -/// Stores the absolute filename of the last 10 design files, saved in app preferences. -char absolute_history[10][FL_PATH_MAX]; - -/// This list of filenames is computed from \c absolute_history and displayed in the main menu. -char relative_history[10][FL_PATH_MAX]; - -/// Menuitem to save a .fl design file, will be deactivated if the design is unchanged. -Fl_Menu_Item *save_item = NULL; - -/// First Menuitem that shows the .fl design file history. -Fl_Menu_Item *history_item = NULL; - -/// Menuitem to show or hide the widget bin, label will change if bin is visible. -Fl_Menu_Item *widgetbin_item = NULL; - -/// Menuitem to show or hide the code view, label will change if view is visible. -Fl_Menu_Item *codeview_item = NULL; - -/// Menuitem to show or hide the editing overlay, label will change if overlay visibility changes. -Fl_Menu_Item *overlay_item = NULL; - -/// Menuitem to show or hide the editing guides, label will change if overlay visibility changes. -Fl_Menu_Item *guides_item = NULL; - -/// Menuitem to show or hide the restricted area overlys, label will change if overlay visibility changes. -Fl_Menu_Item *restricted_item = NULL; - -//////////////////////////////////////////////////////////////// - -/// Filename of the current .fl project file -static const char *filename = NULL; - -/// Set if the current design has been modified compared to the associated .fl design file. -int modflag = 0; - -/// Set if the code files are older than the current design. -int modflag_c = 0; - -/// Application work directory, stored here when temporarily changing to the source code directory. -/// \see goto_source_dir() -static std::string app_work_dir; - -/// Used as a counter to set the .fl project dir as the current directory. -/// \see enter_project_dir(), leave_project_dir() -static char in_project_dir = 0; - -/// Set, if Fluid was started with the command line argument -u -int update_file = 0; // fluid -u - -/// Set, if Fluid was started with the command line argument -c -int compile_file = 0; // fluid -c - -/// Set, if Fluid was started with the command line argument -cs -int compile_strings = 0; // fluid -cs - -/// Set, if Fluid was started with the command line argument -v -int show_version = 0; // fluid -v - -/// Set, if Fluid runs in batch mode, and no user interface is activated. -int batch_mode = 0; // if set (-c, -u) don't open display - -/// command line arguments that overrides the generate code file extension or name -std::string g_code_filename_arg; - -/// command line arguments that overrides the generate header file extension or name -std::string g_header_filename_arg; - -/// current directory path at application launch -std::string g_launch_path; - -/// if set, generate images for automatic documentation in this directory -std::string g_autodoc_path; - -/// path to store temporary files during app run -/// \see tmpdir_create_called -std::string tmpdir_path; - -/// true if the temporary file path was already created -/// \see tmpdir_path -bool tmpdir_create_called = false; - - -/// Offset in pixels when adding widgets from an .fl file. -int pasteoffset = 0; - -/// Paste offset incrementing at every paste command. -static int ipasteoffset = 0; // ---- project settings @@ -205,16 +28,16 @@ Fluid_Project g_project; Initialize a new project. */ Fluid_Project::Fluid_Project() : - i18n_type(FD_I18N_NONE), - include_H_from_C(1), - use_FL_COMMAND(0), - utf8_in_src(0), - avoid_early_includes(0), - header_file_set(0), - code_file_set(0), - write_mergeback_data(0), - header_file_name(".h"), - code_file_name(".cxx") +i18n_type(FD_I18N_NONE), +include_H_from_C(1), +use_FL_COMMAND(0), +utf8_in_src(0), +avoid_early_includes(0), +header_file_set(0), +code_file_set(0), +write_mergeback_data(0), +header_file_name(".h"), +code_file_name(".cxx") { } /** @@ -263,2078 +86,107 @@ void Fluid_Project::update_settings_dialog() { } /** - Make sure that a path name ends with a forward slash. - \param[in] str directory or path name - \return a new string, ending with a '/' - */ -static std::string end_with_slash(const std::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\\AppData\Local\Temp - fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId()); - std::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; - } - std::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()); - std::string name = buf; - std::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 = std::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 = std::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()) { - if (batch_mode) { - fprintf(stderr, "ERROR: Can't create directory for temporary data storage.\n"); - } else { - 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; id_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) { - if (batch_mode) { - fprintf(stderr, "WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); - } else { - 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 if no directory could be created. - */ -const std::string &get_tmpdir() { - if (!tmpdir_create_called) - create_tmpdir(); - return tmpdir_path; -} - -/** - Give the user the opportunity to save a project before clearing it. - - If the project has unsaved changes, this function pops up a dialog, that - allows the user to save the project, continue without saving the project, - or to cancel the operation. - - If the user chooses to save, and no filename was set, a file dialog allows - the user to pick a name and location, or to cancel the operation. - - \return false if the user aborted the operation and the calling function - should abort as well - */ -bool confirm_project_clear() { - if (modflag == 0) return true; - switch (fl_choice("This project has unsaved changes. Do you want to save\n" - "the project file before proceeding?", - "Cancel", "Save", "Don't Save")) - { - case 0 : /* Cancel */ - return false; - case 1 : /* Save */ - save_cb(NULL, NULL); - if (modflag) return false; // user canceled the "Save As" dialog - } - return true; -} - -// ---- - -extern Fl_Window *the_panel; - -/** - Ensure that text widgets in the widget panel propagates apply current changes. - By temporarily clearing the text focus, all text widgets with changed text - will unfocus and call their respective callbacks, propagating those changes to - their data set. - */ -void flush_text_widgets() { - if (Fl::focus() && (Fl::focus()->top_window() == the_panel)) { - Fl_Widget *old_focus = Fl::focus(); - Fl::focus(NULL); // trigger callback of the widget that is losing focus - Fl::focus(old_focus); - } -} - -// ---- - -/** - Change the current working directory to the .fl project directory. - - Every call to enter_project_dir() must have a corresponding leave_project_dir() - call. Enter and leave calls can be nested. - - The first call to enter_project_dir() remembers the original directory, usually - the launch directory of the application. Nested calls will increment a nesting - counter. When the nesting counter is back to 0, leave_project_dir() will return - to the original directory. - - The global variable 'filename' must be set to the current project file with - absolute or relative path information. - - \see leave_project_dir(), pwd, in_project_dir - */ -void enter_project_dir() { - if (in_project_dir<0) { - fprintf(stderr, "** Fluid internal error: enter_project_dir() calls unmatched\n"); - return; - } - in_project_dir++; - // check if we are already in the project dir and do nothing if so - if (in_project_dir>1) return; - // check if there is an active project, and do nothing if there is none - if (!filename || !*filename) { - fprintf(stderr, "** Fluid internal error: enter_project_dir() no filename set\n"); - return; - } - // store the current working directory for later - app_work_dir = fl_getcwd_str(); - // set the current directory to the path of our .fl file - std::string project_path = fl_filename_path_str(fl_filename_absolute_str(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)); - return; - } - //fprintf(stderr, "chdir from %s to %s\n", app_work_dir.c_str(), fl_getcwd().c_str()); -} - -/** - Change the current working directory to the previous directory. - \see enter_project_dir(), pwd, in_project_dir - */ -void leave_project_dir() { - if (in_project_dir == 0) { - fprintf(stderr, "** Fluid internal error: leave_project_dir() calls unmatched\n"); - return; - } - in_project_dir--; - // still nested, stay in the project directory - if (in_project_dir > 0) return; - // no longer nested, return to the original, usually the application working directory - if (fl_chdir(app_work_dir.c_str()) < 0) { - fprintf(stderr, "** Fluid internal error: leave_project_dir() can't chdir back to %s : %s\n", - app_work_dir.c_str(), strerror(errno)); - } -} - -/** - Position the given window window based on entries in the app preferences. - Customisable by user; feature can be switched off. - The window is not shown or hidden by this function, but a value is returned - to indicate the state to the caller. - \param[in] w position this window - \param[in] prefsName name of the preferences item that stores the window settings - \param[in] Visible default value if window is hidden or shown - \param[in] X, Y, W, H default size and position if nothing is specified in the preferences - \return 1 if the caller should make the window visible, 0 if hidden. + Get the absolute path of the project file, for example `/Users/matt/dev/`. + \return the path ending in '/' */ -char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W, int H) { - Fl_Preferences pos(fluid_prefs, prefsName); - if (prevpos_button->value()) { - pos.get("x", X, X); - pos.get("y", Y, Y); - if ( W!=0 ) { - pos.get("w", W, W); - pos.get("h", H, H); - w->resize( X, Y, W, H ); - } - else - w->position( X, Y ); - } - pos.get("visible", Visible, Visible); - return Visible; +std::string Fluid_Project::projectfile_path() const { + return end_with_slash(fl_filename_absolute_str(fl_filename_path_str(proj_filename), g_launch_path)); } /** - Save the position and visibility state of a window to the app preferences. - \param[in] w save this window data - \param[in] prefsName name of the preferences item that stores the window settings + Get the project file name including extension, for example `test.fl`. + \return the file name without path */ -void save_position(Fl_Window *w, const char *prefsName) { - Fl_Preferences pos(fluid_prefs, prefsName); - pos.set("x", w->x()); - pos.set("y", w->y()); - pos.set("w", w->w()); - pos.set("h", w->h()); - pos.set("visible", (int)(w->shown() && w->visible())); +std::string Fluid_Project::projectfile_name() const { + return fl_filename_name(proj_filename); } /** - Return the path and filename of a temporary file for cut or duplicated data. - \param[in] which 0 gets the cut/copy/paste buffer, 1 gets the duplication buffer - \return a pointer to a string in a static buffer + Get the absolute path of the generated C++ code file, for example `/Users/matt/dev/src/`. + \return the path ending in '/' */ -static char* cutfname(int which = 0) { - static char name[2][FL_PATH_MAX]; - static char beenhere = 0; - - if (!beenhere) { - beenhere = 1; - fluid_prefs.getUserdataPath(name[0], sizeof(name[0])); - strlcat(name[0], "cut_buffer", sizeof(name[0])); - fluid_prefs.getUserdataPath(name[1], sizeof(name[1])); - strlcat(name[1], "dup_buffer", sizeof(name[1])); - } - - return name[which]; +std::string Fluid_Project::codefile_path() const { + std::string path = fl_filename_path_str(code_file_name); + if (batch_mode) + return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); + else + return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); } /** - Timer to watch for external editor modifications. - - If one or more external editors open, check if their files were modified. - If so: reload to ram, update size/mtime records, and change fluid's - 'modified' state. + Get the generated C++ code file name including extension, for example `test.cxx`. + \return the file name without path */ -static void external_editor_timer(void*) { - int editors_open = ExternalCodeEditor::editors_open(); - if ( G_debug ) printf("--- TIMER --- External editors open=%d\n", editors_open); - if ( editors_open > 0 ) { - // Walk tree looking for files modified by external editors. - int modified = 0; - for (Fl_Type *p = Fl_Type::first; p; p = p->next) { - if ( p->is_a(ID_Code) ) { - Fl_Code_Type *code = (Fl_Code_Type*)p; - // Code changed by external editor? - if ( code->handle_editor_changes() ) { // updates ram, file size/mtime - modified++; - } - if ( code->is_editing() ) { // editor open? - code->reap_editor(); // Try to reap; maybe it recently closed - } - } - } - if ( modified ) set_modflag(1); - } - // Repeat timeout if editors still open - // The ExternalCodeEditor class handles start/stopping timer, we just - // repeat_timeout() if it's already on. NOTE: above code may have reaped - // only open editor, which would disable further timeouts. So *recheck* - // if editors still open, to ensure we don't accidentally re-enable them. - // - if ( ExternalCodeEditor::editors_open() ) { - Fl::repeat_timeout(2.0, external_editor_timer); +std::string Fluid_Project::codefile_name() const { + std::string name = fl_filename_name_str(code_file_name); + if (name.empty()) { + return fl_filename_setext_str(fl_filename_name(proj_filename), ".cxx"); + } else if (name[0] == '.') { + return fl_filename_setext_str(fl_filename_name(proj_filename), code_file_name); + } else { + return name; } } /** - Save the current design to the file given by \c filename. - If automatic, this overwrites an existing file. If interactive, if will - verify with the user. - \param[in] v if v is not NULL, or no filename is set, open a filechooser. + Get the absolute path of the generated C++ header file, for example `/Users/matt/dev/src/`. + \return the path ending in '/' */ -void save_cb(Fl_Widget *, void *v) { - flush_text_widgets(); - Fl_Native_File_Chooser fnfc; - const char *c = filename; - if (v || !c || !*c) { - fnfc.title("Save To:"); - fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); - fnfc.filter("FLUID Files\t*.f[ld]"); - if (fnfc.show() != 0) return; - c = fnfc.filename(); - if (!fl_access(c, 0)) { - std::string basename = fl_filename_name_str(std::string(c)); - if (fl_choice("The file \"%s\" already exists.\n" - "Do you want to replace it?", "Cancel", - "Replace", NULL, basename.c_str()) == 0) return; - } - - if (v != (void *)2) set_filename(c); - } - if (!fld::io::write_file(c)) { - fl_alert("Error writing %s: %s", c, strerror(errno)); - return; - } - - if (v != (void *)2) { - set_modflag(0, 1); - undo_save = undo_current; - } +std::string Fluid_Project::headerfile_path() const { + std::string path = fl_filename_path_str(header_file_name); + if (batch_mode) + return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); + else + return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); } /** - Save a design template. - \todo We should document the concept of templates. + Get the generated C++ header file name including extension, for example `test.cxx`. + \return the file name without path */ -void save_template_cb(Fl_Widget *, void *) { - // Setup the template panel... - if (!template_panel) make_template_panel(); - - template_clear(); - template_browser->add("New Template"); - template_load(); - - template_name->show(); - template_name->value(""); - - template_instance->hide(); - - template_delete->show(); - template_delete->deactivate(); - - template_submit->label("Save"); - template_submit->deactivate(); - - template_panel->label("Save Template"); - - // Show the panel and wait for the user to do something... - template_panel->show(); - while (template_panel->shown()) Fl::wait(); - - // Get the template name, return if it is empty... - const char *c = template_name->value(); - if (!c || !*c) return; - - // Convert template name to filename_with_underscores - char savename[FL_PATH_MAX], *saveptr; - strlcpy(savename, c, sizeof(savename)); - for (saveptr = savename; *saveptr; saveptr ++) { - if (isspace(*saveptr)) *saveptr = '_'; - } - - // Find the templates directory... - char filename[FL_PATH_MAX]; - fluid_prefs.getUserdataPath(filename, sizeof(filename)); - - strlcat(filename, "templates", sizeof(filename)); - if (fl_access(filename, 0)) fl_make_path(filename); - - strlcat(filename, "/", sizeof(filename)); - strlcat(filename, savename, sizeof(filename)); - - char *ext = filename + strlen(filename); - if (ext >= (filename + sizeof(filename) - 5)) { - fl_alert("The template name \"%s\" is too long!", c); - return; - } - - // Save the .fl file... - strcpy(ext, ".fl"); - - if (!fl_access(filename, 0)) { - if (fl_choice("The template \"%s\" already exists.\n" - "Do you want to replace it?", "Cancel", - "Replace", NULL, c) == 0) return; - } - - if (!fld::io::write_file(filename)) { - fl_alert("Error writing %s: %s", filename, strerror(errno)); - return; - } - -#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) - // Get the screenshot, if any... - Fl_Type *t; - - for (t = Fl_Type::first; t; t = t->next) { - // Find the first window... - if (t->is_a(ID_Window)) break; - } - - if (!t) return; - - // Grab a screenshot... - Fl_Window_Type *wt = (Fl_Window_Type *)t; - uchar *pixels; - int w, h; - - if ((pixels = wt->read_image(w, h)) == NULL) return; - - // Save to a PNG file... - strcpy(ext, ".png"); - - errno = 0; - if (fl_write_png(filename, pixels, w, h, 3) != 0) { - delete[] pixels; - fl_alert("Error writing %s: %s", filename, strerror(errno)); - return; +std::string Fluid_Project::headerfile_name() const { + std::string name = fl_filename_name_str(header_file_name); + if (name.empty()) { + return fl_filename_setext_str(fl_filename_name_str(proj_filename), ".h"); + } else if (name[0] == '.') { + return fl_filename_setext_str(fl_filename_name_str(proj_filename), header_file_name); + } else { + return name; } - -# if 0 // The original PPM output code... - strcpy(ext, ".ppm"); - fp = fl_fopen(filename, "wb"); - fprintf(fp, "P6\n%d %d 255\n", w, h); - fwrite(pixels, w * h, 3, fp); - fclose(fp); -# endif // 0 - - delete[] pixels; -#endif // HAVE_LIBPNG && HAVE_LIBZ } /** - Reload the file set by \c filename, replacing the current design. - If the design was modified, a dialog will ask for confirmation. + Get the absolute path of the generated i18n strings file, for example `/Users/matt/dev/`. + Although it may be more useful to put the text file into the same directory + with the source and header file, historically, the text is always saved with + the project file in interactive mode, and in the FLUID launch directory in + batch mode. + \return the path ending in '/' */ -void revert_cb(Fl_Widget *,void *) { - if (modflag) { - if (!fl_choice("This user interface has been changed. Really revert?", - "Cancel", "Revert", NULL)) return; - } - undo_suspend(); - if (!fld::io::read_file(filename, 0)) { - undo_resume(); - widget_browser->rebuild(); - g_project.update_settings_dialog(); - fl_message("Can't read %s: %s", filename, strerror(errno)); - return; - } - widget_browser->rebuild(); - undo_resume(); - set_modflag(0, 0); - undo_clear(); - g_project.update_settings_dialog(); +std::string Fluid_Project::stringsfile_path() const { + if (batch_mode) + return g_launch_path; + else + return projectfile_path(); } /** - Exit Fluid; we hope you had a nice experience. - If the design was modified, a dialog will ask for confirmation. + Get the generated i18n text file name including extension, for example `test.po`. + \return the file name without path */ -void exit_cb(Fl_Widget *,void *) { - if (shell_command_running()) { - int choice = fl_choice("Previous shell command still running!", - "Cancel", - "Exit", - NULL); - if (choice == 0) { // user chose to cancel the exit operation - return; - } - } - - flush_text_widgets(); - - // verify user intention - if (confirm_project_clear() == false) - return; - - // Stop any external editor update timers - ExternalCodeEditor::stop_update_timer(); - - save_position(main_window,"main_window_pos"); - - if (widgetbin_panel) { - save_position(widgetbin_panel,"widgetbin_pos"); - delete widgetbin_panel; - } - if (codeview_panel) { - Fl_Preferences svp(fluid_prefs, "codeview"); - svp.set("autorefresh", cv_autorefresh->value()); - svp.set("autoposition", cv_autoposition->value()); - svp.set("tab", cv_tab->find(cv_tab->value())); - svp.set("code_choice", cv_code_choice); - save_position(codeview_panel,"codeview_pos"); - delete codeview_panel; - codeview_panel = 0; - } - if (shell_run_window) { - save_position(shell_run_window,"shell_run_Window_pos"); +std::string Fluid_Project::stringsfile_name() const { + switch (i18n_type) { + default: return fl_filename_setext_str(fl_filename_name(proj_filename), ".txt"); + case FD_I18N_GNU: return fl_filename_setext_str(fl_filename_name(proj_filename), ".po"); + case FD_I18N_POSIX: return fl_filename_setext_str(fl_filename_name(proj_filename), ".msg"); } - - if (about_panel) - delete about_panel; - 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(); - - // Destroy tree - // Doing so causes dtors to automatically close all external editors - // and cleans up editor tmp files. Then remove fluid tmpdir /last/. - g_project.reset(); - ExternalCodeEditor::tmpdir_clear(); - delete_tmpdir(); - - exit(0); -} - -/** - Clear the current project and create a new, empty one. - - If the current project was modified, FLUID will give the user the opportunity - to save the old project first. - - \param[in] user_must_confirm if set, a confimation dialog is presented to the - user before resetting the project. Default is `true`. - \return false if the operation was canceled - */ -bool new_project(bool user_must_confirm) { - // verify user intention - if ((user_must_confirm) && (confirm_project_clear() == false)) - return false; - - // clear the current project - g_project.reset(); - set_filename(NULL); - set_modflag(0, 0); - widget_browser->rebuild(); - g_project.update_settings_dialog(); - - // all is clear to continue - return true; } /** - Open the template browser and load a new file from templates. - - If the current project was modified, FLUID will give the user the opportunity - to save the old project first. - - \return false if the operation was canceled or failed otherwise + Get the name of the project file without the filename extension. + \return the file name without path or extension */ -bool new_project_from_template() { - // clear the current project first - if (new_project() == false) - return false; - - // Setup the template panel... - if (!template_panel) make_template_panel(); - - template_clear(); - template_browser->add("Blank"); - template_load(); - - template_name->hide(); - template_name->value(""); - - template_instance->show(); - template_instance->deactivate(); - template_instance->value(""); - - template_delete->show(); - - template_submit->label("New"); - template_submit->deactivate(); - - template_panel->label("New"); - - //if ( template_browser->size() == 1 ) { // only one item? - template_browser->value(1); // select it - template_browser->do_callback(); - //} - - // Show the panel and wait for the user to do something... - template_panel->show(); - while (template_panel->shown()) Fl::wait(); - - // See if the user chose anything... - int item = template_browser->value(); - if (item < 1) return false; - - // Load the template, if any... - const char *tname = (const char *)template_browser->data(item); - - if (tname) { - // Grab the instance name... - const char *iname = template_instance->value(); - - if (iname && *iname) { - // Copy the template to a temp file, then read it in... - char line[1024], *ptr, *next; - FILE *infile, *outfile; - - if ((infile = fl_fopen(tname, "rb")) == NULL) { - fl_alert("Error reading template file \"%s\":\n%s", tname, - strerror(errno)); - set_modflag(0); - undo_clear(); - return false; - } - - if ((outfile = fl_fopen(cutfname(1), "wb")) == NULL) { - fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1), - strerror(errno)); - fclose(infile); - set_modflag(0); - undo_clear(); - return false; - } - - while (fgets(line, sizeof(line), infile)) { - // Replace @INSTANCE@ with the instance name... - for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != NULL; ptr = next + 10) { - fwrite(ptr, next - ptr, 1, outfile); - fputs(iname, outfile); - } - - fputs(ptr, outfile); - } - - fclose(infile); - fclose(outfile); - - undo_suspend(); - fld::io::read_file(cutfname(1), 0); - fl_unlink(cutfname(1)); - undo_resume(); - } else { - // No instance name, so read the template without replacements... - undo_suspend(); - fld::io::read_file(tname, 0); - undo_resume(); - } - } - - widget_browser->rebuild(); - g_project.update_settings_dialog(); - set_modflag(0); - undo_clear(); - - return true; +std::string Fluid_Project::basename() const { + return fl_filename_setext_str(fl_filename_name(proj_filename), ""); } -/** - Open a native file chooser to allow choosing a project file for reading. - - Path and filename are preset with the current project filename, if there - is one. - - \param title a text describing the action after selecting a file (load, merge, ...) - \return the file path and name, or an empty string if the operation was canceled - */ -std::string open_project_filechooser(const std::string &title) { - Fl_Native_File_Chooser dialog; - dialog.title(title.c_str()); - dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); - dialog.filter("FLUID Files\t*.f[ld]\n"); - if (filename) { - std::string current_project_file = filename; - dialog.directory(fl_filename_path_str(current_project_file).c_str()); - dialog.preset_file(fl_filename_name_str(current_project_file).c_str()); - } - if (dialog.show() != 0) - return std::string(); - return std::string(dialog.filename()); -} - -/** - Load a project from the give file name and path. - - The project file is inserted at the currently selected type. - - If no filename is given, FLUID will open a file chooser dialog. - - \param[in] filename_arg path and name of the new project file - \return false if the operation failed - */ -bool merge_project_file(const std::string &filename_arg) { - bool is_a_merge = (Fl_Type::first != NULL); - std::string title = is_a_merge ? "Merge Project File" : "Open Project File"; - - // ask for a filename if none was given - std::string new_filename = filename_arg; - if (new_filename.empty()) { - new_filename = open_project_filechooser(title); - if (new_filename.empty()) { - return false; - } - } - - const char *c = new_filename.c_str(); - const char *oldfilename = filename; - filename = NULL; - set_filename(c); - if (is_a_merge) undo_checkpoint(); - undo_suspend(); - if (!fld::io::read_file(c, is_a_merge)) { - undo_resume(); - widget_browser->rebuild(); - g_project.update_settings_dialog(); - fl_message("Can't read %s: %s", c, strerror(errno)); - free((void *)filename); - filename = oldfilename; - if (main_window) set_modflag(modflag); - return false; - } - undo_resume(); - widget_browser->rebuild(); - if (is_a_merge) { - // Inserting a file; restore the original filename... - set_filename(oldfilename); - set_modflag(1); - } else { - // Loaded a file; free the old filename... - set_modflag(0, 0); - undo_clear(); - } - if (oldfilename) free((void *)oldfilename); - return true; -} - -/** - Open a file chooser and load an exiting project file. - - If the current project was modified, FLUID will give the user the opportunity - to save the old project first. - - If no filename is given, FLUID will open a file chooser dialog. - - \param[in] filename_arg load from this file, or show file chooser if empty - \return false if the operation was canceled or failed otherwise - */ -bool open_project_file(const std::string &filename_arg) { - // verify user intention - if (confirm_project_clear() == false) - return false; - - // ask for a filename if none was given - std::string new_filename = filename_arg; - if (new_filename.empty()) { - new_filename = open_project_filechooser("Open Project File"); - if (new_filename.empty()) { - return false; - } - } - - // clear the project and merge a file by the given name - new_project(false); - return merge_project_file(new_filename); -} - -#ifdef __APPLE__ -/** - Handle app launch with an associated filename (macOS only). - Should there be a modified design already, Fluid asks for user confirmation. - \param[in] c the filename of the new design - */ -void apple_open_cb(const char *c) { - open_project_file(std::string(c)); -} -#endif // __APPLE__ - -/** - Get the absolute path of the project file, for example `/Users/matt/dev/`. - \return the path ending in '/' - */ -std::string Fluid_Project::projectfile_path() const { - return end_with_slash(fl_filename_absolute_str(fl_filename_path_str(filename), g_launch_path)); -} - -/** - Get the project file name including extension, for example `test.fl`. - \return the file name without path - */ -std::string Fluid_Project::projectfile_name() const { - return fl_filename_name(filename); -} - -/** - Get the absolute path of the generated C++ code file, for example `/Users/matt/dev/src/`. - \return the path ending in '/' - */ -std::string Fluid_Project::codefile_path() const { - std::string path = fl_filename_path_str(code_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); - else - return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); -} - -/** - Get the generated C++ code file name including extension, for example `test.cxx`. - \return the file name without path - */ -std::string Fluid_Project::codefile_name() const { - std::string name = fl_filename_name_str(code_file_name); - if (name.empty()) { - return fl_filename_setext_str(fl_filename_name(filename), ".cxx"); - } else if (name[0] == '.') { - return fl_filename_setext_str(fl_filename_name(filename), code_file_name); - } else { - return name; - } -} - -/** - Get the absolute path of the generated C++ header file, for example `/Users/matt/dev/src/`. - \return the path ending in '/' - */ -std::string Fluid_Project::headerfile_path() const { - std::string path = fl_filename_path_str(header_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); - else - return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); -} - -/** - Get the generated C++ header file name including extension, for example `test.cxx`. - \return the file name without path - */ -std::string Fluid_Project::headerfile_name() const { - std::string name = fl_filename_name_str(header_file_name); - if (name.empty()) { - return fl_filename_setext_str(fl_filename_name_str(filename), ".h"); - } else if (name[0] == '.') { - return fl_filename_setext_str(fl_filename_name_str(filename), header_file_name); - } else { - return name; - } -} - -/** - Get the absolute path of the generated i18n strings file, for example `/Users/matt/dev/`. - Although it may be more useful to put the text file into the same directory - with the source and header file, historically, the text is always saved with - the project file in interactive mode, and in the FLUID launch directory in - batch mode. - \return the path ending in '/' - */ -std::string Fluid_Project::stringsfile_path() const { - if (batch_mode) - return g_launch_path; - else - return projectfile_path(); -} - -/** - Get the generated i18n text file name including extension, for example `test.po`. - \return the file name without path - */ -std::string Fluid_Project::stringsfile_name() const { - switch (i18n_type) { - default: return fl_filename_setext_str(fl_filename_name(filename), ".txt"); - case FD_I18N_GNU: return fl_filename_setext_str(fl_filename_name(filename), ".po"); - case FD_I18N_POSIX: return fl_filename_setext_str(fl_filename_name(filename), ".msg"); - } -} - -/** - Get the name of the project file without the filename extension. - \return the file name without path or extension - */ -std::string Fluid_Project::basename() const { - return fl_filename_setext_str(fl_filename_name(filename), ""); -} - -/** - Generate the C++ source and header filenames and write those files. - - This function creates the source filename by setting the file - extension to \c code_file_name and a header filename - with the extension \c code_file_name which are both - settable by the user. - - If the code filename has not been set yet, a "save file as" dialog will be - presented to the user. - - In batch_mode, the function will either be silent, or, if opening or writing - the files fails, write an error message to \c stderr and exit with exit code 1. - - In interactive mode, it will pop up an error message, or, if the user - hasn't disabled that, pop up a confirmation message. - - \param[in] dont_show_completion_dialog don't show the completion dialog - \return 1 if the operation failed, 0 if it succeeded - */ -int write_code_files(bool dont_show_completion_dialog) -{ - // -- handle user interface issues - flush_text_widgets(); - if (!filename) { - save_cb(0,0); - if (!filename) return 1; - } - - // -- generate the file names with absolute paths - fld::io::Code_Writer f; - std::string code_filename = g_project.codefile_path() + g_project.codefile_name(); - std::string header_filename = g_project.headerfile_path() + g_project.headerfile_name(); - - // -- write the code and header files - if (!batch_mode) enter_project_dir(); - int x = f.write_code(code_filename.c_str(), header_filename.c_str()); - std::string code_filename_rel = fl_filename_relative_str(code_filename); - std::string header_filename_rel = fl_filename_relative_str(header_filename); - if (!batch_mode) leave_project_dir(); - - // -- print error message in batch mode or pop up an error or confirmation dialog box - if (batch_mode) { - if (!x) { - fprintf(stderr, "%s and %s: %s\n", - code_filename_rel.c_str(), - header_filename_rel.c_str(), - strerror(errno)); - exit(1); - } - } else { - if (!x) { - fl_message("Can't write %s or %s: %s", - code_filename_rel.c_str(), - header_filename_rel.c_str(), - strerror(errno)); - } else { - set_modflag(-1, 0); - if (dont_show_completion_dialog==false && completion_button->value()) { - fl_message("Wrote %s and %s", - code_filename_rel.c_str(), - header_filename_rel.c_str()); - } - } - } - return 0; -} - -/** - Callback to write C++ code and header files. - */ -void write_cb(Fl_Widget *, void *) { - write_code_files(); -} - -#if 0 -// Matt: disabled -/** - Merge the possibly modified content of code files back into the project. - */ -int mergeback_code_files() -{ - flush_text_widgets(); - if (!filename) return 1; - if (!g_project.write_mergeback_data) { - fl_message("MergeBack is not enabled for this project.\n" - "Please enable MergeBack in the project settings\n" - "dialog and re-save the project file and the code."); - return 0; - } - - std::string proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); - std::string code_filename; -#if 1 - if (!batch_mode) { - Fl_Preferences build_records(Fl_Preferences::USER_L, "fltk.org", "fluid-build"); - Fl_Preferences path(build_records, proj_filename.c_str()); - int i, n = proj_filename.size(); - for (i=0; ivalue()) { - fl_message("Wrote %s", g_project.stringsfile_name().c_str()); - } - } -} - -/** - Show the editor for the \c current Fl_Type. - */ -void openwidget_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { - fl_message("Please select a widget"); - return; - } - Fl_Type::current->open(); -} - -/** - User chose to copy the currently selected widgets. - */ -void copy_cb(Fl_Widget*, void*) { - flush_text_widgets(); - if (!Fl_Type::current) { - fl_beep(); - return; - } - flush_text_widgets(); - ipasteoffset = 10; - if (!fld::io::write_file(cutfname(),1)) { - fl_message("Can't write %s: %s", cutfname(), strerror(errno)); - return; - } -} - -/** - User chose to cut the currently selected widgets. - */ -void cut_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { - fl_beep(); - return; - } - flush_text_widgets(); - if (!fld::io::write_file(cutfname(),1)) { - fl_message("Can't write %s: %s", cutfname(), strerror(errno)); - return; - } - undo_checkpoint(); - set_modflag(1); - ipasteoffset = 0; - Fl_Type *p = Fl_Type::current->parent; - while (p && p->selected) p = p->parent; - delete_all(1); - if (p) select_only(p); - widget_browser->rebuild(); -} - -/** - User chose to delete the currently selected widgets. - */ -void delete_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { - fl_beep(); - return; - } - undo_checkpoint(); - set_modflag(1); - ipasteoffset = 0; - Fl_Type *p = Fl_Type::current->parent; - while (p && p->selected) p = p->parent; - delete_all(1); - if (p) select_only(p); - widget_browser->rebuild(); -} - -/** - User chose to paste the widgets from the cut buffer. - - This function will paste the widgets in the cut buffer after the currently - selected widget. If the currently selected widget is a group widget and - it is not folded, the new widgets will be added inside the group. - */ -void paste_cb(Fl_Widget*, void*) { - pasteoffset = ipasteoffset; - undo_checkpoint(); - undo_suspend(); - Strategy strategy = Strategy::FROM_FILE_AFTER_CURRENT; - if (Fl_Type::current && Fl_Type::current->can_have_children()) { - if (Fl_Type::current->folded_ == 0) { - // If the current widget is a group widget and it is not folded, - // add the new widgets inside the group. - strategy = Strategy::FROM_FILE_AS_LAST_CHILD; - // The following alternative also works quite nicely - //strategy = Strategy::FROM_FILE_AS_FIRST_CHILD; - } - } - if (!fld::io::read_file(cutfname(), 1, strategy)) { - widget_browser->rebuild(); - fl_message("Can't read %s: %s", cutfname(), strerror(errno)); - } - undo_resume(); - widget_browser->display(Fl_Type::current); - widget_browser->rebuild(); - pasteoffset = 0; - ipasteoffset += 10; -} - -/** - Duplicate the selected widgets. - - This code is a bit complex because it needs to find the last selected - widget with the lowest level, so that the new widgets are inserted after - this one. - */ -void duplicate_cb(Fl_Widget*, void*) { - if (!Fl_Type::current) { - fl_beep(); - return; - } - - // flush the text widgets to make sure the user's changes are saved: - flush_text_widgets(); - - // find the last selected node with the lowest level: - int lowest_level = 9999; - Fl_Type *new_insert = NULL; - if (Fl_Type::current->selected) { - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { - if (t->selected && (t->level <= lowest_level)) { - lowest_level = t->level; - new_insert = t; - } - } - } - if (new_insert) - Fl_Type::current = new_insert; - - // write the selected widgets to a file: - if (!fld::io::write_file(cutfname(1),1)) { - fl_message("Can't write %s: %s", cutfname(1), strerror(errno)); - return; - } - - // read the file and add the widgets after the current one: - pasteoffset = 0; - undo_checkpoint(); - undo_suspend(); - if (!fld::io::read_file(cutfname(1), 1, Strategy::FROM_FILE_AFTER_CURRENT)) { - fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); - } - fl_unlink(cutfname(1)); - widget_browser->display(Fl_Type::current); - widget_browser->rebuild(); - undo_resume(); -} - -/** - User wants to sort selected widgets by y coordinate. - */ -static void sort_cb(Fl_Widget *,void *) { - undo_checkpoint(); - sort((Fl_Type*)NULL); - widget_browser->rebuild(); - set_modflag(1); -} - -/** - Open the "About" dialog. - */ -void about_cb(Fl_Widget *, void *) { - if (!about_panel) make_about_panel(); - about_panel->show(); -} - -/** - Open a dialog to show the HTML help page form the FLTK documentation folder. - \param[in] name name of the HTML help file. - */ -void show_help(const char *name) { - const char *docdir; - char helpname[FL_PATH_MAX]; - - if (!help_dialog) help_dialog = new Fl_Help_Dialog(); - - if ((docdir = fl_getenv("FLTK_DOCDIR")) == NULL) { - docdir = FLTK_DOCDIR; - } - snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name); - - // make sure that we can read the file - FILE *f = fopen(helpname, "rb"); - if (f) { - fclose(f); - help_dialog->load(helpname); - } else { - // if we can not read the file, we display the canned version instead - // or ask the native browser to open the page on www.fltk.org - if (strcmp(name, "fluid.html")==0) { - if (!Fl_Shared_Image::find("embedded:/fluid_flow_chart_800.png")) - new Fl_PNG_Image("embedded:/fluid_flow_chart_800.png", fluid_flow_chart_800_png, sizeof(fluid_flow_chart_800_png)); - help_dialog->value - ( - "\n" - "FLTK: Programming with FLUID\n" - "

What is FLUID?

\n" - "The Fast Light User Interface Designer, or FLUID, is a graphical editor " - "that is used to produce FLTK source code. FLUID edits and saves its state " - "in .fl files. These files are text, and you can (with care) " - "edit them in a text editor, perhaps to get some special effects.

\n" - "FLUID can \"compile\" the .fl file into a .cxx " - "and a .h file. The .cxx file defines all the " - "objects from the .fl file and the .h file " - "declares all the global ones. FLUID also supports localization " - "(Internationalization) of label strings using message files and the GNU " - "gettext or POSIX catgets interfaces.

\n" - "A simple program can be made by putting all your code (including a " - "main() function) into the .fl file and thus making the " - ".cxx file a single source file to compile. Most programs are " - "more complex than this, so you write other .cxx files that " - "call the FLUID functions. These .cxx files must " - "#include the .h file or they can #include " - "the .cxx file so it still appears to be a single source file.

" - "

" - "

More information is available online at https://www.fltk.org/" - "" - ); - } else if (strcmp(name, "license.html")==0) { - fl_open_uri("https://www.fltk.org/doc-1.4/license.html"); - return; - } else if (strcmp(name, "index.html")==0) { - fl_open_uri("https://www.fltk.org/doc-1.4/index.html"); - return; - } else { - snprintf(helpname, sizeof(helpname), "https://www.fltk.org/%s", name); - fl_open_uri(helpname); - return; - } - } - help_dialog->show(); -} - -/** - User wants help on Fluid. - */ -void help_cb(Fl_Widget *, void *) { - show_help("fluid.html"); -} - -/** - User wants to see the Fluid manual. - */ -void manual_cb(Fl_Widget *, void *) { - show_help("index.html"); -} - -// ---- Printing - -/** - Open the dialog to allow the user to print the current window. - */ -void print_menu_cb(Fl_Widget *, void *) { - int w, h, ww, hh; - int frompage, topage; - Fl_Type *t; // Current widget - int num_windows; // Number of windows - Fl_Window_Type *windows[1000]; // Windows to print - int winpage; // Current window page - Fl_Window *win; - - for (t = Fl_Type::first, num_windows = 0; t; t = t->next) { - if (t->is_a(ID_Window)) { - windows[num_windows] = (Fl_Window_Type *)t; - if (!((Fl_Window*)(windows[num_windows]->o))->shown()) continue; - num_windows ++; - } - } - - Fl_Printer printjob; - if ( printjob.start_job(num_windows, &frompage, &topage) ) return; - int pagecount = 0; - for (winpage = 0; winpage < num_windows; winpage++) { - float scale = 1, scale_x = 1, scale_y = 1; - if (winpage+1 < frompage || winpage+1 > topage) continue; - printjob.start_page(); - printjob.printable_rect(&w, &h); - - // Get the time and date... - time_t curtime = time(NULL); - struct tm *curdate = localtime(&curtime); - char date[1024]; - strftime(date, sizeof(date), "%c", curdate); - fl_font(FL_HELVETICA, 12); - fl_color(FL_BLACK); - fl_draw(date, (w - (int)fl_width(date))/2, fl_height()); - sprintf(date, "%d/%d", ++pagecount, topage-frompage+1); - fl_draw(date, w - (int)fl_width(date), fl_height()); - - // Get the base filename... - std::string basename = fl_filename_name_str(std::string(filename)); - fl_draw(basename.c_str(), 0, fl_height()); - - // print centered and scaled to fit in the page - win = (Fl_Window*)windows[winpage]->o; - ww = win->decorated_w(); - if(ww > w) scale_x = float(w)/ww; - hh = win->decorated_h(); - if(hh > h) scale_y = float(h)/hh; - if (scale_x < scale) scale = scale_x; - if (scale_y < scale) scale = scale_y; - if (scale < 1) { - printjob.scale(scale); - printjob.printable_rect(&w, &h); - } - printjob.origin(w/2, h/2); - printjob.print_window(win, -ww/2, -hh/2); - printjob.end_page(); - } - printjob.end_job(); -} - -// ---- Main menu bar - -extern void select_layout_preset_cb(Fl_Widget *, void *user_data); -extern void layout_suite_marker(Fl_Widget *, void *user_data); - -static void menu_file_new_cb(Fl_Widget *, void *) { new_project(); } -static void menu_file_new_from_template_cb(Fl_Widget *, void *) { new_project_from_template(); } -static void menu_file_open_cb(Fl_Widget *, void *) { open_project_file(""); } -static void menu_file_insert_cb(Fl_Widget *, void *) { merge_project_file(""); } -static void menu_file_open_history_cb(Fl_Widget *, void *v) { open_project_file(std::string((const char*)v)); } -static void menu_layout_sync_resize_cb(Fl_Menu_ *m, void*) { - if (m->mvalue()->value()) Fl_Type::allow_layout = 1; else Fl_Type::allow_layout = 0; } -/** - This is the main Fluid menu. - - Design history is manipulated right inside this menu structure. - Some menu items change or deactivate correctly, but most items just trigger - various callbacks. - - \c New_Menu creates new widgets and is explained in detail in another location. - - \see New_Menu - \todo This menu needs some major modernization. Menus are too long and their - sorting is not always obvious. - \todo Shortcuts are all over the place (Alt, Ctrl, Command, Shift-Ctrl, - function keys), and there should be a help page listing all shortcuts. - */ -Fl_Menu_Item Main_Menu[] = { -{"&File",0,0,0,FL_SUBMENU}, - {"&New", FL_COMMAND+'n', menu_file_new_cb}, - {"&Open...", FL_COMMAND+'o', menu_file_open_cb}, - {"&Insert...", FL_COMMAND+'i', menu_file_insert_cb, 0, FL_MENU_DIVIDER}, - {"&Save", FL_COMMAND+'s', save_cb, 0}, - {"Save &As...", FL_COMMAND+FL_SHIFT+'s', save_cb, (void*)1}, - {"Sa&ve A Copy...", 0, save_cb, (void*)2}, - {"&Revert...", 0, revert_cb, 0, FL_MENU_DIVIDER}, - {"New &From Template...", FL_COMMAND+'N', menu_file_new_from_template_cb, 0}, - {"Save As &Template...", 0, save_template_cb, 0, FL_MENU_DIVIDER}, - {"&Print...", FL_COMMAND+'p', print_menu_cb}, - {"Write &Code", FL_COMMAND+FL_SHIFT+'c', write_cb, 0}, -// Matt: disabled {"MergeBack Code", FL_COMMAND+FL_SHIFT+'m', mergeback_cb, 0}, - {"&Write Strings", FL_COMMAND+FL_SHIFT+'w', write_strings_cb, 0, FL_MENU_DIVIDER}, - {relative_history[0], FL_COMMAND+'1', menu_file_open_history_cb, absolute_history[0]}, - {relative_history[1], FL_COMMAND+'2', menu_file_open_history_cb, absolute_history[1]}, - {relative_history[2], FL_COMMAND+'3', menu_file_open_history_cb, absolute_history[2]}, - {relative_history[3], FL_COMMAND+'4', menu_file_open_history_cb, absolute_history[3]}, - {relative_history[4], FL_COMMAND+'5', menu_file_open_history_cb, absolute_history[4]}, - {relative_history[5], FL_COMMAND+'6', menu_file_open_history_cb, absolute_history[5]}, - {relative_history[6], FL_COMMAND+'7', menu_file_open_history_cb, absolute_history[6]}, - {relative_history[7], FL_COMMAND+'8', menu_file_open_history_cb, absolute_history[7]}, - {relative_history[8], FL_COMMAND+'9', menu_file_open_history_cb, absolute_history[8]}, - {relative_history[9], 0, menu_file_open_history_cb, absolute_history[9], FL_MENU_DIVIDER}, - {"&Quit", FL_COMMAND+'q', exit_cb}, - {0}, -{"&Edit",0,0,0,FL_SUBMENU}, - {"&Undo", FL_COMMAND+'z', undo_cb}, - {"&Redo", FL_COMMAND+FL_SHIFT+'z', redo_cb, 0, FL_MENU_DIVIDER}, - {"C&ut", FL_COMMAND+'x', cut_cb}, - {"&Copy", FL_COMMAND+'c', copy_cb}, - {"&Paste", FL_COMMAND+'v', paste_cb}, - {"Dup&licate", FL_COMMAND+'u', duplicate_cb}, - {"&Delete", FL_Delete, delete_cb, 0, FL_MENU_DIVIDER}, - {"Select &All", FL_COMMAND+'a', select_all_cb}, - {"Select &None", FL_COMMAND+FL_SHIFT+'a', select_none_cb, 0, FL_MENU_DIVIDER}, - {"Pr&operties...", FL_F+1, openwidget_cb}, - {"&Sort",0,sort_cb}, - {"&Earlier", FL_F+2, earlier_cb}, - {"&Later", FL_F+3, later_cb}, - {"&Group", FL_F+7, group_cb}, - {"Ung&roup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER}, - {"Hide O&verlays",FL_COMMAND+FL_SHIFT+'o',toggle_overlays}, - {"Hide Guides",FL_COMMAND+FL_SHIFT+'g',toggle_guides}, - {"Hide Restricted",FL_COMMAND+FL_SHIFT+'r',toggle_restricted}, - {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb}, - {"Show Code View",FL_ALT+'c', (Fl_Callback*)toggle_codeview_cb, 0, FL_MENU_DIVIDER}, - {"Settings...",FL_ALT+'p',show_settings_cb}, - {0}, -{"&New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER}, -{"&Layout",0,0,0,FL_SUBMENU}, - {"&Align",0,0,0,FL_SUBMENU}, - {"&Left",0,(Fl_Callback *)align_widget_cb,(void*)10}, - {"&Center",0,(Fl_Callback *)align_widget_cb,(void*)11}, - {"&Right",0,(Fl_Callback *)align_widget_cb,(void*)12}, - {"&Top",0,(Fl_Callback *)align_widget_cb,(void*)13}, - {"&Middle",0,(Fl_Callback *)align_widget_cb,(void*)14}, - {"&Bottom",0,(Fl_Callback *)align_widget_cb,(void*)15}, - {0}, - {"&Space Evenly",0,0,0,FL_SUBMENU}, - {"&Across",0,(Fl_Callback *)align_widget_cb,(void*)20}, - {"&Down",0,(Fl_Callback *)align_widget_cb,(void*)21}, - {0}, - {"&Make Same Size",0,0,0,FL_SUBMENU}, - {"&Width",0,(Fl_Callback *)align_widget_cb,(void*)30}, - {"&Height",0,(Fl_Callback *)align_widget_cb,(void*)31}, - {"&Both",0,(Fl_Callback *)align_widget_cb,(void*)32}, - {0}, - {"&Center In Group",0,0,0,FL_SUBMENU}, - {"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40}, - {"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41}, - {0}, - {"Synchronized Resize", 0, (Fl_Callback*)menu_layout_sync_resize_cb, NULL, FL_MENU_TOGGLE|FL_MENU_DIVIDER }, - {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb, NULL, FL_MENU_DIVIDER}, - {"Presets", 0, layout_suite_marker, (void*)main_layout_submenu_, FL_SUBMENU_POINTER }, - {"Application", 0, select_layout_preset_cb, (void*)0, FL_MENU_RADIO|FL_MENU_VALUE }, - {"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, 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}, - {"&About FLUID...",0,about_cb}, - {0}, -{0}}; - -/** - Change the app's and hence preview the design's scheme. - - The scheme setting is stored in the app preferences - - in key \p 'scheme_name' since 1.4.0 - - in key \p 'scheme' (index: 0 - 4) in 1.3.x - - This callback is triggered by changing the scheme in the - Fl_Scheme_Choice widget (\p Edit/GUI Settings). - - \param[in] choice the calling widget - - \see init_scheme() for choice values and backwards compatibility - */ -void scheme_cb(Fl_Scheme_Choice *choice, void *) { - if (batch_mode) - return; - - // set the new scheme only if the scheme was changed - const char *new_scheme = choice->text(choice->value()); - - if (Fl::is_scheme(new_scheme)) - return; - - Fl::scheme(new_scheme); - fluid_prefs.set("scheme_name", new_scheme); - - // Backwards compatibility: store 1.3 scheme index (1-4). - // We assume that index 0-3 (base, plastic, gtk+, gleam) are in the - // same order as in 1.3.x (index 1-4), higher values are ignored - - int scheme_index = scheme_choice->value(); - if (scheme_index <= 3) // max. index for 1.3.x (Gleam) - fluid_prefs.set("scheme", scheme_index + 1); // compensate for different indexing -} - -/** - Read Fluid's scheme preferences and set the app's scheme. - - Since FLTK 1.4.0 the scheme \b name is stored as a character string - with key "scheme_name" in the preference database. - - In FLTK 1.3.x the scheme preference was stored as an integer index - with key "scheme" in the database. The known schemes were hardcoded in - Fluid's sources (here for reference): - - | Index | 1.3 Scheme Name | Choice | 1.4 Scheme Name | - |-------|-----------------|-------|-----------------| - | 0 | Default (same as None) | n/a | n/a | - | 1 | None (same as Default) | 0 | base | - | 2 | Plastic | 1 | plastic | - | 3 | GTK+ | 2 | gtk+ | - | 4 | Gleam | 3 | gleam | - | n/a | n/a | 4 | oxy | - - The new Fluid tries to keep backwards compatibility and reads both - keys (\p scheme and \p scheme_name). If the latter is defined, it is used. - If not the old \p scheme (index) is used - but we need to subtract one to - get the new Fl_Scheme_Choice index (column "Choice" above). -*/ -void init_scheme() { - int scheme_index = 0; // scheme index for backwards compatibility (1.3.x) - char *scheme_name = 0; // scheme name since 1.4.0 - fluid_prefs.get("scheme_name", scheme_name, "XXX"); // XXX means: not set => fallback 1.3.x - if (!strcmp(scheme_name, "XXX")) { - fluid_prefs.get("scheme", scheme_index, 0); - if (scheme_index > 0) { - scheme_index--; - scheme_choice->value(scheme_index); // set the choice value - } - if (scheme_index < 0) - scheme_index = 0; - else if (scheme_index > scheme_choice->size() - 1) - scheme_index = 0; - scheme_name = const_cast(scheme_choice->text(scheme_index)); - fluid_prefs.set("scheme_name", scheme_name); - } - // Set the new scheme only if it was not overridden by the -scheme - // command line option - if (Fl::scheme() == NULL) { - Fl::scheme(scheme_name); - } - free(scheme_name); -} - -/** - Show or hide the widget bin. - The state is stored in the app preferences. - */ -void toggle_widgetbin_cb(Fl_Widget *, void *) { - if (!widgetbin_panel) { - make_widgetbin(); - if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return; - } - - if (widgetbin_panel->visible()) { - widgetbin_panel->hide(); - widgetbin_item->label("Show Widget &Bin..."); - } else { - widgetbin_panel->show(); - widgetbin_item->label("Hide Widget &Bin"); - } -} - -/** - Show or hide the code preview window. - */ -void toggle_codeview_cb(Fl_Double_Window *, void *) { - codeview_toggle_visibility(); -} - -/** - Show or hide the code preview window, button callback. - */ -void toggle_codeview_b_cb(Fl_Button*, void *) { - codeview_toggle_visibility(); -} - -/** - Build the main app window and create a few other dialogs. - */ -void make_main_window() { - if (!batch_mode) { - fluid_prefs.get("show_guides", show_guides, 1); - fluid_prefs.get("show_restricted", show_restricted, 1); - fluid_prefs.get("show_ghosted_outline", show_ghosted_outline, 0); - fluid_prefs.get("show_comments", show_comments, 1); - make_shell_window(); - } - - if (!main_window) { - Fl_Widget *o; - loadPixmaps(); - main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid"); - main_window->box(FL_NO_BOX); - o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT); - o->box(FL_FLAT_BOX); - o->tooltip("Double-click to view or change an item."); - main_window->resizable(o); - main_menubar = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT); - main_menubar->menu(Main_Menu); - // quick access to all dynamic menu items - save_item = (Fl_Menu_Item*)main_menubar->find_item(save_cb); - history_item = (Fl_Menu_Item*)main_menubar->find_item(menu_file_open_history_cb); - widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb); - codeview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_codeview_cb); - overlay_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_overlays); - guides_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_guides); - restricted_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_restricted); - main_menubar->global(); - fill_in_New_Menu(); - main_window->end(); - } - - if (!batch_mode) { - load_history(); - g_shell_config = new Fd_Shell_Command_List; - widget_browser->load_prefs(); - make_settings_window(); - } -} - -/** - Load file history from preferences. - - This loads the absolute filepaths of the last 10 used design files. - It also computes and stores the relative filepaths for display in - the main menu. - */ -void load_history() { - int i; // Looping var - int max_files; - - fluid_prefs.get("recent_files", max_files, 5); - if (max_files > 10) max_files = 10; - - for (i = 0; i < max_files; i ++) { - fluid_prefs.get( Fl_Preferences::Name("file%d", i), absolute_history[i], "", sizeof(absolute_history[i])); - if (absolute_history[i][0]) { - // Make a shortened version of the filename for the menu... - std::string fn = fl_filename_shortened(absolute_history[i], 48); - strncpy(relative_history[i], fn.c_str(), sizeof(relative_history[i]) - 1); - if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; - else history_item[i].flags = 0; - } else break; - } - - for (; i < 10; i ++) { - if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; - history_item[i].hide(); - } -} - -/** - Update file history from preferences. - - Add this new filepath to the history and update the main menu. - Writes the new file history to the app preferences. - - \param[in] flname path or filename of .fl file, will be converted into an - absolute file path based on the current working directory. - */ -void update_history(const char *flname) { - int i; // Looping var - char absolute[FL_PATH_MAX]; - int max_files; - - - fluid_prefs.get("recent_files", max_files, 5); - if (max_files > 10) max_files = 10; - - fl_filename_absolute(absolute, sizeof(absolute), flname); -#ifdef _WIN32 - // Make path canonical. - for (char *s = absolute; *s; s++) { - if (*s == '\\') - *s = '/'; - } -#endif - - - for (i = 0; i < max_files; i ++) -#if defined(_WIN32) || defined(__APPLE__) - if (!strcasecmp(absolute, absolute_history[i])) break; -#else - if (!strcmp(absolute, absolute_history[i])) break; -#endif // _WIN32 || __APPLE__ - - if (i == 0) return; - - if (i >= max_files) i = max_files - 1; - - // Move the other flnames down in the list... - memmove(absolute_history + 1, absolute_history, - i * sizeof(absolute_history[0])); - memmove(relative_history + 1, relative_history, - i * sizeof(relative_history[0])); - - // Put the new file at the top... - strlcpy(absolute_history[0], absolute, sizeof(absolute_history[0])); - std::string fn = fl_filename_shortened(absolute_history[0], 48); - strncpy(relative_history[0], fn.c_str(), sizeof(relative_history[0]) - 1); - - // Update the menu items as needed... - for (i = 0; i < max_files; i ++) { - fluid_prefs.set( Fl_Preferences::Name("file%d", i), absolute_history[i]); - if (absolute_history[i][0]) { - if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; - else history_item[i].flags = 0; - } else break; - } - - for (; i < 10; i ++) { - fluid_prefs.set( Fl_Preferences::Name("file%d", i), ""); - if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; - history_item[i].hide(); - } - fluid_prefs.flush(); -} - -/** - Set the filename of the current .fl design. - \param[in] c the new absolute filename and path - */ -void set_filename(const char *c) { - if (filename) free((void *)filename); - filename = c ? fl_strdup(c) : NULL; - - if (filename && !batch_mode) - update_history(filename); - - set_modflag(modflag); -} - - -/** - Set the "modified" flag and update the title of the main window. - - The first argument sets the modification state of the current design against - the corresponding .fl design file. Any change to the widget tree will mark - the design 'modified'. Saving the design will mark it clean. - - The second argument is optional and set the modification state of the current - design against the source code and header file. Any change to the tree, - including saving the tree, will mark the code 'outdated'. Generating source - code and header files will clear this flag until the next modification. - - \param[in] mf 0 to clear the modflag, 1 to mark the design "modified", -1 to - ignore this parameter - \param[in] mfc default -1 to let \c mf control \c modflag_c, 0 to mark the - code files current, 1 to mark it out of date. -2 to ignore changes to mf. - */ -void set_modflag(int mf, int mfc) { - const char *code_ext = NULL; - char new_title[FL_PATH_MAX]; - - // Update the modflag_c to the worst possible condition. We could be a bit - // more graceful and compare modification times of the files, but C++ has - // no API for that until C++17. - if (mf!=-1) { - modflag = mf; - if (mfc==-1 && mf==1) - mfc = mf; - } - if (mfc>=0) { - modflag_c = mfc; - } - - if (main_window) { - std::string basename; - if (!filename) basename = "Untitled.fl"; - else basename = fl_filename_name_str(std::string(filename)); - code_ext = fl_filename_ext(g_project.code_file_name.c_str()); - char mod_star = modflag ? '*' : ' '; - char mod_c_star = modflag_c ? '*' : ' '; - snprintf(new_title, sizeof(new_title), "%s%c %s%c", - basename.c_str(), mod_star, code_ext, mod_c_star); - const char *old_title = main_window->label(); - // only update the title if it actually changed - if (!old_title || strcmp(old_title, new_title)) - main_window->copy_label(new_title); - } - // if the UI was modified in any way, update the Code View panel - if (codeview_panel && codeview_panel->visible() && cv_autorefresh->value()) - codeview_defer_update(); -} - -// ---- Main program entry point - -/** - Handle command line arguments. - \param[in] argc number of arguments in the list - \param[in] argv pointer to an array of arguments - \param[inout] i current argument index - \return number of arguments used; if 0, the argument is not supported - */ -static int arg(int argc, char** argv, int& i) { - if (argv[i][0] != '-') - return 0; - if (argv[i][1] == 'd' && !argv[i][2]) { - G_debug=1; - i++; return 1; - } - if (argv[i][1] == 'u' && !argv[i][2]) { - update_file++; - batch_mode++; - i++; return 1; - } - if (argv[i][1] == 'c' && !argv[i][2]) { - compile_file++; - batch_mode++; - i++; return 1; - } - if ((strcmp(argv[i], "-v")==0) || (strcmp(argv[i], "--version")==0)) { - show_version = 1; - i++; return 1; - } - if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) { - compile_file++; - compile_strings++; - batch_mode++; - i++; return 1; - } - if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { - g_code_filename_arg = argv[i+1]; - batch_mode++; - i += 2; return 2; - } -#ifndef NDEBUG - if ((i+1 < argc) && (strcmp(argv[i], "--autodoc") == 0)) { - g_autodoc_path = argv[i+1]; - i += 2; return 2; - } -#endif - if (strcmp(argv[i], "--help")==0) { - return 0; - } - if (argv[i][1] == 'h' && !argv[i][2]) { - if ( (i+1 < argc) && (argv[i+1][0] != '-') ) { - g_header_filename_arg = argv[i+1]; - batch_mode++; - i += 2; - return 2; - } else { - // a lone "-h" without a filename will output the help string - return 0; - } - } - return 0; -} - -#if ! (defined(_WIN32) && !defined (__CYGWIN__)) - -int quit_flag = 0; -#include -#ifdef _sigargs -#define SIGARG _sigargs -#else -#ifdef __sigargs -#define SIGARG __sigargs -#else -#define SIGARG int // you may need to fix this for older systems -#endif -#endif - -extern "C" { -static void sigint(SIGARG) { - signal(SIGINT,sigint); - quit_flag = 1; -} -} - -#endif - -/** - Start Fluid. - - Fluid can run in interactive mode with a full user interface to design new - user interfaces and write the C++ files to manage them, - - Fluid can run form the command line in batch mode to convert .fl design files - into C++ source and header files. In batch mode, no display is needed, - particularly no X11 connection will be attempted on Linux/Unix. - - \param[in] argc number of arguments in the list - \param[in] argv pointer to an array of arguments - \return in batch mode, an error code will be returned via \c exit() . This - function return 1, if there was an error in the parameters list. - \todo On Windows, Fluid can under certain conditions open a dialog box, even - in batch mode. Is that intentional? Does it circumvent issues with Windows' - stderr and stdout? - */ -int fluid_main(int argc,char **argv) { - int i = 1; - - setlocale(LC_ALL, ""); // enable multi-language errors in file chooser - setlocale(LC_NUMERIC, "C"); // make sure numeric values are written correctly - g_launch_path = end_with_slash(fl_getcwd_str()); // store the current path at launch - - Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW - if ( (Fl::args(argc,argv,i,arg) == 0) // unsupported argument found - || (batch_mode && (i != argc-1)) // .fl filename missing - || (!batch_mode && (i < argc-1)) // more than one filename found - || (argv[i] && (argv[i][0] == '-'))) { // unknown option - static const char *msg = - "usage: %s name.fl\n" - " -u : update .fl file and exit (may be combined with '-c' or '-cs')\n" - " -c : write .cxx and .h and exit\n" - " -cs : write .cxx and .h and strings and exit\n" - " -o : .cxx output filename, or extension if starts with '.'\n" - " -h : .h output filename, or extension if starts with '.'\n" - " --help : brief usage information\n" - " --version, -v : print fluid version number\n" - " -d : enable internal debugging\n"; - const char *app_name = NULL; - if ( (argc > 0) && argv[0] && argv[0][0] ) - app_name = fl_filename_name(argv[0]); - if ( !app_name || !app_name[0]) - app_name = "fluid"; -#ifdef _MSC_VER - // TODO: if this is fluid-cmd, use stderr and not fl_message - fl_message(msg, app_name); -#else - fprintf(stderr, msg, app_name); -#endif - return 1; - } - if (show_version) { - printf("fluid v%d.%d.%d\n", FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION); - ::exit(0); - } - - const char *c = NULL; - if (g_autodoc_path.empty()) - c = argv[i]; - - fl_register_images(); - - make_main_window(); - - if (c) set_filename(c); - if (!batch_mode) { -#ifdef __APPLE__ - fl_open_callback(apple_open_cb); -#endif // __APPLE__ - Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX)); - Fl_File_Icon::load_system_icons(); - main_window->callback(exit_cb); - position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT ); - if (g_shell_config) { - g_shell_config->read(fluid_prefs, FD_STORE_USER); - g_shell_config->update_settings_dialog(); - g_shell_config->rebuild_shell_menu(); - } - g_layout_list.read(fluid_prefs, FD_STORE_USER); - main_window->show(argc,argv); - toggle_widgetbin_cb(0,0); - toggle_codeview_cb(0,0); - if (!c && openlast_button->value() && absolute_history[0][0] && g_autodoc_path.empty()) { - // Open previous file when no file specified... - open_project_file(absolute_history[0]); - } - } - undo_suspend(); - if (c && !fld::io::read_file(c,0)) { - if (batch_mode) { - fprintf(stderr,"%s : %s\n", c, strerror(errno)); - exit(1); - } - fl_message("Can't read %s: %s", c, strerror(errno)); - } - undo_resume(); - - // command line args override code and header filenames from the project file - // in batch mode only - if (batch_mode) { - if (!g_code_filename_arg.empty()) { - g_project.code_file_set = 1; - g_project.code_file_name = g_code_filename_arg; - } - if (!g_header_filename_arg.empty()) { - g_project.header_file_set = 1; - g_project.header_file_name = g_header_filename_arg; - } - } - - if (update_file) { // fluid -u - fld::io::write_file(c,0); - if (!compile_file) - exit(0); - } - - if (compile_file) { // fluid -c[s] - if (compile_strings) - write_strings_cb(0,0); - write_cb(0,0); - exit(0); - } - - // don't lock up if inconsistent command line arguments were given - if (batch_mode) - exit(0); - - set_modflag(0); - undo_clear(); -#ifndef _WIN32 - signal(SIGINT,sigint); -#endif - - // Set (but do not start) timer callback for external editor updates - ExternalCodeEditor::set_update_timer_callback(external_editor_timer); - -#ifndef NDEBUG - // check if the user wants FLUID to generate image for the user documentation - if (!g_autodoc_path.empty()) { - run_autodoc(g_autodoc_path); - set_modflag(0, 0); - exit_cb(0,0); - return 0; - } -#endif - -#ifdef _WIN32 - Fl::run(); -#else - while (!quit_flag) Fl::wait(); - if (quit_flag) exit_cb(0,0); -#endif // _WIN32 - - undo_clear(); - return (0); -} - -/// \} - diff --git a/fluid/app/project.h b/fluid/app/project.h index 3d5720330..058ce1764 100644 --- a/fluid/app/project.h +++ b/fluid/app/project.h @@ -14,91 +14,12 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_FLUID_H -#define _FLUID_FLUID_H -#include "tools/filename.h" - -#include -#include -#include +#ifndef FLUID_APP_PROJECT_H +#define FLUID_APP_PROJECT_H #include -#define BROWSERWIDTH 300 -#define BROWSERHEIGHT 500 -#define WINWIDTH 300 -#define MENUHEIGHT 25 -#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT) - -// ---- types - -class Fl_Double_Window; -class Fl_Window; -class Fl_Menu_Bar; -class Fl_Type; -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 Fl_Preferences fluid_prefs; -extern Fl_Menu_Item Main_Menu[]; -extern Fl_Menu_Bar *main_menubar; -extern Fl_Window *main_window; - -extern int show_guides; -extern int show_restricted; -extern int show_ghosted_outline; -extern int show_comments; - -extern int G_use_external_editor; -extern int G_debug; -extern char G_external_editor_command[512]; - -// File history info... -extern char absolute_history[10][FL_PATH_MAX]; -extern char relative_history[10][FL_PATH_MAX]; -extern void load_history(); -extern void update_history(const char *); - -extern Fl_Menu_Item *save_item; -extern Fl_Menu_Item *history_item; -extern Fl_Menu_Item *widgetbin_item; -extern Fl_Menu_Item *codeview_item; -extern Fl_Menu_Item *overlay_item; -extern Fl_Button *overlay_button; -extern Fl_Menu_Item *guides_item; -extern Fl_Menu_Item *restricted_item; -extern Fl_Check_Button *guides_button; - -extern int modflag; - -extern int update_file; // fluid -u -extern int compile_file; // fluid -c -extern int compile_strings; // fluic -cs -extern int batch_mode; - -extern int pasteoffset; - -extern std::string g_code_filename_arg; -extern std::string g_header_filename_arg; -extern std::string g_launch_path; - -extern std::string g_autodoc_path; - // ---- project class declaration /** @@ -167,6 +88,8 @@ public: /// If set, command line overrides source code file name in .fl file. int code_file_set; int write_mergeback_data; + /// Filename of the current .fl project file + const char *proj_filename { nullptr }; /// Hold the default extension for header files, or the entire filename if set via command line. std::string header_file_name; /// Hold the default extension for source code files, or the entire filename if set via command line. @@ -175,35 +98,6 @@ public: extern Fluid_Project g_project; -// ---- public functions - -extern int fluid_main(int argc,char **argv); - -extern bool new_project(bool user_must_confirm = true); -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 std::string &get_tmpdir(); - -// ---- public callback functions - -extern void save_cb(Fl_Widget *, void *v); -extern void save_template_cb(Fl_Widget *, void *); -extern void revert_cb(Fl_Widget *,void *); -extern void exit_cb(Fl_Widget *,void *); - -extern int write_code_files(bool dont_show_completion_dialog=false); -extern void write_strings_cb(Fl_Widget *, void *); -extern void align_widget_cb(Fl_Widget *, long); -extern void toggle_widgetbin_cb(Fl_Widget *, void *); - -extern char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0); - -inline int fd_min(int a, int b) { return (a < b ? a : b); } -inline int fd_max(int a, int b) { return (a > b ? a : b); } -inline int fd_min(int a, int b, int c) { return fd_min(a, fd_min(b, c)); } +#endif // FLUID_APP_PROJECT_H -#endif // _FLUID_FLUID_H diff --git a/fluid/app/shell_command.cxx b/fluid/app/shell_command.cxx index df71a00f5..7012de8e6 100644 --- a/fluid/app/shell_command.cxx +++ b/fluid/app/shell_command.cxx @@ -98,7 +98,9 @@ #include "app/shell_command.h" #include "app/fluid.h" -#include "io/file.h" +#include "app/project.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" #include "panels/settings_panel.h" #include @@ -618,7 +620,7 @@ void Fd_Shell_Command::write(Fl_Preferences &prefs, bool save_location) { if (flags != 0) prefs.set("flags", flags); } -void Fd_Shell_Command::read(class Fd_Project_Reader *in) { +void Fd_Shell_Command::read(class fld::io::Project_Reader *in) { const char *c = in->read_word(1); if (strcmp(c, "{")!=0) return; // expecting start of group storage = FD_STORE_PROJECT; @@ -644,7 +646,7 @@ void Fd_Shell_Command::read(class Fd_Project_Reader *in) { } } -void Fd_Shell_Command::write(class Fd_Project_Writer *out) { +void Fd_Shell_Command::write(class fld::io::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()); @@ -771,7 +773,7 @@ void Fd_Shell_Command_List::write(Fl_Preferences &prefs, Fd_Tool_Store storage) /** Read shell configuration from a project file. */ -void Fd_Shell_Command_List::read(Fd_Project_Reader *in) { +void Fd_Shell_Command_List::read(fld::io::Project_Reader *in) { const char *c = in->read_word(1); if (strcmp(c, "{")!=0) return; // expecting start of group clear(FD_STORE_PROJECT); @@ -791,7 +793,7 @@ void Fd_Shell_Command_List::read(Fd_Project_Reader *in) { /** Write shell configuration to a project file. */ -void Fd_Shell_Command_List::write(Fd_Project_Writer *out) { +void Fd_Shell_Command_List::write(fld::io::Project_Writer *out) { int n_in_project_file = 0; for (int i=0; istorage == FD_STORE_PROJECT) diff --git a/fluid/app/shell_command.h b/fluid/app/shell_command.h index b45e2f8cc..3f5508493 100644 --- a/fluid/app/shell_command.h +++ b/fluid/app/shell_command.h @@ -35,6 +35,15 @@ # include #endif +namespace fld { +namespace io { + +class Project_Reader; +class Project_Writer; + +} // namespace io +} // namespace fld + struct Fl_Menu_Item; class Fl_Widget; class Fl_Preferences; @@ -105,8 +114,8 @@ public: 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 read(class fld::io::Project_Reader*); + void write(class fld::io::Project_Writer*); void update_shell_menu(); bool is_active(); }; @@ -132,8 +141,8 @@ public: // int save(const std::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 read(class fld::io::Project_Reader*); + void write(class fld::io::Project_Writer*); void rebuild_shell_menu(); void update_settings_dialog(); diff --git a/fluid/app/undo.cxx b/fluid/app/undo.cxx index f5e5fbbac..baef9e717 100644 --- a/fluid/app/undo.cxx +++ b/fluid/app/undo.cxx @@ -17,7 +17,9 @@ #include "app/undo.h" #include "app/fluid.h" -#include "io/file.h" +#include "app/project.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" #include "nodes/Fl_Type.h" #include "nodes/Fl_Widget_Type.h" #include "widgets/Node_Browser.h" @@ -27,7 +29,7 @@ #include #include #include -#include "tools/fluid_filename.h" +#include "tools/filename.h" #include "../src/flstring.h" #if defined(_WIN32) && !defined(__CYGWIN__) @@ -94,7 +96,7 @@ void redo_cb(Fl_Widget *, void *) { widget_browser->new_list(); } int reload_panel = (the_panel && the_panel->visible()); - if (!read_file(undo_filename(undo_current + 1), 0)) { + if (!fld::io::read_file(undo_filename(undo_current + 1), 0)) { // Unable to read checkpoint file, don't redo... widget_browser->rebuild(); g_project.update_settings_dialog(); @@ -134,7 +136,7 @@ void undo_cb(Fl_Widget *, void *) { } if (undo_current == undo_last) { - write_file(undo_filename(undo_current)); + fld::io::write_file(undo_filename(undo_current)); } undo_suspend(); @@ -146,7 +148,7 @@ void undo_cb(Fl_Widget *, void *) { widget_browser->new_list(); } int reload_panel = (the_panel && the_panel->visible()); - if (!read_file(undo_filename(undo_current - 1), 0)) { + if (!fld::io::read_file(undo_filename(undo_current - 1), 0)) { // Unable to read checkpoint file, don't undo... widget_browser->rebuild(); g_project.update_settings_dialog(); @@ -213,7 +215,7 @@ void undo_checkpoint() { // Save the current UI to a checkpoint file... const char *filename = undo_filename(undo_current); - if (!write_file(filename)) { + if (!fld::io::write_file(filename)) { // Don't attempt to do undo stuff if we can't write a checkpoint file... perror(filename); return; diff --git a/fluid/io/Code_Writer.cxx b/fluid/io/Code_Writer.cxx index b77cad147..cbd6443e2 100644 --- a/fluid/io/Code_Writer.cxx +++ b/fluid/io/Code_Writer.cxx @@ -14,30 +14,21 @@ // https://www.fltk.org/bugs.php // -#include "io/code.h" +#include "io/Code_Writer.h" -#include "app/fluid.h" -#include "app/undo.h" -#include "io/file.h" -#include "nodes/Fl_Group_Type.h" +#include "app/project.h" #include "nodes/Fl_Window_Type.h" #include "nodes/Fl_Function_Type.h" -#include "tools/fluid_filename.h" -#include -#include -#include #include "../src/flstring.h" -#include -#include -#include - #include /// \defgroup cfile C Code File Operations /// \{ +using namespace fld; +using namespace fld::io; /** Return true if c can be in a C identifier. @@ -201,9 +192,9 @@ Fd_Identifier_Tree::~Fd_Identifier_Tree() { \param[in] type is the first word of the ID \param[in] name if name is set, it is appended to the ID \param[in] label else if label is set, it is appended, skipping non-keyword characters - \return buffer to a unique identifier, managed by Fd_Code_Writer, so caller must NOT free() it + \return buffer to a unique identifier, managed by Code_Writer, so caller must NOT free() it */ -const char* Fd_Code_Writer::unique_id(void* o, const char* type, const char* name, const char* label) { +const char* Code_Writer::unique_id(void* o, const char* type, const char* name, const char* label) { char buffer[128]; char* q = buffer; char* q_end = q + 128 - 8 - 1; // room for hex number and NUL @@ -253,7 +244,7 @@ const char* Fd_Code_Writer::unique_id(void* o, const char* type, const char* nam \param[in] set generate this indent depth \return pointer to a static string */ -const char *Fd_Code_Writer::indent(int set) { +const char *Code_Writer::indent(int set) { static const char* spaces = " "; int i = set * 2; if (i>32) i = 32; @@ -265,7 +256,7 @@ const char *Fd_Code_Writer::indent(int set) { Return a C string that indents code to the current source file depth. \return pointer to a static string */ -const char *Fd_Code_Writer::indent() { +const char *Code_Writer::indent() { return indent(indentation); } @@ -275,7 +266,7 @@ const char *Fd_Code_Writer::indent() { change the `indentation` variable; offset can be negative \return pointer to a static string */ -const char *Fd_Code_Writer::indent_plus(int offset) { +const char *Code_Writer::indent_plus(int offset) { return indent(indentation+offset); } @@ -325,7 +316,7 @@ Fd_Pointer_Tree::~Fd_Pointer_Tree() { \param[in] format printf-style formatting text, followed by a vararg list \return 1 if the text was written to the file, 0 if it was previously written. */ -int Fd_Code_Writer::write_h_once(const char *format, ...) { +int Code_Writer::write_h_once(const char *format, ...) { va_list args; char buf[1024]; va_start(args, format); @@ -349,7 +340,7 @@ int Fd_Code_Writer::write_h_once(const char *format, ...) { \param[in] format printf-style formatting text, followed by a vararg list \return 1 if the text was written to the file, 0 if it was previously written. */ -int Fd_Code_Writer::write_c_once(const char *format, ...) { +int Code_Writer::write_c_once(const char *format, ...) { va_list args; char buf[1024]; va_start(args, format); @@ -380,7 +371,7 @@ int Fd_Code_Writer::write_c_once(const char *format, ...) { \param[in] pp ay pointer \return true if found in the tree, false if added to the tree */ -bool Fd_Code_Writer::c_contains(void *pp) { +bool Code_Writer::c_contains(void *pp) { Fd_Pointer_Tree **p = &ptr_in_code; while (*p) { if ((*p)->ptr == pp) return true; @@ -408,7 +399,7 @@ bool Fd_Code_Writer::c_contains(void *pp) { \see f.write_cstring(const char*) */ -void Fd_Code_Writer::write_cstring(const char *s, int length) { +void Code_Writer::write_cstring(const char *s, int length) { const char *next_line = "\"\n\""; if (varused_test) { varused = 1; @@ -489,7 +480,7 @@ void Fd_Code_Writer::write_cstring(const char *s, int length) { \param[in] s write this string \see f.write_cstring(const char*, int) */ -void Fd_Code_Writer::write_cstring(const char *s) { +void Code_Writer::write_cstring(const char *s) { write_cstring(s, (int)strlen(s)); } @@ -501,7 +492,7 @@ void Fd_Code_Writer::write_cstring(const char *s) { \param[in] s a block of binary data, interpreted as unsigned bytes \param[in] length size of the block in bytes */ -void Fd_Code_Writer::write_cdata(const char *s, int length) { +void Code_Writer::write_cdata(const char *s, int length) { if (varused_test) { varused = 1; return; @@ -539,7 +530,7 @@ void Fd_Code_Writer::write_cdata(const char *s, int length) { \param[in] format printf-style formatting text \param[in] args list of arguments */ -void Fd_Code_Writer::vwrite_c(const char* format, va_list args) { +void Code_Writer::vwrite_c(const char* format, va_list args) { if (varused_test) { varused = 1; return; @@ -551,7 +542,7 @@ void Fd_Code_Writer::vwrite_c(const char* format, va_list args) { Print a formatted line to the source file. \param[in] format printf-style formatting text, followed by a vararg list */ -void Fd_Code_Writer::write_c(const char* format,...) { +void Code_Writer::write_c(const char* format,...) { va_list args; va_start(args, format); vwrite_c(format, args); @@ -566,7 +557,7 @@ void Fd_Code_Writer::write_c(const char* format,...) { \param[in] c line of code \param[in] com optional commentary */ -void Fd_Code_Writer::write_cc(const char *indent, int n, const char *c, const char *com) { +void Code_Writer::write_cc(const char *indent, int n, const char *c, const char *com) { write_c("%s%.*s", indent, n, c); char cc = c[n-1]; if (cc!='}' && cc!=';') @@ -580,7 +571,7 @@ void Fd_Code_Writer::write_cc(const char *indent, int n, const char *c, const ch Print a formatted line to the header file. \param[in] format printf-style formatting text, followed by a vararg list */ -void Fd_Code_Writer::write_h(const char* format,...) { +void Code_Writer::write_h(const char* format,...) { if (varused_test) return; va_list args; va_start(args, format); @@ -596,7 +587,7 @@ void Fd_Code_Writer::write_h(const char* format,...) { \param[in] c line of code \param[in] com optional commentary */ -void Fd_Code_Writer::write_hc(const char *indent, int n, const char* c, const char *com) { +void Code_Writer::write_hc(const char *indent, int n, const char* c, const char *com) { write_h("%s%.*s", indent, n, c); char cc = c[n-1]; if (cc!='}' && cc!=';') @@ -613,7 +604,7 @@ void Fd_Code_Writer::write_hc(const char *indent, int n, const char* c, const ch \param[in] inTrailWith append this character if the last line did not end with a newline, usually 0 or newline. */ -void Fd_Code_Writer::write_c_indented(const char *textlines, int inIndent, char inTrailWith) { +void Code_Writer::write_c_indented(const char *textlines, int inIndent, char inTrailWith) { if (textlines) { indentation += inIndent; for (;;) { @@ -686,7 +677,7 @@ bool is_comment_before_class_member(Fl_Type *q) { \param[in] p write this type and all its children \return pointer to the next sibling */ -Fl_Type* Fd_Code_Writer::write_static(Fl_Type* p) { +Fl_Type* Code_Writer::write_static(Fl_Type* p) { if (write_codeview) p->header_static_start = (int)ftell(header_file); if (write_codeview) p->code_static_start = (int)ftell(code_file); p->write_static(*this); @@ -708,7 +699,7 @@ Fl_Type* Fd_Code_Writer::write_static(Fl_Type* p) { \param[in] p write this type and all its children \return pointer to the next sibling */ -Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) { +Fl_Type* Code_Writer::write_code(Fl_Type* p) { // write all code that comes before the children code // (but don't write the last comment until the very end) if (!(p==Fl_Type::last && p->is_a(ID_Comment))) { @@ -777,7 +768,7 @@ Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) { \param[in] t filename of the header file \return 0 if the operation failed, 1 if it was successful */ -int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { +int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { write_codeview = to_codeview; delete id_root; id_root = 0; indentation = 0; @@ -939,7 +930,7 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { This avoids repeating these words if the mode is already set. \param[in] state 0 for private, 1 for public, 2 for protected */ -void Fd_Code_Writer::write_public(int state) { +void Code_Writer::write_public(int state) { if (!current_class && !current_widget_class) return; if (current_class && current_class->write_public_state == state) return; if (current_widget_class && current_widget_class->write_public_state == state) return; @@ -955,7 +946,7 @@ void Fd_Code_Writer::write_public(int state) { /** Create and initialize a new C++ source code writer. */ -Fd_Code_Writer::Fd_Code_Writer() +Code_Writer::Code_Writer() : code_file(NULL), header_file(NULL), id_root(NULL), @@ -977,7 +968,7 @@ Fd_Code_Writer::Fd_Code_Writer() /** Release all resources. */ -Fd_Code_Writer::~Fd_Code_Writer() +Code_Writer::~Code_Writer() { delete id_root; delete ptr_in_code; @@ -994,7 +985,7 @@ Fd_Code_Writer::~Fd_Code_Writer() \param[in] type FD_TAG_GENERIC, FD_TAG_CODE, FD_TAG_MENU_CALLBACK, or FD_TAG_WIDGET_CALLBACK \param[in] uid the unique id of the current type */ -void Fd_Code_Writer::tag(int type, unsigned short uid) { +void Code_Writer::tag(int type, unsigned short uid) { if (g_project.write_mergeback_data) fprintf(code_file, "//~fl~%d~%04x~%08x~~\n", type, (int)uid, (unsigned int)block_crc_); block_crc_ = crc32(0, NULL, 0); @@ -1011,7 +1002,7 @@ void Fd_Code_Writer::tag(int type, unsigned short uid) { if we are the start of a line, used to find leading whitespace \return the new CRC */ -unsigned long Fd_Code_Writer::block_crc(const void *data, int n, unsigned long in_crc, bool *inout_line_start) { +unsigned long Code_Writer::block_crc(const void *data, int n, unsigned long in_crc, bool *inout_line_start) { if (!data) return 0; if (n==-1) n = (int)strlen((const char*)data); bool line_start = true; @@ -1038,7 +1029,7 @@ unsigned long Fd_Code_Writer::block_crc(const void *data, int n, unsigned long i \param[in] data a pointer to the data block \param[in] n the size of the data in bytes, or -1 to use strlen() */ -void Fd_Code_Writer::crc_add(const void *data, int n) { +void Code_Writer::crc_add(const void *data, int n) { block_crc_ = block_crc(data, n, block_crc_, &block_line_start_); } @@ -1047,7 +1038,7 @@ void Fd_Code_Writer::crc_add(const void *data, int n) { \param[in] format printf style formatting string \return see fprintf(FILE *, *const char*, ...) */ -int Fd_Code_Writer::crc_printf(const char *format, ...) { +int Code_Writer::crc_printf(const char *format, ...) { va_list args; va_start(args, format); int ret = crc_vprintf(format, args); @@ -1061,7 +1052,7 @@ int Fd_Code_Writer::crc_printf(const char *format, ...) { \param[in] args list of arguments \return see fprintf(FILE *, *const char*, ...) */ -int Fd_Code_Writer::crc_vprintf(const char *format, va_list args) { +int Code_Writer::crc_vprintf(const char *format, va_list args) { if (g_project.write_mergeback_data) { int n = vsnprintf(block_buffer_, block_buffer_size_, format, args); if (n > block_buffer_size_) { @@ -1082,7 +1073,7 @@ int Fd_Code_Writer::crc_vprintf(const char *format, va_list args) { \param[in] text any text, no requirements to end in a newline or such \return see fputs(const char*, FILE*) */ -int Fd_Code_Writer::crc_puts(const char *text) { +int Code_Writer::crc_puts(const char *text) { if (g_project.write_mergeback_data) { crc_add(text); } @@ -1091,11 +1082,11 @@ int Fd_Code_Writer::crc_puts(const char *text) { /** Write a single ASCII character to the code file. If MergeBack is enabled, the CRC calculation is continued. - \note to write UTF-8 characters, use Fd_Code_Writer::crc_puts(const char *text) + \note to write UTF-8 characters, use Code_Writer::crc_puts(const char *text) \param[in] c any character between 0 and 127 inclusive \return see fputc(int, FILE*) */ -int Fd_Code_Writer::crc_putc(int c) { +int Code_Writer::crc_putc(int c) { if (g_project.write_mergeback_data) { uchar uc = (uchar)c; crc_add(&uc, 1); diff --git a/fluid/io/Code_Writer.h b/fluid/io/Code_Writer.h index 758e7bf45..b4a6518b4 100644 --- a/fluid/io/Code_Writer.h +++ b/fluid/io/Code_Writer.h @@ -14,8 +14,8 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_CODE_H -#define _FLUID_CODE_H +#ifndef FLUID_IO_CODE_WRITER_H +#define FLUID_IO_CODE_WRITER_H #include @@ -31,7 +31,10 @@ struct Fd_Pointer_Tree; int is_id(char c); int write_strings(const std::string &filename); -class Fd_Code_Writer +namespace fld { +namespace io { + +class Code_Writer { protected: /// file pointer for the C++ code file @@ -77,8 +80,8 @@ public: int varused; public: - Fd_Code_Writer(); - ~Fd_Code_Writer(); + Code_Writer(); + ~Code_Writer(); const char* unique_id(void* o, const char*, const char*, const char*); /// Increment source code indentation level. void indent_more() { indentation++; } @@ -109,4 +112,7 @@ public: static unsigned long block_crc(const void *data, int n=-1, unsigned long in_crc=0, bool *inout_line_start=NULL); }; -#endif // _FLUID_CODE_H +} // namespace io +} // namespace fld + +#endif // FLUID_IO_CODE_WRITER_H diff --git a/fluid/io/Project_Reader.cxx b/fluid/io/Project_Reader.cxx index ba1afeb1b..ff88238ba 100644 --- a/fluid/io/Project_Reader.cxx +++ b/fluid/io/Project_Reader.cxx @@ -19,37 +19,33 @@ // https://www.fltk.org/bugs.php // -#include "io/file.h" +#include "io/Project_Reader.h" #include "app/fluid.h" +#include "app/project.h" #include "app/shell_command.h" #include "app/undo.h" -#include "io/code.h" +#include "app/Fd_Snap_Action.h" #include "nodes/factory.h" #include "nodes/Fl_Function_Type.h" #include "nodes/Fl_Widget_Type.h" #include "nodes/Fl_Grid_Type.h" #include "nodes/Fl_Window_Type.h" -#include "panels/settings_panel.h" #include "widgets/Node_Browser.h" -#include -#include -#include +#include #include -#include "../src/flstring.h" - -#include -#include -#include /// \defgroup flfile .fl Project File Operations /// \{ +using namespace fld; +using namespace fld::io; + // This file contains code to read and write .fl files. /// If set, we read an old fdesign file and widget y coordinates need to be flipped. -int fdesign_flip = 0; +int fld::io::fdesign_flip = 0; /** \brief Read a .fl project file. @@ -61,26 +57,12 @@ int fdesign_flip = 0; \param[in] strategy add new nodes after current or as last child \return 0 if the operation failed, 1 if it succeeded */ -int read_file(const char *filename, int merge, Strategy strategy) { - Fd_Project_Reader f; +int fld::io::read_file(const char *filename, int merge, Strategy strategy) { + Project_Reader f; strategy.source(Strategy::FROM_FILE); return f.read_project(filename, merge, strategy); } -/** \brief Write an .fl design description file. - - The .fl file format is documented in `fluid/README_fl.txt`. - - \param[in] filename create this file, and if it exists, overwrite it - \param[in] selected_only write only the selected nodes in the widget_tree. This - is used to implement copy and paste. - \return 0 if the operation failed, 1 if it succeeded - */ -int write_file(const char *filename, int selected_only, bool to_codeview) { - Fd_Project_Writer out; - return out.write_project(filename, selected_only, to_codeview); -} - /** Convert a single ASCII char, assumed to be a hex digit, into its decimal value. \param[in] x ASCII character @@ -94,14 +76,14 @@ static int hexdigit(int x) { return 20; } -// ---- Fd_Project_Reader ---------------------------------------------- MARK: - +// ---- Project_Reader ---------------------------------------------- MARK: - /** A simple growing buffer. Oh how I wish sometimes we would upgrade to modern C++. \param[in] length minimum length in bytes */ -void Fd_Project_Reader::expand_buffer(int length) { +void Project_Reader::expand_buffer(int length) { if (length >= buflen) { if (!buflen) { buflen = length+1; @@ -115,7 +97,7 @@ void Fd_Project_Reader::expand_buffer(int length) { } /** \brief Construct local project reader. */ -Fd_Project_Reader::Fd_Project_Reader() +Project_Reader::Project_Reader() : fin(NULL), lineno(0), fname(NULL), @@ -126,7 +108,7 @@ Fd_Project_Reader::Fd_Project_Reader() } /** \brief Release project reader resources. */ -Fd_Project_Reader::~Fd_Project_Reader() +Project_Reader::~Project_Reader() { // fname is not copied, so do not free it if (buffer) @@ -138,7 +120,7 @@ Fd_Project_Reader::~Fd_Project_Reader() \param[in] s filename, if NULL, read from stdin instead \return 0 if the operation failed, 1 if it succeeded */ -int Fd_Project_Reader::open_read(const char *s) { +int Project_Reader::open_read(const char *s) { lineno = 1; if (!s) { fin = stdin; @@ -157,7 +139,7 @@ int Fd_Project_Reader::open_read(const char *s) { Close the .fl file. \return 0 if the operation failed, 1 if it succeeded */ -int Fd_Project_Reader::close_read() { +int Project_Reader::close_read() { if (fin != stdin) { int x = fclose(fin); fin = 0; @@ -170,7 +152,7 @@ int Fd_Project_Reader::close_read() { Return the name part of the current filename and path. \return a pointer into a string that is not owned by this class */ -const char *Fd_Project_Reader::filename_name() { +const char *Project_Reader::filename_name() { return fl_filename_name(fname); } @@ -180,7 +162,7 @@ const char *Fd_Project_Reader::filename_name() { values, and \\o### octal values. \return a character in the ASCII range */ -int Fd_Project_Reader::read_quoted() { // read whatever character is after a \ . +int Project_Reader::read_quoted() { // read whatever character is after a \ . int c,d,x; switch(c = nextchar()) { case '\n': lineno++; return -1; @@ -225,7 +207,7 @@ int Fd_Project_Reader::read_quoted() { // read whatever character is after a previous call, and there is no need to waste time searching for them. \return the last type that was created */ -Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) { +Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) { Fl_Type::current = p; Fl_Type *last_child_read = NULL; Fl_Type *t = NULL; @@ -432,7 +414,7 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate \param[in] strategy add new nodes after current or as last child \return 0 if the operation failed, 1 if it succeeded */ -int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy) { +int Project_Reader::read_project(const char *filename, int merge, Strategy strategy) { Fl_Type *o; undo_suspend(); read_version = 0.0; @@ -482,7 +464,7 @@ int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy st operations. \param[in] format printf style format string, followed by an argument list */ -void Fd_Project_Reader::read_error(const char *format, ...) { +void Project_Reader::read_error(const char *format, ...) { va_list args; va_start(args, format); if (!fin) { // FIXME: this line suppresses any error messages in interactive mode @@ -515,7 +497,7 @@ void Fd_Project_Reader::read_error(const char *format, ...) { overwrite this buffer. If wantbrace is not set, but we read a leading '{', the returned string will be stripped of its leading and trailing braces. */ -const char *Fd_Project_Reader::read_word(int wantbrace) { +const char *Project_Reader::read_word(int wantbrace) { int x; // skip all the whitespace before it: @@ -585,7 +567,7 @@ const char *Fd_Project_Reader::read_word(int wantbrace) { /** Read a word and interpret it as an integer value. \return integer value, or 0 if the word is not an integer */ -int Fd_Project_Reader::read_int() { +int Project_Reader::read_int() { const char *word = read_word(); if (word) { return atoi(word); @@ -601,7 +583,7 @@ int Fd_Project_Reader::read_int() { \param[out] value string \return 0 if end of file, else 1 */ -int Fd_Project_Reader::read_fdesign_line(const char*& name, const char*& value) { +int Project_Reader::read_fdesign_line(const char*& name, const char*& value) { int length = 0; int x; // find a colon: @@ -727,7 +709,7 @@ static void forms_end(Fl_Group *g, int flip) { FLTK widgets. \see http://xforms-toolkit.org */ -void Fd_Project_Reader::read_fdesign() { +void Project_Reader::read_fdesign() { int fdesign_magic = atoi(read_word()); fdesign_flip = (fdesign_magic < 13000); Fl_Widget_Type *window = 0; @@ -782,202 +764,4 @@ void Fd_Project_Reader::read_fdesign() { } } -// ---- Fd_Project_Writer ---------------------------------------------- MARK: - - -/** \brief Construct local project writer. */ -Fd_Project_Writer::Fd_Project_Writer() -: fout(NULL), - needspace(0), - write_codeview_(false) -{ -} - -/** \brief Release project writer resources. */ -Fd_Project_Writer::~Fd_Project_Writer() -{ -} - -/** - Open the .fl design file for writing. - If the filename is NULL, associate stdout instead. - \param[in] s the filename or NULL for stdout - \return 1 if successful. 0 if the operation failed - */ -int Fd_Project_Writer::open_write(const char *s) { - if (!s) { - fout = stdout; - } else { - FILE *f = fl_fopen(s,"wb"); - if (!f) return 0; - fout = f; - } - return 1; -} - -/** - Close the .fl design file. - Don't close, if data was sent to stdout. - \return 1 if succeeded, 0 if fclose failed - */ -int Fd_Project_Writer::close_write() { - if (fout != stdout) { - int x = fclose(fout); - fout = stdout; - return x >= 0; - } - return 1; -} - -/** \brief Write an .fl design description file. - \param[in] filename create this file, and if it exists, overwrite it - \param[in] selected_only write only the selected nodes in the widget_tree. This - is used to implement copy and paste. - \param[in] sv if set, this file will be used by codeview - \return 0 if the operation failed, 1 if it succeeded - */ -int Fd_Project_Writer::write_project(const char *filename, int selected_only, bool sv) { - write_codeview_ = sv; - undo_suspend(); - if (!open_write(filename)) { - undo_resume(); - return 0; - } - write_string("# data file for the Fltk User Interface Designer (fluid)\n" - "version %.4f",FL_VERSION); - if(!g_project.include_H_from_C) - write_string("\ndo_not_include_H_from_C"); - if(g_project.use_FL_COMMAND) - write_string("\nuse_FL_COMMAND"); - if (g_project.utf8_in_src) - write_string("\nutf8_in_src"); - if (g_project.avoid_early_includes) - write_string("\navoid_early_includes"); - if (g_project.i18n_type) { - write_string("\ni18n_type %d", g_project.i18n_type); - switch (g_project.i18n_type) { - case FD_I18N_NONE: - break; - case FD_I18N_GNU : /* GNU gettext */ - write_string("\ni18n_include"); write_word(g_project.i18n_gnu_include.c_str()); - write_string("\ni18n_conditional"); write_word(g_project.i18n_gnu_conditional.c_str()); - write_string("\ni18n_gnu_function"); write_word(g_project.i18n_gnu_function.c_str()); - write_string("\ni18n_gnu_static_function"); write_word(g_project.i18n_gnu_static_function.c_str()); - break; - case FD_I18N_POSIX : /* POSIX catgets */ - write_string("\ni18n_include"); write_word(g_project.i18n_pos_include.c_str()); - write_string("\ni18n_conditional"); write_word(g_project.i18n_pos_conditional.c_str()); - if (!g_project.i18n_pos_file.empty()) { - write_string("\ni18n_pos_file"); - write_word(g_project.i18n_pos_file.c_str()); - } - write_string("\ni18n_pos_set"); write_word(g_project.i18n_pos_set.c_str()); - break; - } - } - - if (!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 (g_shell_config) - g_shell_config->write(this); - if (g_project.write_mergeback_data) - write_string("\nmergeback %d", g_project.write_mergeback_data); - } - - for (Fl_Type *p = Fl_Type::first; p;) { - if (!selected_only || p->selected) { - p->write(*this); - write_string("\n"); - int q = p->level; - for (p = p->next; p && p->level > q; p = p->next) {/*empty*/} - } else { - p = p->next; - } - } - int ret = close_write(); - undo_resume(); - return ret; -} - -/** - Write a string to the .fl file, quoting characters if necessary. - \param[in] w NUL terminated text - */ -void Fd_Project_Writer::write_word(const char *w) { - if (needspace) putc(' ', fout); - needspace = 1; - if (!w || !*w) {fprintf(fout,"{}"); return;} - const char *p; - // see if it is a single word: - for (p = w; is_id(*p); p++) ; - if (!*p) {fprintf(fout,"%s",w); return;} - // see if there are matching braces: - int n = 0; - for (p = w; *p; p++) { - if (*p == '{') n++; - else if (*p == '}') {n--; if (n<0) break;} - } - int mismatched = (n != 0); - // write out brace-quoted string: - putc('{', fout); - for (; *w; w++) { - switch (*w) { - case '{': - case '}': - if (!mismatched) break; - case '\\': - case '#': - putc('\\',fout); - break; - } - putc(*w,fout); - } - putc('}', fout); -} - -/** - Write an arbitrary formatted word to the .fl file, or a comment, etc . - If needspace is set, then one space is written before the string - unless the format starts with a newline character \\n. - \param[in] format printf style formatting string followed by a list of arguments - */ -void Fd_Project_Writer::write_string(const char *format, ...) { - va_list args; - va_start(args, format); - if (needspace && *format != '\n') fputc(' ',fout); - vfprintf(fout, format, args); - va_end(args); - needspace = !isspace(format[strlen(format)-1] & 255); -} - -/** - Start a new line in the .fl file and indent it for a given nesting level. - \param[in] n indent level - */ -void Fd_Project_Writer::write_indent(int n) { - fputc('\n',fout); - while (n--) {fputc(' ',fout); fputc(' ',fout);} - needspace = 0; -} - -/** - Write a '{' to the .fl file at the given indenting level. - */ -void Fd_Project_Writer::write_open() { - if (needspace) fputc(' ',fout); - fputc('{',fout); - needspace = 0; -} - -/** - Write a '}' to the .fl file at the given indenting level. - \param[in] n indent level - */ -void Fd_Project_Writer::write_close(int n) { - if (needspace) write_indent(n); - fputc('}',fout); - needspace = 1; -} - /// \} diff --git a/fluid/io/Project_Reader.h b/fluid/io/Project_Reader.h index 470cc1a7b..20928d25f 100644 --- a/fluid/io/Project_Reader.h +++ b/fluid/io/Project_Reader.h @@ -14,21 +14,26 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_FILE_H -#define _FLUID_FILE_H +#ifndef FLUID_IO_PROJECT_READER_H +#define FLUID_IO_PROJECT_READER_H #include "nodes/Fl_Type.h" #include +#include + + class Fl_Type; +namespace fld { +namespace io { + extern int fdesign_flip; int read_file(const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); -int write_file(const char *, int selected_only = 0, bool to_codeview = false); -class Fd_Project_Reader +class Project_Reader { protected: /// Project input file @@ -51,8 +56,8 @@ public: double read_version; public: - Fd_Project_Reader(); - ~Fd_Project_Reader(); + Project_Reader(); + ~Project_Reader(); int open_read(const char *s); int close_read(); const char *filename_name(); @@ -66,29 +71,7 @@ public: void read_fdesign(); }; -class Fd_Project_Writer -{ -protected: - // Project output file, always opened in "wb" mode - FILE *fout; - /// If set, one space is written before text unless the format starts with a newline character - int needspace; - /// Set if this file will be used in the codeview dialog - bool write_codeview_; - -public: - Fd_Project_Writer(); - ~Fd_Project_Writer(); - int open_write(const char *s); - int close_write(); - int write_project(const char *filename, int selected_only, bool codeview); - void write_word(const char *); - void write_string(const char *,...) __fl_attr((__format__ (__printf__, 2, 3))); - void write_indent(int n); - void write_open(); - void write_close(int n); - FILE *file() const { return fout; } - bool write_codeview() const { return write_codeview_; } -}; +} // namespace io +} // namespace fld -#endif // _FLUID_FILE_H +#endif // FLUID_IO_PROJECT_READER_H diff --git a/fluid/io/Project_Writer.cxx b/fluid/io/Project_Writer.cxx index ba1afeb1b..26af62f37 100644 --- a/fluid/io/Project_Writer.cxx +++ b/fluid/io/Project_Writer.cxx @@ -19,53 +19,19 @@ // https://www.fltk.org/bugs.php // -#include "io/file.h" +#include "io/Project_Writer.h" #include "app/fluid.h" +#include "app/project.h" #include "app/shell_command.h" #include "app/undo.h" -#include "io/code.h" -#include "nodes/factory.h" -#include "nodes/Fl_Function_Type.h" -#include "nodes/Fl_Widget_Type.h" -#include "nodes/Fl_Grid_Type.h" -#include "nodes/Fl_Window_Type.h" -#include "panels/settings_panel.h" -#include "widgets/Node_Browser.h" - -#include -#include -#include -#include -#include "../src/flstring.h" - -#include -#include -#include +#include "app/Fd_Snap_Action.h" /// \defgroup flfile .fl Project File Operations /// \{ -// This file contains code to read and write .fl files. - -/// If set, we read an old fdesign file and widget y coordinates need to be flipped. -int fdesign_flip = 0; - -/** \brief Read a .fl project file. - - The .fl file format is documented in `fluid/README_fl.txt`. - - \param[in] filename read this file - \param[in] merge if this is set, merge the file into an existing project - at Fl_Type::current - \param[in] strategy add new nodes after current or as last child - \return 0 if the operation failed, 1 if it succeeded - */ -int read_file(const char *filename, int merge, Strategy strategy) { - Fd_Project_Reader f; - strategy.source(Strategy::FROM_FILE); - return f.read_project(filename, merge, strategy); -} +using namespace fld; +using namespace fld::io; /** \brief Write an .fl design description file. @@ -76,716 +42,15 @@ int read_file(const char *filename, int merge, Strategy strategy) { is used to implement copy and paste. \return 0 if the operation failed, 1 if it succeeded */ -int write_file(const char *filename, int selected_only, bool to_codeview) { - Fd_Project_Writer out; +int fld::io::write_file(const char *filename, int selected_only, bool to_codeview) { + Project_Writer out; return out.write_project(filename, selected_only, to_codeview); } -/** - Convert a single ASCII char, assumed to be a hex digit, into its decimal value. - \param[in] x ASCII character - \return decimal value or 20 if character is not a valid hex digit (0..9,a..f,A..F) - */ -static int hexdigit(int x) { - if ((x < 0) || (x > 127)) return 20; - if (isdigit(x)) return x-'0'; - if (isupper(x)) return x-'A'+10; - if (islower(x)) return x-'a'+10; - return 20; -} - -// ---- Fd_Project_Reader ---------------------------------------------- MARK: - - -/** - A simple growing buffer. - Oh how I wish sometimes we would upgrade to modern C++. - \param[in] length minimum length in bytes - */ -void Fd_Project_Reader::expand_buffer(int length) { - if (length >= buflen) { - if (!buflen) { - buflen = length+1; - buffer = (char*)malloc(buflen); - } else { - buflen = 2*buflen; - if (length >= buflen) buflen = length+1; - buffer = (char *)realloc((void *)buffer,buflen); - } - } -} - -/** \brief Construct local project reader. */ -Fd_Project_Reader::Fd_Project_Reader() -: fin(NULL), - lineno(0), - fname(NULL), - buffer(NULL), - buflen(0), - read_version(0.0) -{ -} - -/** \brief Release project reader resources. */ -Fd_Project_Reader::~Fd_Project_Reader() -{ - // fname is not copied, so do not free it - if (buffer) - ::free(buffer); -} - -/** - Open an .fl file for reading. - \param[in] s filename, if NULL, read from stdin instead - \return 0 if the operation failed, 1 if it succeeded - */ -int Fd_Project_Reader::open_read(const char *s) { - lineno = 1; - if (!s) { - fin = stdin; - fname = "stdin"; - } else { - FILE *f = fl_fopen(s, "rb"); - if (!f) - return 0; - fin = f; - fname = s; - } - return 1; -} - -/** - Close the .fl file. - \return 0 if the operation failed, 1 if it succeeded - */ -int Fd_Project_Reader::close_read() { - if (fin != stdin) { - int x = fclose(fin); - fin = 0; - return x >= 0; - } - return 1; -} - -/** - Return the name part of the current filename and path. - \return a pointer into a string that is not owned by this class - */ -const char *Fd_Project_Reader::filename_name() { - return fl_filename_name(fname); -} - -/** - Convert an ASCII sequence from the \.fl file following a previously read `\\` into a single character. - Conversion includes the common C style \\ characters like \\n, \\x## hex - values, and \\o### octal values. - \return a character in the ASCII range - */ -int Fd_Project_Reader::read_quoted() { // read whatever character is after a \ . - int c,d,x; - switch(c = nextchar()) { - case '\n': lineno++; return -1; - case 'a' : return('\a'); - case 'b' : return('\b'); - case 'f' : return('\f'); - case 'n' : return('\n'); - case 'r' : return('\r'); - case 't' : return('\t'); - case 'v' : return('\v'); - case 'x' : /* read hex */ - for (c=x=0; x<3; x++) { - int ch = nextchar(); - d = hexdigit(ch); - if (d > 15) {ungetc(ch,fin); break;} - c = (c<<4)+d; - } - break; - default: /* read octal */ - if (c<'0' || c>'7') break; - c -= '0'; - for (x=0; x<2; x++) { - int ch = nextchar(); - d = hexdigit(ch); - if (d>7) {ungetc(ch,fin); break;} - c = (c<<3)+d; - } - break; - } - return(c); -} - -/** - Recursively read child nodes in the .fl design file. - - If this is the first call, also read the global settings for this design. - - \param[in] p parent node or NULL - \param[in] merge if set, merge into existing design, else replace design - \param[in] strategy add nodes after current or as last child - \param[in] skip_options this is set if the options were already found in - a previous call, and there is no need to waste time searching for them. - \return the last type that was created - */ -Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) { - Fl_Type::current = p; - Fl_Type *last_child_read = NULL; - Fl_Type *t = NULL; - for (;;) { - const char *c = read_word(); - REUSE_C: - if (!c) { - if (p && !merge) - read_error("Missing '}'"); - break; - } - - if (!strcmp(c,"}")) { - if (!p) read_error("Unexpected '}'"); - break; - } - - // Make sure that we don't go through the list of options for child nodes - if (!skip_options) { - // this is the first word in a .fd file: - if (!strcmp(c,"Magic:")) { - read_fdesign(); - return NULL; - } - - if (!strcmp(c,"version")) { - c = read_word(); - read_version = strtod(c,0); - if (read_version<=0 || read_version>double(FL_VERSION+0.00001)) - read_error("unknown version '%s'",c); - continue; - } - - // back compatibility with Vincent Penne's original class code: - if (!p && !strcmp(c,"define_in_struct")) { - Fl_Type *t = add_new_widget_from_file("class", Strategy::FROM_FILE_AS_LAST_CHILD); - t->name(read_word()); - Fl_Type::current = p = t; - merge = 1; // stops "missing }" error - continue; - } - - if (!strcmp(c,"do_not_include_H_from_C")) { - g_project.include_H_from_C=0; - goto CONTINUE; - } - if (!strcmp(c,"use_FL_COMMAND")) { - g_project.use_FL_COMMAND=1; - goto CONTINUE; - } - if (!strcmp(c,"utf8_in_src")) { - g_project.utf8_in_src=1; - goto CONTINUE; - } - if (!strcmp(c,"avoid_early_includes")) { - g_project.avoid_early_includes=1; - goto CONTINUE; - } - if (!strcmp(c,"i18n_type")) { - g_project.i18n_type = static_cast(atoi(read_word())); - goto CONTINUE; - } - if (!strcmp(c,"i18n_gnu_function")) { - g_project.i18n_gnu_function = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_gnu_static_function")) { - g_project.i18n_gnu_static_function = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_pos_file")) { - g_project.i18n_pos_file = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_pos_set")) { - g_project.i18n_pos_set = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_include")) { - if (g_project.i18n_type == FD_I18N_GNU) - g_project.i18n_gnu_include = read_word(); - else if (g_project.i18n_type == FD_I18N_POSIX) - g_project.i18n_pos_include = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_conditional")) { - if (g_project.i18n_type == FD_I18N_GNU) - g_project.i18n_gnu_conditional = read_word(); - else if (g_project.i18n_type == FD_I18N_POSIX) - g_project.i18n_pos_conditional = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"header_name")) { - if (!g_project.header_file_set) g_project.header_file_name = read_word(); - else read_word(); - goto CONTINUE; - } - - if (!strcmp(c,"code_name")) { - if (!g_project.code_file_set) g_project.code_file_name = read_word(); - else read_word(); - goto CONTINUE; - } - - if (!strcmp(c, "snap")) { - g_layout_list.read(this); - goto CONTINUE; - } - - if (!strcmp(c, "gridx") || !strcmp(c, "gridy")) { - // grid settings are now global - read_word(); - goto CONTINUE; - } - - if (strcmp(c, "shell_commands")==0) { - if (g_shell_config) { - g_shell_config->read(this); - } else { - read_word(); - } - goto CONTINUE; - } - - if (!strcmp(c, "mergeback")) { - g_project.write_mergeback_data = read_int(); - goto CONTINUE; - } - } - t = add_new_widget_from_file(c, strategy); - if (!t) { - read_error("Unknown word \"%s\"", c); - continue; - } - last_child_read = t; - // After reading the first widget, we no longer need to look for options - skip_options = 1; - - t->name(read_word()); - - c = read_word(1); - if (strcmp(c,"{") && t->is_class()) { // - ((Fl_Class_Type*)t)->prefix(t->name()); - t->name(c); - c = read_word(1); - } - - if (strcmp(c,"{")) { - read_error("Missing property list for %s\n",t->title()); - goto REUSE_C; - } - - t->folded_ = 1; - for (;;) { - const char *cc = read_word(); - if (!cc || !strcmp(cc,"}")) break; - t->read_property(*this, cc); - } - - if (t->can_have_children()) { - c = read_word(1); - if (strcmp(c,"{")) { - read_error("Missing child list for %s\n",t->title()); - goto REUSE_C; - } - read_children(t, 0, Strategy::FROM_FILE_AS_LAST_CHILD, skip_options); - t->postprocess_read(); - // FIXME: this has no business in the file reader! - // TODO: this is called whenever something is pasted from the top level into a grid - // It makes sense to make this more universal for other widget types too. - if (merge && t && t->parent && t->parent->is_a(ID_Grid)) { - if (Fl_Window_Type::popupx != 0x7FFFFFFF) { - ((Fl_Grid_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy); - } else { - ((Fl_Grid_Type*)t->parent)->insert_child_at_next_free_cell(((Fl_Widget_Type*)t)->o); - } - } - - t->layout_widget(); - } - - if (strategy.placement() == Strategy::AS_FIRST_CHILD) { - strategy.placement(Strategy::AFTER_CURRENT); - } - if (strategy.placement() == Strategy::AFTER_CURRENT) { - Fl_Type::current = t; - } else { - Fl_Type::current = p; - } - - CONTINUE:; - } - if (merge && last_child_read && last_child_read->parent) { - last_child_read->parent->postprocess_read(); - last_child_read->parent->layout_widget(); - } - return last_child_read; -} - -/** \brief Read a .fl project file. - \param[in] filename read this file - \param[in] merge if this is set, merge the file into an existing project - at Fl_Type::current - \param[in] strategy add new nodes after current or as last child - \return 0 if the operation failed, 1 if it succeeded - */ -int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy) { - Fl_Type *o; - undo_suspend(); - read_version = 0.0; - if (!open_read(filename)) { - undo_resume(); - return 0; - } - if (merge) - deselect(); - else - g_project.reset(); - read_children(Fl_Type::current, merge, strategy); - // clear this - Fl_Type::current = 0; - // Force menu items to be rebuilt... - for (o = Fl_Type::first; o; o = o->next) { - if (o->is_a(ID_Menu_Manager_)) { - o->add_child(0,0); - } - } - for (o = Fl_Type::first; o; o = o->next) { - if (o->selected) { - Fl_Type::current = o; - break; - } - } - selection_changed(Fl_Type::current); - if (g_shell_config) { - g_shell_config->rebuild_shell_menu(); - g_shell_config->update_settings_dialog(); - } - g_layout_list.update_dialogs(); - g_project.update_settings_dialog(); - int ret = close_read(); - undo_resume(); - return ret; -} - -/** - Display an error while reading the file. - If the .fl file isn't opened for reading, pop up an FLTK dialog, otherwise - print to stdout. - \note Matt: I am not sure why it is done this way. Shouldn't this depend on \c batch_mode? - \todo Not happy about this function. Output channel should depend on `batch_mode` - as the note above already states. I want to make all file readers and writers - depend on an error handling base class that outputs a useful analysis of file - operations. - \param[in] format printf style format string, followed by an argument list - */ -void Fd_Project_Reader::read_error(const char *format, ...) { - va_list args; - va_start(args, format); - if (!fin) { // FIXME: this line suppresses any error messages in interactive mode - char buffer[1024]; // TODO: hides class member "buffer" - vsnprintf(buffer, sizeof(buffer), format, args); - fl_message("%s", buffer); - } else { - fprintf(stderr, "%s:%d: ", fname, lineno); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - } - va_end(args); -} - -/** - Return a word read from the .fl file, or NULL at the EOF. - - This will skip all comments (# to end of line), and evaluate - all \\xxx sequences and use \\ at the end of line to remove the newline. - - A word is any one of: - - a continuous string of non-space chars except { and } and # - - everything between matching {...} (unless wantbrace != 0) - - the characters '{' and '}' - - \param[in] wantbrace if set, reading a `{` as the first non-space character - will return the string `"{"`, if clear, a `{` is seen as the start of a word - \return a pointer to the internal buffer, containing a copy of the word. - Don't free the buffer! Note that most (all?) other file operations will - overwrite this buffer. If wantbrace is not set, but we read a leading '{', - the returned string will be stripped of its leading and trailing braces. - */ -const char *Fd_Project_Reader::read_word(int wantbrace) { - int x; - - // skip all the whitespace before it: - for (;;) { - x = nextchar(); - if (x < 0 && feof(fin)) { // eof - return 0; - } else if (x == '#') { // comment - do x = nextchar(); while (x >= 0 && x != '\n'); - lineno++; - continue; - } else if (x == '\n') { - lineno++; - } else if (!isspace(x & 255)) { - break; - } - } - - expand_buffer(100); - - if (x == '{' && !wantbrace) { - - // read in whatever is between braces - int length = 0; - int nesting = 0; - for (;;) { - x = nextchar(); - if (x<0) {read_error("Missing '}'"); break;} - else if (x == '#') { // embedded comment - do x = nextchar(); while (x >= 0 && x != '\n'); - lineno++; - continue; - } else if (x == '\n') lineno++; - else if (x == '\\') {x = read_quoted(); if (x<0) continue;} - else if (x == '{') nesting++; - else if (x == '}') {if (!nesting--) break;} - buffer[length++] = x; - expand_buffer(length); - } - buffer[length] = 0; - return buffer; - - } else if (x == '{' || x == '}') { - // all the punctuation is a word: - buffer[0] = x; - buffer[1] = 0; - return buffer; - - } else { - - // read in an unquoted word: - int length = 0; - for (;;) { - if (x == '\\') {x = read_quoted(); if (x<0) continue;} - else if (x<0 || isspace(x & 255) || x=='{' || x=='}' || x=='#') break; - buffer[length++] = x; - expand_buffer(length); - x = nextchar(); - } - ungetc(x, fin); - buffer[length] = 0; - return buffer; - - } -} - -/** Read a word and interpret it as an integer value. - \return integer value, or 0 if the word is not an integer - */ -int Fd_Project_Reader::read_int() { - const char *word = read_word(); - if (word) { - return atoi(word); - } else { - return 0; - } -} - -/** Read fdesign name/value pairs. - Fdesign is the file format of the XForms UI designer. It stores lists of name - and value pairs separated by a colon: `class: FL_LABELFRAME`. - \param[out] name string - \param[out] value string - \return 0 if end of file, else 1 - */ -int Fd_Project_Reader::read_fdesign_line(const char*& name, const char*& value) { - int length = 0; - int x; - // find a colon: - for (;;) { - x = nextchar(); - if (x < 0 && feof(fin)) return 0; - if (x == '\n') {length = 0; continue;} // no colon this line... - if (!isspace(x & 255)) { - buffer[length++] = x; - expand_buffer(length); - } - if (x == ':') break; - } - int valueoffset = length; - buffer[length-1] = 0; - - // skip to start of value: - for (;;) { - x = nextchar(); - if ((x < 0 && feof(fin)) || x == '\n' || !isspace(x & 255)) break; - } - - // read the value: - for (;;) { - if (x == '\\') {x = read_quoted(); if (x<0) continue;} - else if (x == '\n') break; - buffer[length++] = x; - expand_buffer(length); - x = nextchar(); - } - buffer[length] = 0; - name = buffer; - value = buffer+valueoffset; - return 1; -} - -/// Lookup table from fdesign .fd files to .fl files -static const char *class_matcher[] = { - "FL_CHECKBUTTON", "Fl_Check_Button", - "FL_ROUNDBUTTON", "Fl_Round_Button", - "FL_ROUND3DBUTTON", "Fl_Round_Button", - "FL_LIGHTBUTTON", "Fl_Light_Button", - "FL_FRAME", "Fl_Box", - "FL_LABELFRAME", "Fl_Box", - "FL_TEXT", "Fl_Box", - "FL_VALSLIDER", "Fl_Value_Slider", - "FL_MENU", "Fl_Menu_Button", - "3", "FL_BITMAP", - "1", "FL_BOX", - "71","FL_BROWSER", - "11","FL_BUTTON", - "4", "FL_CHART", - "42","FL_CHOICE", - "61","FL_CLOCK", - "25","FL_COUNTER", - "22","FL_DIAL", - "101","FL_FREE", - "31","FL_INPUT", - "12","Fl_Light_Button", - "41","FL_MENU", - "23","FL_POSITIONER", - "13","Fl_Round_Button", - "21","FL_SLIDER", - "2", "FL_BOX", // was FL_TEXT - "62","FL_TIMER", - "24","Fl_Value_Slider", - 0}; - - -/** - Finish a group of widgets and optionally transform its children's coordinates. - - Implements the same functionality as Fl_Group::forms_end() from the forms - compatibility library would have done: - - - resize the group to surround its children if the group's w() == 0 - - optionally flip the \p y coordinates of all children relative to the group's window - - Fl_Group::end() the group - - \note Copied from forms_compatibility.cxx and modified as a static fluid - function so we don't have to link to fltk_forms. - - \param[in] g the Fl_Group widget - \param[in] flip flip children's \p y coordinates if true (non-zero) - */ -static void forms_end(Fl_Group *g, int flip) { - // set the dimensions of a group to surround its contents - const int nc = g->children(); - if (nc && !g->w()) { - Fl_Widget*const* a = g->array(); - Fl_Widget* o = *a++; - int rx = o->x(); - int ry = o->y(); - int rw = rx+o->w(); - int rh = ry+o->h(); - for (int i = nc - 1; i--;) { - o = *a++; - if (o->x() < rx) rx = o->x(); - if (o->y() < ry) ry = o->y(); - if (o->x() + o->w() > rw) rw = o->x() + o->w(); - if (o->y() + o->h() > rh) rh = o->y() + o->h(); - } - g->Fl_Widget::resize(rx, ry, rw-rx, rh-ry); - } - // flip all the children's coordinate systems: - if (nc && flip) { - Fl_Widget* o = (g->as_window()) ? g : g->window(); - int Y = o->h(); - Fl_Widget*const* a = g->array(); - for (int i = nc; i--;) { - Fl_Widget* ow = *a++; - int newy = Y - ow->y() - ow->h(); - ow->Fl_Widget::resize(ow->x(), newy, ow->w(), ow->h()); - } - } - g->end(); -} - -/** - Read a XForms design file. - .fl and .fd file start with the same header. Fluid can recognize .fd XForms - Design files by a magic number. It will read them and map XForms widgets onto - FLTK widgets. - \see http://xforms-toolkit.org - */ -void Fd_Project_Reader::read_fdesign() { - int fdesign_magic = atoi(read_word()); - fdesign_flip = (fdesign_magic < 13000); - Fl_Widget_Type *window = 0; - Fl_Widget_Type *group = 0; - Fl_Widget_Type *widget = 0; - if (!Fl_Type::current) { - Fl_Type *t = add_new_widget_from_file("Function", Strategy::FROM_FILE_AS_LAST_CHILD); - t->name("create_the_forms()"); - Fl_Type::current = t; - } - for (;;) { - const char *name; - const char *value; - if (!read_fdesign_line(name, value)) break; - - if (!strcmp(name,"Name")) { - - window = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Window", Strategy::FROM_FILE_AS_LAST_CHILD); - window->name(value); - window->label(value); - Fl_Type::current = widget = window; - - } else if (!strcmp(name,"class")) { - - if (!strcmp(value,"FL_BEGIN_GROUP")) { - group = widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Group", Strategy::FROM_FILE_AS_LAST_CHILD); - Fl_Type::current = group; - } else if (!strcmp(value,"FL_END_GROUP")) { - if (group) { - Fl_Group* g = (Fl_Group*)(group->o); - g->begin(); - forms_end(g, fdesign_flip); - Fl_Group::current(0); - } - group = widget = 0; - Fl_Type::current = window; - } else { - for (int i = 0; class_matcher[i]; i += 2) - if (!strcmp(value,class_matcher[i])) { - value = class_matcher[i+1]; break;} - widget = (Fl_Widget_Type*)add_new_widget_from_file(value, Strategy::FROM_FILE_AS_LAST_CHILD); - if (!widget) { - printf("class %s not found, using Fl_Button\n", value); - widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Button", Strategy::FROM_FILE_AS_LAST_CHILD); - } - } - - } else if (widget) { - if (!widget->read_fdesign(name, value)) - printf("Ignoring \"%s: %s\"\n", name, value); - } - } -} - -// ---- Fd_Project_Writer ---------------------------------------------- MARK: - +// ---- Project_Writer ---------------------------------------------- MARK: - /** \brief Construct local project writer. */ -Fd_Project_Writer::Fd_Project_Writer() +Project_Writer::Project_Writer() : fout(NULL), needspace(0), write_codeview_(false) @@ -793,7 +58,7 @@ Fd_Project_Writer::Fd_Project_Writer() } /** \brief Release project writer resources. */ -Fd_Project_Writer::~Fd_Project_Writer() +Project_Writer::~Project_Writer() { } @@ -803,7 +68,7 @@ Fd_Project_Writer::~Fd_Project_Writer() \param[in] s the filename or NULL for stdout \return 1 if successful. 0 if the operation failed */ -int Fd_Project_Writer::open_write(const char *s) { +int Project_Writer::open_write(const char *s) { if (!s) { fout = stdout; } else { @@ -819,7 +84,7 @@ int Fd_Project_Writer::open_write(const char *s) { Don't close, if data was sent to stdout. \return 1 if succeeded, 0 if fclose failed */ -int Fd_Project_Writer::close_write() { +int Project_Writer::close_write() { if (fout != stdout) { int x = fclose(fout); fout = stdout; @@ -835,7 +100,7 @@ int Fd_Project_Writer::close_write() { \param[in] sv if set, this file will be used by codeview \return 0 if the operation failed, 1 if it succeeded */ -int Fd_Project_Writer::write_project(const char *filename, int selected_only, bool sv) { +int Project_Writer::write_project(const char *filename, int selected_only, bool sv) { write_codeview_ = sv; undo_suspend(); if (!open_write(filename)) { @@ -904,7 +169,7 @@ int Fd_Project_Writer::write_project(const char *filename, int selected_only, bo Write a string to the .fl file, quoting characters if necessary. \param[in] w NUL terminated text */ -void Fd_Project_Writer::write_word(const char *w) { +void Project_Writer::write_word(const char *w) { if (needspace) putc(' ', fout); needspace = 1; if (!w || !*w) {fprintf(fout,"{}"); return;} @@ -942,7 +207,7 @@ void Fd_Project_Writer::write_word(const char *w) { unless the format starts with a newline character \\n. \param[in] format printf style formatting string followed by a list of arguments */ -void Fd_Project_Writer::write_string(const char *format, ...) { +void Project_Writer::write_string(const char *format, ...) { va_list args; va_start(args, format); if (needspace && *format != '\n') fputc(' ',fout); @@ -955,7 +220,7 @@ void Fd_Project_Writer::write_string(const char *format, ...) { Start a new line in the .fl file and indent it for a given nesting level. \param[in] n indent level */ -void Fd_Project_Writer::write_indent(int n) { +void Project_Writer::write_indent(int n) { fputc('\n',fout); while (n--) {fputc(' ',fout); fputc(' ',fout);} needspace = 0; @@ -964,7 +229,7 @@ void Fd_Project_Writer::write_indent(int n) { /** Write a '{' to the .fl file at the given indenting level. */ -void Fd_Project_Writer::write_open() { +void Project_Writer::write_open() { if (needspace) fputc(' ',fout); fputc('{',fout); needspace = 0; @@ -974,7 +239,7 @@ void Fd_Project_Writer::write_open() { Write a '}' to the .fl file at the given indenting level. \param[in] n indent level */ -void Fd_Project_Writer::write_close(int n) { +void Project_Writer::write_close(int n) { if (needspace) write_indent(n); fputc('}',fout); needspace = 1; diff --git a/fluid/io/Project_Writer.h b/fluid/io/Project_Writer.h index 470cc1a7b..c6e50ca7c 100644 --- a/fluid/io/Project_Writer.h +++ b/fluid/io/Project_Writer.h @@ -14,59 +14,21 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_FILE_H -#define _FLUID_FILE_H - -#include "nodes/Fl_Type.h" +#ifndef FLUID_IO_PROJECT_WRITER_H +#define FLUID_IO_PROJECT_WRITER_H #include +#include + class Fl_Type; -extern int fdesign_flip; +namespace fld { +namespace io { -int read_file(const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); int write_file(const char *, int selected_only = 0, bool to_codeview = false); -class Fd_Project_Reader -{ -protected: - /// Project input file - FILE *fin; - /// Number of most recently read line - int lineno; - /// Pointer to the file path and name (not copied!) - const char *fname; - /// Expanding buffer to store the most recently read word - char *buffer; - /// Exact size of the expanding buffer in bytes - int buflen; - - void expand_buffer(int length); - - int nextchar() { for (;;) { int ret = fgetc(fin); if (ret!='\r') return ret; } } - -public: - /// Holds the file version number after reading the "version" tag - double read_version; - -public: - Fd_Project_Reader(); - ~Fd_Project_Reader(); - int open_read(const char *s); - int close_read(); - const char *filename_name(); - int read_quoted(); - Fl_Type *read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options=0); - int read_project(const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); - void read_error(const char *format, ...); - const char *read_word(int wantbrace = 0); - int read_int(); - int read_fdesign_line(const char*& name, const char*& value); - void read_fdesign(); -}; - -class Fd_Project_Writer +class Project_Writer { protected: // Project output file, always opened in "wb" mode @@ -77,8 +39,8 @@ protected: bool write_codeview_; public: - Fd_Project_Writer(); - ~Fd_Project_Writer(); + Project_Writer(); + ~Project_Writer(); int open_write(const char *s); int close_write(); int write_project(const char *filename, int selected_only, bool codeview); @@ -91,4 +53,7 @@ public: bool write_codeview() const { return write_codeview_; } }; -#endif // _FLUID_FILE_H +} // namespace io +} // namespace fld + +#endif // FLUID_IO_PROJECT_WRITER_H diff --git a/fluid/nodes/Fl_Button_Type.cxx b/fluid/nodes/Fl_Button_Type.cxx index 18620b477..2d3b7f31f 100644 --- a/fluid/nodes/Fl_Button_Type.cxx +++ b/fluid/nodes/Fl_Button_Type.cxx @@ -25,7 +25,8 @@ #include "nodes/Fl_Button_Type.h" #include "app/Fd_Snap_Action.h" -#include "io/file.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" #include #include @@ -65,7 +66,7 @@ Fl_Widget *Fl_Button_Type::widget(int x, int y, int w, int h) { return new Fl_Button(x, y, w, h, "Button"); } -void Fl_Button_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Button_Type::write_properties(fld::io::Project_Writer &f) { Fl_Widget_Type::write_properties(f); Fl_Button *btn = (Fl_Button*)o; if (btn->compact()) { @@ -74,7 +75,7 @@ void Fl_Button_Type::write_properties(Fd_Project_Writer &f) { } } -void Fl_Button_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Button_Type::read_property(fld::io::Project_Reader &f, const char *c) { Fl_Button *btn = (Fl_Button*)o; if (!strcmp(c, "compact")) { btn->compact((uchar)atol(f.read_word())); diff --git a/fluid/nodes/Fl_Button_Type.h b/fluid/nodes/Fl_Button_Type.h index d513c1398..4229ac82d 100644 --- a/fluid/nodes/Fl_Button_Type.h +++ b/fluid/nodes/Fl_Button_Type.h @@ -35,8 +35,8 @@ public: int is_button() const FL_OVERRIDE { return 1; } ID id() const FL_OVERRIDE { return ID_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Button) ? true : super::is_a(inID); } - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; }; diff --git a/fluid/nodes/Fl_Function_Type.cxx b/fluid/nodes/Fl_Function_Type.cxx index f8845dcdd..5778324bf 100644 --- a/fluid/nodes/Fl_Function_Type.cxx +++ b/fluid/nodes/Fl_Function_Type.cxx @@ -19,8 +19,9 @@ #include "app/fluid.h" #include "app/mergeback.h" #include "app/undo.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "nodes/Fl_Window_Type.h" #include "nodes/Fl_Group_Type.h" #include "panels/function_panel.h" @@ -230,7 +231,7 @@ Fl_Type *Fl_Function_Type::make(Strategy strategy) { - "C" is written if we want a C signature instead of C++ - "return_type" is followed by the return type of the function */ -void Fl_Function_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Function_Type::write_properties(fld::io::Project_Writer &f) { Fl_Type::write_properties(f); switch (public_) { case 0: f.write_string("private"); break; @@ -247,7 +248,7 @@ void Fl_Function_Type::write_properties(Fd_Project_Writer &f) { Read function specific properties fron an .fl file. \param[in] c read from this string */ -void Fl_Function_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Function_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { @@ -407,9 +408,9 @@ static void clean_function_for_implementation(char *out, const char *function_na /** Write the code for the source and the header file. This writes the code that goes \b before all children of this class. - \see write_code2(Fd_Code_Writer& f) + \see write_code2(fld::io::Code_Writer& f) */ -void Fl_Function_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Function_Type::write_code1(fld::io::Code_Writer& f) { constructor=0; havewidgets = 0; Fl_Type *child; @@ -526,9 +527,9 @@ void Fl_Function_Type::write_code1(Fd_Code_Writer& f) { /** Write the code for the source and the header file. This writes the code that goes \b after all children of this class. - \see write_code1(Fd_Code_Writer& f) + \see write_code1(fld::io::Code_Writer& f) */ -void Fl_Function_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Function_Type::write_code2(fld::io::Code_Writer& f) { Fl_Type *child; const char *var = "w"; char havechildren = 0; @@ -664,7 +665,7 @@ BREAK2: /** Grab changes from an external editor and write this node. */ -void Fl_Code_Type::write(Fd_Project_Writer &f) { +void Fl_Code_Type::write(fld::io::Project_Writer &f) { // External editor changes? If so, load changes into ram, update mtime/size if ( handle_editor_changes() == 1 ) { main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents @@ -675,7 +676,7 @@ void Fl_Code_Type::write(Fd_Project_Writer &f) { /** Write the code block with the correct indentation. */ -void Fl_Code_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Code_Type::write_code1(fld::io::Code_Writer& f) { // External editor changes? If so, load changes into ram, update mtime/size if ( handle_editor_changes() == 1 ) { main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents @@ -789,7 +790,7 @@ Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) { - "after" is followed by the code that comes after the children The "before" code is stored in the name() field. */ -void Fl_CodeBlock_Type::write_properties(Fd_Project_Writer &f) { +void Fl_CodeBlock_Type::write_properties(fld::io::Project_Writer &f) { Fl_Type::write_properties(f); if (after) { f.write_string("after"); @@ -800,7 +801,7 @@ void Fl_CodeBlock_Type::write_properties(Fd_Project_Writer &f) { /** Read the node specific properties. */ -void Fl_CodeBlock_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_CodeBlock_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"after")) { storestring(f.read_word(),after); } else { @@ -849,7 +850,7 @@ BREAK2: /** Write the "before" code. */ -void Fl_CodeBlock_Type::write_code1(Fd_Code_Writer& f) { +void Fl_CodeBlock_Type::write_code1(fld::io::Code_Writer& f) { const char* c = name(); f.write_c("%s%s {\n", f.indent(), c ? c : ""); f.indentation++; @@ -858,7 +859,7 @@ void Fl_CodeBlock_Type::write_code1(Fd_Code_Writer& f) { /** Write the "after" code. */ -void Fl_CodeBlock_Type::write_code2(Fd_Code_Writer& f) { +void Fl_CodeBlock_Type::write_code2(fld::io::Code_Writer& f) { f.indentation--; if (after) f.write_c("%s} %s\n", f.indent(), after); else f.write_c("%s}\n", f.indent()); @@ -928,7 +929,7 @@ Fl_Type *Fl_Decl_Type::make(Strategy strategy) { - "private"/"public"/"protected" - "local"/"global" if this is static or not */ -void Fl_Decl_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Decl_Type::write_properties(fld::io::Project_Writer &f) { Fl_Type::write_properties(f); switch (public_) { case 0: f.write_string("private"); break; @@ -944,7 +945,7 @@ void Fl_Decl_Type::write_properties(Fd_Project_Writer &f) { /** Read the specific properties. */ -void Fl_Decl_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Decl_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"public")) { public_ = 1; } else if (!strcmp(c,"private")) { @@ -1035,7 +1036,7 @@ BREAK2: \todo There are a lot of side effect in this node depending on the given text and the parent node. They need to be understood and documented. */ -void Fl_Decl_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Decl_Type::write_code1(fld::io::Code_Writer& f) { const char* c = name(); if (!c) return; // handle a few keywords differently if inside a class @@ -1158,7 +1159,7 @@ Fl_Type *Fl_Data_Type::make(Strategy strategy) { - "filename" followed by the filename of the file to inline - "textmode" if data is written in ASCII vs. binary */ -void Fl_Data_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Data_Type::write_properties(fld::io::Project_Writer &f) { Fl_Decl_Type::write_properties(f); if (filename_) { f.write_string("filename"); @@ -1175,7 +1176,7 @@ void Fl_Data_Type::write_properties(Fd_Project_Writer &f) { /** Read specific properties. */ -void Fl_Data_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Data_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"filename")) { storestring(f.read_word(), filename_, 1); } else if (!strcmp(c,"textmode")) { @@ -1300,7 +1301,7 @@ BREAK2: /** Write the content of the external file inline into the source code. */ -void Fl_Data_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Data_Type::write_code1(fld::io::Code_Writer& f) { const char *message = 0; const char *c = name(); if (!c) return; @@ -1499,7 +1500,7 @@ Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) { - "public"/"protected" - "after" followed by the second code block. */ -void Fl_DeclBlock_Type::write_properties(Fd_Project_Writer &f) { +void Fl_DeclBlock_Type::write_properties(fld::io::Project_Writer &f) { Fl_Type::write_properties(f); // deprecated if (is_public()) f.write_string("public"); @@ -1513,7 +1514,7 @@ void Fl_DeclBlock_Type::write_properties(Fd_Project_Writer &f) { /** Read the specific properties. */ -void Fl_DeclBlock_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_DeclBlock_Type::read_property(fld::io::Project_Reader &f, const char *c) { if(!strcmp(c,"public")) { write_map_ |= CODE_IN_HEADER; } else if(!strcmp(c,"protected")) { @@ -1632,7 +1633,7 @@ BREAK2: Write the \b before static code to the source file, and to the header file if declared public. The before code is stored in the name() field. */ -void Fl_DeclBlock_Type::write_static(Fd_Code_Writer& f) { +void Fl_DeclBlock_Type::write_static(fld::io::Code_Writer& f) { const char* c = name(); if (c && *c) { if (write_map_ & STATIC_IN_HEADER) @@ -1645,7 +1646,7 @@ void Fl_DeclBlock_Type::write_static(Fd_Code_Writer& f) { /** Write the \b after static code to the source file, and to the header file if declared public. */ -void Fl_DeclBlock_Type::write_static_after(Fd_Code_Writer& f) { +void Fl_DeclBlock_Type::write_static_after(fld::io::Code_Writer& f) { const char* c = after; if (c && *c) { if (write_map_ & STATIC_IN_HEADER) @@ -1659,7 +1660,7 @@ void Fl_DeclBlock_Type::write_static_after(Fd_Code_Writer& f) { Write the \b before code to the source file, and to the header file if declared public. The before code is stored in the name() field. */ -void Fl_DeclBlock_Type::write_code1(Fd_Code_Writer& f) { +void Fl_DeclBlock_Type::write_code1(fld::io::Code_Writer& f) { const char* c = name(); if (c && *c) { if (write_map_ & CODE_IN_HEADER) @@ -1672,7 +1673,7 @@ void Fl_DeclBlock_Type::write_code1(Fd_Code_Writer& f) { /** Write the \b after code to the source file, and to the header file if declared public. */ -void Fl_DeclBlock_Type::write_code2(Fd_Code_Writer& f) { +void Fl_DeclBlock_Type::write_code2(fld::io::Code_Writer& f) { const char* c = after; if (c && *c) { if (write_map_ & CODE_IN_HEADER) @@ -1733,7 +1734,7 @@ Fl_Type *Fl_Comment_Type::make(Strategy strategy) { - "in_source"/"not_in_source" if the comment will be written to the source code - "in_header"/"not_in_header" if the comment will be written to the header file */ -void Fl_Comment_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Comment_Type::write_properties(fld::io::Project_Writer &f) { Fl_Type::write_properties(f); if (in_c_) f.write_string("in_source"); else f.write_string("not_in_source"); if (in_h_) f.write_string("in_header"); else f.write_string("not_in_header"); @@ -1742,7 +1743,7 @@ void Fl_Comment_Type::write_properties(Fd_Project_Writer &f) { /** Read extra properties. */ -void Fl_Comment_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Comment_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"in_source")) { in_c_ = 1; } else if (!strcmp(c,"not_in_source")) { @@ -1900,7 +1901,7 @@ BREAK2: /** Write the comment to the files. */ -void Fl_Comment_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Comment_Type::write_code1(fld::io::Code_Writer& f) { const char* c = name(); if (!c) return; if (!in_c_ && !in_h_) return; @@ -2013,7 +2014,7 @@ Fl_Type *Fl_Class_Type::make(Strategy strategy) { - ":" followed by the super class - "private"/"protected" */ -void Fl_Class_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Class_Type::write_properties(fld::io::Project_Writer &f) { Fl_Type::write_properties(f); if (subclass_of) { f.write_string(":"); @@ -2028,7 +2029,7 @@ void Fl_Class_Type::write_properties(Fd_Project_Writer &f) { /** Read additional properties. */ -void Fl_Class_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Class_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { @@ -2118,7 +2119,7 @@ BREAK2: /** Write the header code that declares this class. */ -void Fl_Class_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Class_Type::write_code1(fld::io::Code_Writer& f) { parent_class = current_class; current_class = this; write_public_state = 0; @@ -2135,7 +2136,7 @@ void Fl_Class_Type::write_code1(Fd_Code_Writer& f) { /** Write the header code that ends the declaration of this class. */ -void Fl_Class_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Class_Type::write_code2(fld::io::Code_Writer& f) { f.write_h("};\n"); current_class = parent_class; } diff --git a/fluid/nodes/Fl_Function_Type.h b/fluid/nodes/Fl_Function_Type.h index 536a511c0..4c2319aee 100644 --- a/fluid/nodes/Fl_Function_Type.h +++ b/fluid/nodes/Fl_Function_Type.h @@ -52,8 +52,8 @@ public: Fl_Function_Type(); ~Fl_Function_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; int ismain() {return name_ == 0;} const char *type_name() FL_OVERRIDE {return "Function";} @@ -65,8 +65,8 @@ public: int is_public() const FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Function; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Function) ? true : super::is_a(inID); } - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; int has_signature(const char *, const char*) const; }; @@ -83,9 +83,9 @@ class Fl_Code_Type : public Fl_Type public: Fl_Code_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write(Fd_Project_Writer &f) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { } + void write(fld::io::Project_Writer &f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE { } void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "code";} int is_code_block() const FL_OVERRIDE {return 0;} @@ -108,8 +108,8 @@ public: Fl_CodeBlock_Type(); ~Fl_CodeBlock_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "codeblock";} int is_code_block() const FL_OVERRIDE {return 1;} @@ -117,8 +117,8 @@ public: int is_public() const FL_OVERRIDE { return -1; } ID id() const FL_OVERRIDE { return ID_CodeBlock; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_CodeBlock) ? true : super::is_a(inID); } - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; }; // ---- Fl_Decl_Type declaration @@ -134,12 +134,12 @@ protected: public: Fl_Decl_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { } + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE { } void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "decl";} - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; int is_public() const FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Decl; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Decl) ? true : super::is_a(inID); } @@ -157,12 +157,12 @@ public: Fl_Data_Type(); ~Fl_Data_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE {} + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE {} void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "data";} - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Data; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Data) ? true : super::is_a(inID); } }; @@ -185,14 +185,14 @@ public: Fl_DeclBlock_Type(); ~Fl_DeclBlock_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_static(Fd_Code_Writer& f) FL_OVERRIDE; - void write_static_after(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_static_after(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "declblock";} - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; int can_have_children() const FL_OVERRIDE {return 1;} int is_decl_block() const FL_OVERRIDE {return 1;} int is_public() const FL_OVERRIDE; @@ -210,12 +210,12 @@ class Fl_Comment_Type : public Fl_Type public: Fl_Comment_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { } + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE { } void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "comment";} - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; int is_public() const FL_OVERRIDE { return 1; } ID id() const FL_OVERRIDE { return ID_Comment; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Comment) ? true : super::is_a(inID); } @@ -238,8 +238,8 @@ public: Fl_Class_Type* parent_class; // save class if nested // Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "class";} int can_have_children() const FL_OVERRIDE {return 1;} @@ -248,8 +248,8 @@ public: int is_public() const FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Class; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Class) ? true : super::is_a(inID); } - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; // class prefix attribute access void prefix(const char* p); diff --git a/fluid/nodes/Fl_Grid_Type.cxx b/fluid/nodes/Fl_Grid_Type.cxx index c2a803c19..03d6620ea 100644 --- a/fluid/nodes/Fl_Grid_Type.cxx +++ b/fluid/nodes/Fl_Grid_Type.cxx @@ -19,8 +19,9 @@ #include "app/fluid.h" #include "app/Fd_Snap_Action.h" #include "app/undo.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "widgets/Node_Browser.h" #include "widgets/Formula_Input.h" @@ -338,7 +339,7 @@ void Fl_Grid_Type::copy_properties_for_children() { d->layout(); } -void Fl_Grid_Type::write_properties(Fd_Project_Writer &f) +void Fl_Grid_Type::write_properties(fld::io::Project_Writer &f) { super::write_properties(f); Fl_Grid* grid = (Fl_Grid*)o; @@ -403,7 +404,7 @@ void Fl_Grid_Type::write_properties(Fd_Project_Writer &f) } } -void Fl_Grid_Type::read_property(Fd_Project_Reader &f, const char *c) +void Fl_Grid_Type::read_property(fld::io::Project_Reader &f, const char *c) { Fl_Grid* grid = (Fl_Grid*)o; if (!strcmp(c,"dimensions")) { @@ -453,7 +454,7 @@ void Fl_Grid_Type::read_property(Fd_Project_Reader &f, const char *c) } } -void Fl_Grid_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) { +void Fl_Grid_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) { Fl_Grid *grid; Fl_Widget *child_widget; Fl_Grid::Cell *cell; @@ -500,7 +501,7 @@ void Fl_Grid_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, // NOTE: we have to do this in a loop just as ::read_property() in case a new // property is added. In the current setup, all the remaining properties // will be skipped -void Fl_Grid_Type::read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) { +void Fl_Grid_Type::read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) { if (!child->is_true_widget()) { super::read_parent_property(f, child, property); return; @@ -539,7 +540,7 @@ void Fl_Grid_Type::read_parent_property(Fd_Project_Reader &f, Fl_Type *child, co } } -void Fl_Grid_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Grid_Type::write_code1(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Grid* grid = (Fl_Grid*)o; Fl_Widget_Type::write_code1(f); @@ -603,7 +604,7 @@ void Fl_Grid_Type::write_code1(Fd_Code_Writer& f) { } } -void Fl_Grid_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Grid_Type::write_code2(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Grid* grid = (Fl_Grid*)o; bool first_cell = true; diff --git a/fluid/nodes/Fl_Grid_Type.h b/fluid/nodes/Fl_Grid_Type.h index 1093a38f3..1ce5321c8 100644 --- a/fluid/nodes/Fl_Grid_Type.h +++ b/fluid/nodes/Fl_Grid_Type.h @@ -57,16 +57,16 @@ public: Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Grid; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Grid) ? true : super::is_a(inID); } - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; - void write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) FL_OVERRIDE; - void read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; + void write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) FL_OVERRIDE; + void read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) FL_OVERRIDE; Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void leave_live_mode() FL_OVERRIDE; void copy_properties() FL_OVERRIDE; void copy_properties_for_children() FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; diff --git a/fluid/nodes/Fl_Group_Type.cxx b/fluid/nodes/Fl_Group_Type.cxx index dc602e870..5d3cba07c 100644 --- a/fluid/nodes/Fl_Group_Type.cxx +++ b/fluid/nodes/Fl_Group_Type.cxx @@ -23,8 +23,9 @@ #include "app/fluid.h" #include "app/undo.h" #include "app/Fd_Snap_Action.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "widgets/Node_Browser.h" #include @@ -195,11 +196,11 @@ void Fl_Group_Type::ideal_size(int &w, int &h) { Fd_Snap_Action::better_size(w, h); } -void Fl_Group_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Group_Type::write_code1(fld::io::Code_Writer& f) { Fl_Widget_Type::write_code1(f); } -void Fl_Group_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Group_Type::write_code2(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; write_extra_code(f); f.write_c("%s%s->end();\n", f.indent(), var); @@ -348,7 +349,7 @@ void Fl_Flex_Type::copy_properties_for_children() { d->layout(); } -void Fl_Flex_Type::write_properties(Fd_Project_Writer &f) +void Fl_Flex_Type::write_properties(fld::io::Project_Writer &f) { Fl_Group_Type::write_properties(f); Fl_Flex* flex = (Fl_Flex*)o; @@ -373,7 +374,7 @@ void Fl_Flex_Type::write_properties(Fd_Project_Writer &f) } } -void Fl_Flex_Type::read_property(Fd_Project_Reader &f, const char *c) +void Fl_Flex_Type::read_property(fld::io::Project_Reader &f, const char *c) { Fl_Flex* flex = (Fl_Flex*)o; suspend_auto_layout = 1; @@ -421,7 +422,7 @@ void Fl_Flex_Type::postprocess_read() suspend_auto_layout = 0; } -void Fl_Flex_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Flex_Type::write_code2(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Flex* flex = (Fl_Flex*)o; int lm, tm, rm, bm; diff --git a/fluid/nodes/Fl_Group_Type.h b/fluid/nodes/Fl_Group_Type.h index 88645a08e..30fab1d20 100644 --- a/fluid/nodes/Fl_Group_Type.h +++ b/fluid/nodes/Fl_Group_Type.h @@ -54,8 +54,8 @@ public: Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { Fl_Group_Proxy *g = new Fl_Group_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Group_Type();} - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; @@ -114,13 +114,13 @@ public: Fl_Flex *g = new Fl_Flex_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} ID id() const FL_OVERRIDE { return ID_Flex; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Flex) ? true : super::is_a(inID); } - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; void copy_properties_for_children() FL_OVERRIDE; void postprocess_read() FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; // void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; // void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; diff --git a/fluid/nodes/Fl_Menu_Type.cxx b/fluid/nodes/Fl_Menu_Type.cxx index 145f0082d..83435df50 100644 --- a/fluid/nodes/Fl_Menu_Type.cxx +++ b/fluid/nodes/Fl_Menu_Type.cxx @@ -23,11 +23,13 @@ #include "nodes/Fl_Menu_Type.h" #include "app/fluid.h" +#include "app/project.h" #include "app/Fluid_Image.h" #include "app/mergeback.h" #include "app/undo.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "nodes/Fl_Window_Type.h" #include "widgets/Formula_Input.h" #include "widgets/Node_Browser.h" @@ -300,7 +302,7 @@ int isdeclare(const char *c); // Search backwards to find the parent menu button and return it's name. // Also put in i the index into the button's menu item array belonging // to this menu item. -const char* Fl_Menu_Item_Type::menu_name(Fd_Code_Writer& f, int& i) { +const char* Fl_Menu_Item_Type::menu_name(fld::io::Code_Writer& f, int& i) { i = 0; Fl_Type* t = prev; while (t && t->is_a(ID_Menu_Item)) { @@ -315,7 +317,7 @@ const char* Fl_Menu_Item_Type::menu_name(Fd_Code_Writer& f, int& i) { return f.unique_id(t, "menu", t->name(), t->label()); } -void Fl_Menu_Item_Type::write_static(Fd_Code_Writer& f) { +void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { if (image && label() && label()[0]) { f.write_h_once("#include "); f.write_h_once("#include "); @@ -447,7 +449,7 @@ void Fl_Menu_Item_Type::write_static(Fd_Code_Writer& f) { f.write_c("Fl_Menu_Item* %s::%s = %s::%s + %d;\n", k, c, k, n, i); } else { // if the name is an array, only define the array. - // The actual assignment is in write_code1(Fd_Code_Writer& f) + // The actual assignment is in write_code1(fld::io::Code_Writer& f) f.write_c("Fl_Menu_Item* %s::%s;\n", k, c); } } @@ -468,7 +470,7 @@ int Fl_Menu_Item_Type::flags() { return i; } -void Fl_Menu_Item_Type::write_item(Fd_Code_Writer& f) { +void Fl_Menu_Item_Type::write_item(fld::io::Code_Writer& f) { static const char * const labeltypes[] = { "FL_NORMAL_LABEL", "FL_NO_LABEL", @@ -534,7 +536,7 @@ void Fl_Menu_Item_Type::write_item(Fd_Code_Writer& f) { f.write_c("},\n"); } -void start_menu_initialiser(Fd_Code_Writer& f, int &initialized, const char *name, int index) { +void start_menu_initialiser(fld::io::Code_Writer& f, int &initialized, const char *name, int index) { if (!initialized) { initialized = 1; f.write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", f.indent(), name, index); @@ -542,7 +544,7 @@ void start_menu_initialiser(Fd_Code_Writer& f, int &initialized, const char *nam } } -void Fl_Menu_Item_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Menu_Item_Type::write_code1(fld::io::Code_Writer& f) { int i; const char* mname = menu_name(f, i); if (!prev->is_a(ID_Menu_Item)) { @@ -637,7 +639,7 @@ void Fl_Menu_Item_Type::write_code1(Fd_Code_Writer& f) { } } -void Fl_Menu_Item_Type::write_code2(Fd_Code_Writer&) {} +void Fl_Menu_Item_Type::write_code2(fld::io::Code_Writer&) {} //////////////////////////////////////////////////////////////// // This is the base class for widgets that contain a menu (ie @@ -729,7 +731,7 @@ Fl_Type* Fl_Menu_Base_Type::click_test(int, int) { return this; } -void Fl_Menu_Manager_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Menu_Manager_Type::write_code2(fld::io::Code_Writer& f) { if (next && next->is_a(ID_Menu_Item)) { f.write_c("%s%s->menu(%s);\n", f.indent(), name() ? name() : "o", f.unique_id(this, "menu", name(), label())); @@ -843,7 +845,7 @@ const char *Fl_Menu_Bar_Type::sys_menubar_proxy_name() { } -void Fl_Menu_Bar_Type::write_static(Fd_Code_Writer& f) { +void Fl_Menu_Bar_Type::write_static(fld::io::Code_Writer& f) { super::write_static(f); if (is_sys_menu_bar()) { f.write_h_once("#include "); @@ -863,7 +865,7 @@ void Fl_Menu_Bar_Type::write_static(Fd_Code_Writer& f) { } } -void Fl_Menu_Bar_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Menu_Bar_Type::write_code1(fld::io::Code_Writer& f) { super::write_code1(f); if (is_sys_menu_bar() && is_in_class()) { f.write_c("%s((%s*)%s)->_parent_class = (void*)this;\n", @@ -871,7 +873,7 @@ void Fl_Menu_Bar_Type::write_code1(Fd_Code_Writer& f) { } } -//void Fl_Menu_Bar_Type::write_code2(Fd_Code_Writer& f) { +//void Fl_Menu_Bar_Type::write_code2(fld::io::Code_Writer& f) { // super::write_code2(f); //} diff --git a/fluid/nodes/Fl_Menu_Type.h b/fluid/nodes/Fl_Menu_Type.h index b4ad90081..136a1c289 100644 --- a/fluid/nodes/Fl_Menu_Type.h +++ b/fluid/nodes/Fl_Menu_Type.h @@ -55,12 +55,12 @@ public: int is_button() const FL_OVERRIDE {return 1;} // this gets shortcut to work Fl_Widget* widget(int,int,int,int) FL_OVERRIDE {return 0;} Fl_Widget_Type* _make() FL_OVERRIDE {return 0;} - virtual const char* menu_name(Fd_Code_Writer& f, int& i); + virtual const char* menu_name(fld::io::Code_Writer& f, int& i); int flags(); - void write_static(Fd_Code_Writer& f) FL_OVERRIDE; - void write_item(Fd_Code_Writer& f); - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_item(fld::io::Code_Writer& f); + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; int is_true_widget() const FL_OVERRIDE { return 0; } ID id() const FL_OVERRIDE { return ID_Menu_Item; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Item) ? true : super::is_a(inID); } @@ -142,7 +142,7 @@ public: void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE { build_menu(); } void remove_child(Fl_Type*) FL_OVERRIDE { build_menu();} Fl_Type* click_test(int x, int y) FL_OVERRIDE = 0; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; void copy_properties() FL_OVERRIDE = 0; ID id() const FL_OVERRIDE { return ID_Menu_Manager_; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Manager_) ? true : super::is_a(inID); } @@ -271,9 +271,9 @@ public: const char *alt_type_name() FL_OVERRIDE {return "fltk::MenuBar";} Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE {return new Fl_Menu_Bar(X,Y,W,H);} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Menu_Bar_Type();} - void write_static(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; -// void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; +// void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Menu_Bar; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Bar) ? true : super::is_a(inID); } bool is_sys_menu_bar(); diff --git a/fluid/nodes/Fl_Type.cxx b/fluid/nodes/Fl_Type.cxx index 02b95888e..8f078e06e 100644 --- a/fluid/nodes/Fl_Type.cxx +++ b/fluid/nodes/Fl_Type.cxx @@ -97,11 +97,13 @@ #include "nodes/Fl_Type.h" #include "app/fluid.h" +#include "app/project.h" #include "app/Fd_Snap_Action.h" #include "app/shell_command.h" #include "app/undo.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "nodes/Fl_Function_Type.h" #include "nodes/Fl_Widget_Type.h" #include "nodes/Fl_Window_Type.h" @@ -886,7 +888,7 @@ void Fl_Type::move_before(Fl_Type* g) { // write a widget and all its children: -void Fl_Type::write(Fd_Project_Writer &f) { +void Fl_Type::write(fld::io::Project_Writer &f) { if (f.write_codeview()) proj1_start = (int)ftell(f.file()) + 1; if (f.write_codeview()) proj2_start = (int)ftell(f.file()) + 1; f.write_indent(level); @@ -918,7 +920,7 @@ void Fl_Type::write(Fd_Project_Writer &f) { if (f.write_codeview()) proj2_end = (int)ftell(f.file()); } -void Fl_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Type::write_properties(fld::io::Project_Writer &f) { // repeat this for each attribute: if (g_project.write_mergeback_data && uid_) { f.write_word("uid"); @@ -952,7 +954,7 @@ void Fl_Type::write_properties(Fd_Project_Writer &f) { if (selected) f.write_word("selected"); } -void Fl_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"uid")) { const char *hex = f.read_word(); int x = 0; @@ -1017,13 +1019,13 @@ void Fl_Type::read_property(Fd_Project_Reader &f, const char *c) { Lastly, this method should call the super class to give it a chance to append its own properties. - \see Fl_Grid_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) + \see Fl_Grid_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) \param[in] f the project file writer \param[in] child write properties for this child, make sure it has the correct type \param[in] encapsulate write the `parent_properties {}` block if true before writing any properties */ -void Fl_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) { +void Fl_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) { (void)f; (void)child; (void)encapsulate; // nothing to do here // put the following code into your implementation of write_parent_properties @@ -1050,14 +1052,14 @@ void Fl_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool method reads back those properties. This function is virtual, so if a Type does not support a property, it will propagate to its super class. - \see Fl_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) - \see Fl_Grid_Type::read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) + \see Fl_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) + \see Fl_Grid_Type::read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) \param[in] f the project file writer \param[in] child read properties for this child \param[in] property the name of a property, or "}" when we reach the end of the list */ -void Fl_Type::read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) { +void Fl_Type::read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) { (void)child; f.read_error("Unknown parent property \"%s\"", property); } @@ -1069,7 +1071,7 @@ int Fl_Type::read_fdesign(const char*, const char*) {return 0;} Write a comment into the header file. \param[in] pre indent the comment by this string */ -void Fl_Type::write_comment_h(Fd_Code_Writer& f, const char *pre) +void Fl_Type::write_comment_h(fld::io::Code_Writer& f, const char *pre) { if (comment() && *comment()) { f.write_h("%s/**\n", pre); @@ -1092,7 +1094,7 @@ void Fl_Type::write_comment_h(Fd_Code_Writer& f, const char *pre) /** Write a comment into the source file. */ -void Fl_Type::write_comment_c(Fd_Code_Writer& f, const char *pre) +void Fl_Type::write_comment_c(fld::io::Code_Writer& f, const char *pre) { if (comment() && *comment()) { f.write_c("%s/**\n", pre); @@ -1117,7 +1119,7 @@ void Fl_Type::write_comment_c(Fd_Code_Writer& f, const char *pre) /** Write a comment into the source file. */ -void Fl_Type::write_comment_inline_c(Fd_Code_Writer& f, const char *pre) +void Fl_Type::write_comment_inline_c(fld::io::Code_Writer& f, const char *pre) { if (comment() && *comment()) { const char *s = comment(); @@ -1197,7 +1199,7 @@ int Fl_Type::user_defined(const char* cbname) const { return 0; } -const char *Fl_Type::callback_name(Fd_Code_Writer& f) { +const char *Fl_Type::callback_name(fld::io::Code_Writer& f) { if (is_name(callback())) return callback(); return f.unique_id(this, "cb", name(), label()); } @@ -1250,18 +1252,18 @@ bool Fl_Type::is_in_class() const { return false; } -void Fl_Type::write_static(Fd_Code_Writer&) { +void Fl_Type::write_static(fld::io::Code_Writer&) { } -void Fl_Type::write_static_after(Fd_Code_Writer&) { +void Fl_Type::write_static_after(fld::io::Code_Writer&) { } -void Fl_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Type::write_code1(fld::io::Code_Writer& f) { f.write_h("// Header for %s\n", title()); f.write_c("// Code for %s\n", title()); } -void Fl_Type::write_code2(Fd_Code_Writer&) { +void Fl_Type::write_code2(fld::io::Code_Writer&) { } /** Set a uid that is unique within the project. diff --git a/fluid/nodes/Fl_Type.h b/fluid/nodes/Fl_Type.h index 478059c13..e7dde3b39 100644 --- a/fluid/nodes/Fl_Type.h +++ b/fluid/nodes/Fl_Type.h @@ -17,7 +17,7 @@ #ifndef _FLUID_FL_TYPE_H #define _FLUID_FL_TYPE_H -#include "io/code.h" +#include "io/Code_Writer.h" #include #include @@ -26,8 +26,14 @@ class Fl_Type; class Fl_Group_Type; class Fl_Window_Type; -class Fd_Project_Reader; -class Fd_Project_Writer; +namespace fld { +namespace io { + +class Project_Reader; +class Project_Writer; + +} // namespace io +} // namespace fld /** Declare where a new type is placed and how to create it. @@ -47,8 +53,8 @@ class Fd_Project_Writer; Add a hierarchy of Types void Fl_Type::add(Fl_Type *p, Strategy strategy) int read_file(const char *filename, int merge, Strategy strategy) - Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) - int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy) + Fl_Type *fld::io::Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) + int fld::io::Project_Reader::read_project(const char *filename, int merge, Strategy strategy) */ typedef struct Strategy { enum Flags { @@ -188,7 +194,7 @@ public: // things that should not be public: Fl_Type *first_child(); Fl_Type *factory; - const char *callback_name(Fd_Code_Writer& f); + const char *callback_name(fld::io::Code_Writer& f); // text positions of this type in code, header, and project file (see codeview) int code_static_start, code_static_end; @@ -252,22 +258,22 @@ public: virtual void open(); // what happens when you double-click // read and write data to a saved file: - virtual void write(Fd_Project_Writer &f); - virtual void write_properties(Fd_Project_Writer &f); - virtual void read_property(Fd_Project_Reader &f, const char *); - virtual void write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate); - virtual void read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property); + virtual void write(fld::io::Project_Writer &f); + virtual void write_properties(fld::io::Project_Writer &f); + virtual void read_property(fld::io::Project_Reader &f, const char *); + virtual void write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate); + virtual void read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property); virtual int read_fdesign(const char*, const char*); virtual void postprocess_read() { } // write code, these are called in order: - virtual void write_static(Fd_Code_Writer& f); // write static stuff to .c file - virtual void write_static_after(Fd_Code_Writer& f); // write static stuff after children - virtual void write_code1(Fd_Code_Writer& f); // code and .h before children - virtual void write_code2(Fd_Code_Writer& f); // code and .h after children - void write_comment_h(Fd_Code_Writer& f, const char *ind=""); // write the commentary text into the header file - void write_comment_c(Fd_Code_Writer& f, const char *ind=""); // write the commentary text into the source file - void write_comment_inline_c(Fd_Code_Writer& f, const char *ind=0L); // write the commentary text + virtual void write_static(fld::io::Code_Writer& f); // write static stuff to .c file + virtual void write_static_after(fld::io::Code_Writer& f); // write static stuff after children + virtual void write_code1(fld::io::Code_Writer& f); // code and .h before children + virtual void write_code2(fld::io::Code_Writer& f); // code and .h after children + void write_comment_h(fld::io::Code_Writer& f, const char *ind=""); // write the commentary text into the header file + void write_comment_c(fld::io::Code_Writer& f, const char *ind=""); // write the commentary text into the source file + void write_comment_inline_c(fld::io::Code_Writer& f, const char *ind=0L); // write the commentary text // live mode virtual Fl_Widget *enter_live_mode(int top=0); // build widgets needed for live mode diff --git a/fluid/nodes/Fl_Widget_Type.cxx b/fluid/nodes/Fl_Widget_Type.cxx index 2ed31f0d8..2cde4d531 100644 --- a/fluid/nodes/Fl_Widget_Type.cxx +++ b/fluid/nodes/Fl_Widget_Type.cxx @@ -17,11 +17,13 @@ #include "nodes/Fl_Widget_Type.h" #include "app/fluid.h" +#include "app/project.h" #include "app/Fluid_Image.h" #include "app/mergeback.h" #include "app/undo.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "nodes/Fl_Window_Type.h" #include "nodes/Fl_Group_Type.h" #include "nodes/Fl_Menu_Type.h" @@ -2912,7 +2914,7 @@ int isdeclare(const char *c) { return 0; } -void Fl_Widget_Type::write_static(Fd_Code_Writer& f) { +void Fl_Widget_Type::write_static(fld::io::Code_Writer& f) { const char* t = subclassname(this); if (!subclass() || (is_class() && !strncmp(t, "Fl_", 3))) { f.write_h_once("#include "); @@ -3001,7 +3003,7 @@ void Fl_Widget_Type::write_static(Fd_Code_Writer& f) { } } -void Fl_Widget_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Widget_Type::write_code1(fld::io::Code_Writer& f) { const char* t = subclassname(this); const char *c = array_name(this); if (c) { @@ -3126,7 +3128,7 @@ void Fl_Widget_Type::write_code1(Fd_Code_Writer& f) { write_widget_code(f); } -void Fl_Widget_Type::write_color(Fd_Code_Writer& f, const char* field, Fl_Color color) { +void Fl_Widget_Type::write_color(fld::io::Code_Writer& f, const char* field, Fl_Color color) { const char* color_name = 0; switch (color) { case FL_FOREGROUND_COLOR: color_name = "FL_FOREGROUND_COLOR"; break; @@ -3164,8 +3166,8 @@ void Fl_Widget_Type::write_color(Fd_Code_Writer& f, const char* field, Fl_Color } } -// this is split from write_code1(Fd_Code_Writer& f) for Fl_Window_Type: -void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) { +// this is split from write_code1(fld::io::Code_Writer& f) for Fl_Window_Type: +void Fl_Widget_Type::write_widget_code(fld::io::Code_Writer& f) { Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; const char *var = is_class() ? "this" : name() ? name() : "o"; @@ -3363,26 +3365,26 @@ void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) { } } -void Fl_Widget_Type::write_extra_code(Fd_Code_Writer& f) { +void Fl_Widget_Type::write_extra_code(fld::io::Code_Writer& f) { for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n) && !isdeclare(extra_code(n))) f.write_c("%s%s\n", f.indent(), extra_code(n)); } -void Fl_Widget_Type::write_block_close(Fd_Code_Writer& f) { +void Fl_Widget_Type::write_block_close(fld::io::Code_Writer& f) { f.indentation--; f.write_c("%s} // %s* %s\n", f.indent(), subclassname(this), name() ? name() : "o"); } -void Fl_Widget_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Widget_Type::write_code2(fld::io::Code_Writer& f) { write_extra_code(f); write_block_close(f); } //////////////////////////////////////////////////////////////// -void Fl_Widget_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Widget_Type::write_properties(fld::io::Project_Writer &f) { Fl_Type::write_properties(f); f.write_indent(level+1); switch (public_) { @@ -3515,7 +3517,7 @@ void Fl_Widget_Type::write_properties(Fd_Project_Writer &f) { } } -void Fl_Widget_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Widget_Type::read_property(fld::io::Project_Reader &f, const char *c) { int x,y,w,h; Fl_Font ft; int s; Fl_Color cc; if (!strcmp(c,"private")) { public_ = 0; @@ -3726,7 +3728,7 @@ int Fl_Widget_Type::read_fdesign(const char* propname, const char* value) { if (!strcmp(propname,"box")) { float x,y,w,h; if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) { - if (fdesign_flip) { + if (fld::io::fdesign_flip) { Fl_Type *p; for (p = parent; p && !p->is_a(ID_Window); p = p->parent) {/*empty*/} if (p && p->is_widget()) y = ((Fl_Widget_Type*)p)->o->h()-(y+h); diff --git a/fluid/nodes/Fl_Widget_Type.h b/fluid/nodes/Fl_Widget_Type.h index 76bea3404..6a26921cc 100644 --- a/fluid/nodes/Fl_Widget_Type.h +++ b/fluid/nodes/Fl_Widget_Type.h @@ -60,13 +60,13 @@ protected: /// disabling the output of the "hide" property by the Widget Type. uchar override_visible_; - void write_static(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_widget_code(Fd_Code_Writer& f); - void write_extra_code(Fd_Code_Writer& f); - void write_block_close(Fd_Code_Writer& f); - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; - void write_color(Fd_Code_Writer& f, const char*, Fl_Color); + void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_widget_code(fld::io::Code_Writer& f); + void write_extra_code(fld::io::Code_Writer& f); + void write_block_close(fld::io::Code_Writer& f); + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_color(fld::io::Code_Writer& f, const char*, Fl_Color); Fl_Widget *live_widget; public: @@ -112,8 +112,8 @@ public: int is_true_widget() const FL_OVERRIDE { return 1; } int is_public() const FL_OVERRIDE; - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; int read_fdesign(const char*, const char*) FL_OVERRIDE; Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; diff --git a/fluid/nodes/Fl_Window_Type.cxx b/fluid/nodes/Fl_Window_Type.cxx index 7de2ba3dc..3f68f7980 100644 --- a/fluid/nodes/Fl_Window_Type.cxx +++ b/fluid/nodes/Fl_Window_Type.cxx @@ -22,9 +22,11 @@ #include "app/Fd_Snap_Action.h" #include "app/fluid.h" +#include "app/project.h" #include "app/undo.h" -#include "io/file.h" -#include "io/code.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" #include "nodes/factory.h" #include "nodes/Fl_Group_Type.h" #include "nodes/Fl_Grid_Type.h" @@ -1262,7 +1264,7 @@ int Fl_Window_Type::handle(int event) { Write the C++ code that comes before the children of the window are written. \param f the source code output stream */ -void Fl_Window_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Window_Type::write_code1(fld::io::Code_Writer& f) { Fl_Widget_Type::write_code1(f); } @@ -1271,7 +1273,7 @@ void Fl_Window_Type::write_code1(Fd_Code_Writer& f) { Write the C++ code that comes after the children of the window are written. \param f the source code output stream */ -void Fl_Window_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Window_Type::write_code2(fld::io::Code_Writer& f) { const char *var = is_class() ? "this" : name() ? name() : "o"; // make the window modal or non-modal if (modal) { @@ -1306,7 +1308,7 @@ void Fl_Window_Type::write_code2(Fd_Code_Writer& f) { write_block_close(f); } -void Fl_Window_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Window_Type::write_properties(fld::io::Project_Writer &f) { Fl_Widget_Type::write_properties(f); if (modal) f.write_string("modal"); else if (non_modal) f.write_string("non_modal"); @@ -1317,7 +1319,7 @@ void Fl_Window_Type::write_properties(Fd_Project_Writer &f) { if (o->visible() || override_visible_) f.write_string("visible"); } -void Fl_Window_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Window_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"modal")) { modal = 1; } else if (!strcmp(c,"non_modal")) { @@ -1404,7 +1406,7 @@ Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) { return myo; } -void Fl_Widget_Class_Type::write_properties(Fd_Project_Writer &f) { +void Fl_Widget_Class_Type::write_properties(fld::io::Project_Writer &f) { Fl_Window_Type::write_properties(f); if (wc_relative==1) f.write_string("position_relative"); @@ -1412,7 +1414,7 @@ void Fl_Widget_Class_Type::write_properties(Fd_Project_Writer &f) { f.write_string("position_relative_rescale"); } -void Fl_Widget_Class_Type::read_property(Fd_Project_Reader &f, const char *c) { +void Fl_Widget_Class_Type::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"position_relative")) { wc_relative = 1; } else if (!strcmp(c,"position_relative_rescale")) { @@ -1435,9 +1437,9 @@ static const char *trimclassname(const char *n) { } -void Fl_Widget_Class_Type::write_code1(Fd_Code_Writer& f) { +void Fl_Widget_Class_Type::write_code1(fld::io::Code_Writer& f) { #if 0 - Fl_Widget_Type::write_code1(Fd_Code_Writer& f); + Fl_Widget_Type::write_code1(fld::io::Code_Writer& f); #endif // 0 current_widget_class = this; @@ -1505,7 +1507,7 @@ void Fl_Widget_Class_Type::write_code1(Fd_Code_Writer& f) { Write the C++ code that comes after the children of the window are written. \param f the source code output stream */ -void Fl_Widget_Class_Type::write_code2(Fd_Code_Writer& f) { +void Fl_Widget_Class_Type::write_code2(fld::io::Code_Writer& f) { // make the window modal or non-modal if (modal) { f.write_c("%sset_modal();\n", f.indent()); diff --git a/fluid/nodes/Fl_Window_Type.h b/fluid/nodes/Fl_Window_Type.h index a0695f2a1..0dcb9e96e 100644 --- a/fluid/nodes/Fl_Window_Type.h +++ b/fluid/nodes/Fl_Window_Type.h @@ -67,8 +67,8 @@ protected: void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h); int handle(int); void setlabel(const char *) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; Fl_Widget_Type *_make() FL_OVERRIDE {return 0;} // we don't call this Fl_Widget *widget(int,int,int,int) FL_OVERRIDE {return 0;} int recalc; // set by fix_overlay() @@ -105,8 +105,8 @@ public: void fix_overlay(); // Update the bounding box, etc uchar *read_image(int &ww, int &hh); // Read an image of the window - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; int read_fdesign(const char*, const char*) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; @@ -139,11 +139,11 @@ public: char write_public_state; // true when public: has been printed char wc_relative; // if 1, reposition all children, if 2, reposition and resize - void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; - void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; + void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; Fl_Type *make(Strategy strategy) FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "widget_class";} ID id() const FL_OVERRIDE { return ID_Widget_Class; } diff --git a/fluid/panels/codeview_panel.cxx b/fluid/panels/codeview_panel.cxx index 6a877896d..c1c6a1d65 100644 --- a/fluid/panels/codeview_panel.cxx +++ b/fluid/panels/codeview_panel.cxx @@ -18,7 +18,9 @@ #include "codeview_panel.h" #include "app/fluid.h" -#include "io/file.h" +#include "app/project.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" #include #include #include "../src/flstring.h" @@ -167,7 +169,7 @@ void update_codeview_cb(class Fl_Button*, void*) { } if (cv_project->visible_r()) { - write_file(cv_design_filename, false, true); + fld::io::write_file(cv_design_filename, false, true); int top = cv_project->top_line(); cv_project->buffer()->loadfile(cv_design_filename); cv_project->scroll(top, 0); @@ -188,7 +190,7 @@ void update_codeview_cb(class Fl_Button*, void*) { g_project.header_file_name = cv_header_filename; // generate the code and load the files - Fd_Code_Writer f; + fld::io::Code_Writer f; // generate files if (f.write_code(cv_source_filename, cv_header_filename, true)) { diff --git a/fluid/panels/codeview_panel.fl b/fluid/panels/codeview_panel.fl index e2ae3e888..ce40ffd8a 100644 --- a/fluid/panels/codeview_panel.fl +++ b/fluid/panels/codeview_panel.fl @@ -23,7 +23,13 @@ comment {// decl {\#include "app/fluid.h"} {private local } -decl {\#include "io/file.h"} {private local +decl {\#include "app/project.h"} {private local +} + +decl {\#include "io/Project_Reader.h"} {private local +} + +decl {\#include "io/Project_Writer.h"} {private local } decl {\#include } {private local @@ -188,7 +194,7 @@ and load those into the Code Viewer widgets.} open return_type void } if (cv_project->visible_r()) { - write_file(cv_design_filename, false, true); + fld::io::write_file(cv_design_filename, false, true); int top = cv_project->top_line(); cv_project->buffer()->loadfile(cv_design_filename); cv_project->scroll(top, 0); @@ -209,7 +215,7 @@ and load those into the Code Viewer widgets.} open return_type void g_project.header_file_name = cv_header_filename; // generate the code and load the files - Fd_Code_Writer f; + fld::io::Code_Writer f; // generate files if (f.write_code(cv_source_filename, cv_header_filename, true)) { diff --git a/fluid/panels/settings_panel.cxx b/fluid/panels/settings_panel.cxx index fb31a319d..358f90c8d 100644 --- a/fluid/panels/settings_panel.cxx +++ b/fluid/panels/settings_panel.cxx @@ -17,6 +17,7 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0500 #include "settings_panel.h" +#include "app/project.h" #include "app/undo.h" #include #include diff --git a/fluid/panels/settings_panel.fl b/fluid/panels/settings_panel.fl index 7890e5b83..7460ae8af 100644 --- a/fluid/panels/settings_panel.fl +++ b/fluid/panels/settings_panel.fl @@ -52,6 +52,9 @@ comment {// decl {\#include "app/fluid.h"} {public global } +decl {\#include "app/project.h"} {private local +} + decl {\#include "app/undo.h"} {private global } @@ -61,7 +64,7 @@ decl {\#include "app/Fd_Snap_Action.h"} {public global decl {\#include "app/shell_command.h"} {public global } -decl {\#include "tools/fluid_filename.h"} {public local +decl {\#include "tools/filename.h"} {public local } decl {\#include "widgets/Node_Browser.h"} {public global diff --git a/fluid/panels/settings_panel.h b/fluid/panels/settings_panel.h index c26b165c5..8aea3a221 100644 --- a/fluid/panels/settings_panel.h +++ b/fluid/panels/settings_panel.h @@ -22,7 +22,7 @@ #include "app/fluid.h" #include "app/Fd_Snap_Action.h" #include "app/shell_command.h" -#include "tools/fluid_filename.h" +#include "tools/filename.h" #include "widgets/Node_Browser.h" #include #include diff --git a/fluid/panels/template_panel.cxx b/fluid/panels/template_panel.cxx index c93500d72..11227a549 100644 --- a/fluid/panels/template_panel.cxx +++ b/fluid/panels/template_panel.cxx @@ -18,7 +18,7 @@ #include "template_panel.h" #include "app/fluid.h" -#include "tools/fluid_filename.h" +#include "tools/filename.h" #include #include #include diff --git a/fluid/panels/template_panel.fl b/fluid/panels/template_panel.fl index cbbb5c7ff..b0ba20968 100644 --- a/fluid/panels/template_panel.fl +++ b/fluid/panels/template_panel.fl @@ -23,7 +23,7 @@ comment {// decl {\#include "app/fluid.h"} {private local } -decl {\#include "tools/fluid_filename.h"} {selected private local +decl {\#include "tools/filename.h"} {selected private local } decl {\#include } {private local diff --git a/fluid/tools/ExternalCodeEditor_UNIX.cxx b/fluid/tools/ExternalCodeEditor_UNIX.cxx index 09d7e6178..bf472d896 100644 --- a/fluid/tools/ExternalCodeEditor_UNIX.cxx +++ b/fluid/tools/ExternalCodeEditor_UNIX.cxx @@ -6,6 +6,7 @@ #include "ExternalCodeEditor_UNIX.h" #include "app/fluid.h" +#include "app/project.h" #include /* Fl_Timeout_Handler.. */ #include /* fl_alert() */ diff --git a/fluid/tools/ExternalCodeEditor_WIN32.cxx b/fluid/tools/ExternalCodeEditor_WIN32.cxx index c58f22a30..09688d16a 100644 --- a/fluid/tools/ExternalCodeEditor_WIN32.cxx +++ b/fluid/tools/ExternalCodeEditor_WIN32.cxx @@ -18,6 +18,7 @@ #include "tools/ExternalCodeEditor_WIN32.h" #include "app/fluid.h" +#include "app/project.h" #include // Fl_Timeout_Handler.. #include // fl_alert() diff --git a/fluid/tools/autodoc.cxx b/fluid/tools/autodoc.cxx index 857c5c12b..295ab8d2f 100644 --- a/fluid/tools/autodoc.cxx +++ b/fluid/tools/autodoc.cxx @@ -19,6 +19,7 @@ #include "tools/autodoc.h" #include "app/fluid.h" +#include "app/project.h" #include "nodes/factory.h" #include "nodes/Fl_Widget_Type.h" #include "nodes/Fl_Window_Type.h" diff --git a/fluid/tools/filename.cxx b/fluid/tools/filename.cxx index 655d90543..bbd749ce1 100644 --- a/fluid/tools/filename.cxx +++ b/fluid/tools/filename.cxx @@ -14,7 +14,7 @@ // https://www.fltk.org/bugs.php // -/** \file fluid/fluid_filename.cxx +/** \file fluid/filename.cxx \brief File names and URI utility functions for FLUID only. @@ -29,7 +29,7 @@ the next release after 1.4.x will be. We'll use std::string instead! */ -#include "tools/fluid_filename.h" +#include "tools/filename.h" #include #include diff --git a/fluid/tools/filename.h b/fluid/tools/filename.h index 4544a0534..13488d399 100644 --- a/fluid/tools/filename.h +++ b/fluid/tools/filename.h @@ -14,7 +14,7 @@ * https://www.fltk.org/bugs.php */ -/** \file fluid/fluid_filename.h +/** \file fluid/filename.h \brief Handling file names operations that are not in the core library. */ @@ -25,4 +25,10 @@ std::string fl_filename_shortened(const std::string &filename, int maxchars); +namespace fld { + +using filename = std::string; + +} // namespace fld + #endif // FLUID_TOOLS_FILENAME_H -- cgit v1.2.3