diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt index 6162bb89e..bb3b9fe51 100644 --- a/fluid/CMakeLists.txt +++ b/fluid/CMakeLists.txt @@ -17,7 +17,8 @@ # Targets that will be built: fluid and fluid-cmd (Windows) set(TARGETS fluid) -# Source files for 'fluid-lib' = all source files except the main file (fluid.cxx) +# Source files for 'fluid-lib' = all source files except the main files +# (fluid.cxx and fluid.h) # Note: macOS (Xcode) needs at least one source file (fluid.cxx) to link the main # program fluid properly @@ -116,7 +117,7 @@ if(APPLE AND NOT FLTK_BACKEND_X11) set(ICON_NAME fluid.icns) set(ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_NAME}") - add_executable(fluid MACOSX_BUNDLE fluid.cxx ${ICON_PATH}) + add_executable(fluid MACOSX_BUNDLE fluid.cxx fluid.h ${ICON_PATH}) # create macOS bundle wrapper script @@ -133,7 +134,7 @@ if(APPLE AND NOT FLTK_BACKEND_X11) else() # Option 'WIN32' builds a Windows GUI program, ignored on other platforms - add_executable(fluid WIN32 fluid.cxx) + add_executable(fluid WIN32 fluid.cxx fluid.h) endif() @@ -144,7 +145,7 @@ target_link_libraries(fluid PRIVATE fluid-lib) if(WIN32) list(APPEND TARGETS fluid-cmd) - add_executable(fluid-cmd fluid.cxx) + add_executable(fluid-cmd fluid.cxx fluid.h) target_link_libraries(fluid-cmd PRIVATE fluid-lib) set(FLTK_FLUID_EXECUTABLE fltk::fluid-cmd) else() diff --git a/fluid/CodeEditor.cxx b/fluid/CodeEditor.cxx index 2243db2fe..2fffcd8bc 100644 --- a/fluid/CodeEditor.cxx +++ b/fluid/CodeEditor.cxx @@ -2,7 +2,7 @@ // Code editor widget for the Fast Light Tool Kit (FLTK). // Syntax highlighting rewritten by erco@seriss.com 09/15/20. // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -28,13 +28,6 @@ // ---- CodeEditor implementation -/** \class CodeEditor - A widget derived from Fl_Text_Editor that implements C++ code highlighting. - - CodeEditor is used in Fluid whenever the user can edit C++ source - code or header text. - */ - /** Lookup table for all supported styles. Every table entry describes a rendering style for the corresponding text. @@ -263,14 +256,6 @@ void CodeEditor::textsize(Fl_Fontsize s) { // ---- CodeViewer implementation -/** \class CodeViewer - A widget derived from CodeEditor with highlighting for code blocks. - - This widget is used by the SourceView system to show the design's - source and header code. The secondary highlighting show the text - part that corresponds to the selected widget(s). - */ - /** Create a CodeViewer widget. \param[in] X, Y, W, H position and size of the widget diff --git a/fluid/CodeEditor.h b/fluid/CodeEditor.h index 50908ebe5..9886705aa 100644 --- a/fluid/CodeEditor.h +++ b/fluid/CodeEditor.h @@ -2,7 +2,7 @@ // Code editor widget for the Fast Light Tool Kit (FLTK). // Syntax highlighting rewritten by erco@seriss.com 09/15/20. // -// Copyright 1998-2022 by Bill Spitzak and others. +// Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -35,6 +35,12 @@ // ---- CodeEditor declaration +/** + A widget derived from Fl_Text_Editor that implements C++ code highlighting. + + CodeEditor is used in Fluid whenever the user can edit C++ source + code or header text. + */ class CodeEditor : public Fl_Text_Editor { friend class StyleParse; @@ -49,31 +55,51 @@ class CodeEditor : public Fl_Text_Editor { public: CodeEditor(int X, int Y, int W, int H, const char *L=0); ~CodeEditor(); - int top_line() { return get_absolute_top_line_number(); } void textsize(Fl_Fontsize s); + + /// access to protected member get_absolute_top_line_number() + int top_line() { return get_absolute_top_line_number(); } + + /// access to protected member mTopLineNum int scroll_row() { return mTopLineNum; } + + /// access to protected member mHorizOffset int scroll_col() { return mHorizOffset; } }; // ---- CodeViewer declaration +/** + A widget derived from CodeEditor with highlighting for code blocks. + + This widget is used by the SourceView system to show the design's + source and header code. The secondary highlighting show the text + part that corresponds to the selected widget(s). + */ class CodeViewer : public CodeEditor { public: CodeViewer(int X, int Y, int W, int H, const char *L=0); protected: - int handle(int ev) FL_OVERRIDE{ return Fl_Text_Display::handle(ev); } void draw() FL_OVERRIDE; + + /// Limit event handling to viewing, not editing + int handle(int ev) FL_OVERRIDE { return Fl_Text_Display::handle(ev); } }; -// ---- Project File Text Viewe declaration +// ---- Project File Text Viewer declaration +/** + A text viewer with an additional highlighting color scheme. + */ class TextViewer : public Fl_Text_Display { public: TextViewer(int X, int Y, int W, int H, const char *L=0); ~TextViewer(); - int top_line() { return get_absolute_top_line_number(); } void draw() FL_OVERRIDE; + + /// access to protected member get_absolute_top_line_number() + int top_line() { return get_absolute_top_line_number(); } }; #endif // !CodeEditor_h diff --git a/fluid/Fd_Snap_Action.cxx b/fluid/Fd_Snap_Action.cxx index f226ff156..ffd944cd8 100644 --- a/fluid/Fd_Snap_Action.cxx +++ b/fluid/Fd_Snap_Action.cxx @@ -30,7 +30,7 @@ // TODO: warning if the user wants to change builtin layouts // TODO: move panel to global settings panel (move load & save to main pulldown, or to toolbox?) -// INFO: how about a small tool box for quick preset selection and disabeling of individual snaps? +// INFO: how about a small tool box for quick preset selection and disabling of individual snaps? void select_layout_suite_cb(Fl_Widget *, void *user_data); diff --git a/fluid/Fd_Snap_Action.h b/fluid/Fd_Snap_Action.h index 413e340f2..5b3731087 100644 --- a/fluid/Fd_Snap_Action.h +++ b/fluid/Fd_Snap_Action.h @@ -88,7 +88,7 @@ public: char *name_; ///< name of the suite char *menu_label; ///< label text used in pulldown menu Fd_Layout_Preset *layout[3]; ///< presets for application, dialog, and toolbox windows - Fd_Tool_Store storage_; ///< storage location (see FD_STORE_INTERNAL, etc.) + Fd_Tool_Store storage_; ///< storage location (see FD_STORE_INTERNAL, etc.) void write(Fl_Preferences &prefs); void read(Fl_Preferences &prefs); void write(Fd_Project_Writer*); diff --git a/fluid/Fl_Button_Type.h b/fluid/Fl_Button_Type.h index c731ce7e7..3eb4a3d1d 100644 --- a/fluid/Fl_Button_Type.h +++ b/fluid/Fl_Button_Type.h @@ -38,7 +38,6 @@ public: void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; - }; extern Fl_Button_Type Fl_Button_type; diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx index ce6493911..f7a7f30d8 100644 --- a/fluid/Fl_Function_Type.cxx +++ b/fluid/Fl_Function_Type.cxx @@ -162,7 +162,7 @@ const char *_c_check(const char * & c, int type) { \note This function checks every conceivable line of code, which is not always wanted. It can't differentiate characters in comments, and the user may well intend to leave a curly bracket open - (i.e. namesapece { ... } ). We should make this option user selectable. + (i.e. namespace { ... } ). We should make this option user selectable. */ const char *c_check(const char *c, int type) { return _c_check(c,type); @@ -779,7 +779,7 @@ void Fl_CodeBlock_Type::write_properties(Fd_Project_Writer &f) { } /** - Read the node specifc properties. + Read the node specific properties. */ void Fl_CodeBlock_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"after")) { @@ -1441,7 +1441,7 @@ int Fl_DeclBlock_Type::is_public() const {return public_;} /** Create a new declaration block. \param[in] strategy add after current or as last child - \return new Declaration Blocknode + \return new Declaration Block node */ Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx index ebc7a4653..b61a01031 100644 --- a/fluid/Fl_Menu_Type.cxx +++ b/fluid/Fl_Menu_Type.cxx @@ -381,14 +381,14 @@ void Fl_Menu_Item_Type::write_item(Fd_Code_Writer& f) { f.write_c(" {"); if (label() && label()[0]) switch (g_project.i18n_type) { - case 1: + case FD_I18N_GNU: // we will call i18n when the menu is instantiated for the first time f.write_c("%s(", g_project.i18n_gnu_static_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; - case 2: - // fall through: strings can't be translated before a catalog is choosen + case FD_I18N_POSIX: + // fall through: strings can't be translated before a catalog is chosen default: f.write_cstring(label()); } @@ -486,15 +486,16 @@ void Fl_Menu_Item_Type::write_code1(Fd_Code_Writer& f) { f.write_c("%sml->labela = (char*)", f.indent()); image->write_inline(f); f.write_c(";\n"); - if (g_project.i18n_type==0) { + if (g_project.i18n_type==FD_I18N_NONE) { f.write_c("%sml->labelb = o->label();\n", f.indent()); - } else if (g_project.i18n_type==1) { + } else if (g_project.i18n_type==FD_I18N_GNU) { f.write_c("%sml->labelb = %s(o->label());\n", f.indent(), g_project.i18n_gnu_function.c_str()); - } else if (g_project.i18n_type==2) { + } else if (g_project.i18n_type==FD_I18N_POSIX) { f.write_c("%sml->labelb = catgets(%s,%s,i+%d,o->label());\n", - f.indent(), g_project.i18n_pos_file[0] ? g_project.i18n_pos_file.c_str() : "_catalog", - g_project.i18n_pos_set.c_str(), msgnum()); + f.indent(), + g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), + g_project.i18n_pos_set.c_str(), msgnum()); } f.write_c("%sml->typea = FL_IMAGE_LABEL;\n", f.indent()); f.write_c("%sml->typeb = FL_NORMAL_LABEL;\n", f.indent()); @@ -510,13 +511,14 @@ void Fl_Menu_Item_Type::write_code1(Fd_Code_Writer& f) { } else if ( t==FL_NORMAL_LABEL || t==FL_SHADOW_LABEL || t==FL_ENGRAVED_LABEL || t==FL_EMBOSSED_LABEL) { start_menu_initialiser(f, menuItemInitialized, mname, i); - if (g_project.i18n_type==1) { + if (g_project.i18n_type==FD_I18N_GNU) { f.write_c("%so->label(%s(o->label()));\n", f.indent(), g_project.i18n_gnu_function.c_str()); - } else if (g_project.i18n_type==2) { + } else if (g_project.i18n_type==FD_I18N_POSIX) { f.write_c("%so->label(catgets(%s,%s,i+%d,o->label()));\n", - f.indent(), g_project.i18n_pos_file[0] ? g_project.i18n_pos_file.c_str() : "_catalog", - g_project.i18n_pos_set.c_str(), msgnum()); + f.indent(), + g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), + g_project.i18n_pos_set.c_str(), msgnum()); } } } diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h index d96f4db99..39a9bb30b 100644 --- a/fluid/Fl_Type.h +++ b/fluid/Fl_Type.h @@ -1,7 +1,7 @@ // // Widget type header file for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -130,7 +130,7 @@ public: // things that should not be public: Fl_Type *parent; /** This type is rendered "selected" in the tree browser. */ char new_selected; // browser highlight - /** Backup storage for selection if an error accured during some operation + /** Backup storage for selection if an error occurred during some operation (see `haderror`). It seems that this is often confused with new_selected which seems to hold the true and visible selection state. */ char selected; // copied here by selection_changed() @@ -225,9 +225,9 @@ public: void write_comment_inline_c(Fd_Code_Writer& f, const char *ind=0L); // write the commentary text // live mode - virtual Fl_Widget *enter_live_mode(int top=0); // build wdgets needed for live mode + virtual Fl_Widget *enter_live_mode(int top=0); // build widgets needed for live mode virtual void leave_live_mode(); // free allocated resources - virtual void copy_properties(); // copy properties from this type into a potetial live object + virtual void copy_properties(); // copy properties from this type into a potential live object // get message number for I18N int msgnum(); diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx index ac93aeeff..d223fba86 100644 --- a/fluid/Fl_Widget_Type.cxx +++ b/fluid/Fl_Widget_Type.cxx @@ -2997,17 +2997,18 @@ void Fl_Widget_Type::write_code1(Fd_Code_Writer& f) { if (label() && *label()) { f.write_c(", "); switch (g_project.i18n_type) { - case 0 : /* None */ + case FD_I18N_NONE : /* None */ f.write_cstring(label()); break; - case 1 : /* GNU gettext */ + case FD_I18N_GNU : /* GNU gettext */ f.write_c("%s(", g_project.i18n_gnu_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; - case 2 : /* POSIX catgets */ - f.write_c("catgets(%s,%s,%d,", g_project.i18n_pos_file[0] ? g_project.i18n_pos_file.c_str() : "_catalog", - g_project.i18n_pos_set.c_str(), msgnum()); + case FD_I18N_POSIX : /* POSIX catgets */ + f.write_c("catgets(%s,%s,%d,", + g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), + g_project.i18n_pos_set.c_str(), msgnum()); f.write_cstring(label()); f.write_c(")"); break; @@ -3070,17 +3071,19 @@ void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) { if (tooltip() && *tooltip()) { f.write_c("%s%s->tooltip(",f.indent(), var); switch (g_project.i18n_type) { - case 0 : /* None */ + case FD_I18N_NONE : /* None */ f.write_cstring(tooltip()); break; - case 1 : /* GNU gettext */ + case FD_I18N_GNU : /* GNU gettext */ f.write_c("%s(", g_project.i18n_gnu_function.c_str()); f.write_cstring(tooltip()); f.write_c(")"); break; - case 2 : /* POSIX catgets */ - f.write_c("catgets(%s,%s,%d,", g_project.i18n_pos_file[0] ? g_project.i18n_pos_file.c_str() : "_catalog", - g_project.i18n_pos_set.c_str(), msgnum() + 1); + case FD_I18N_POSIX : /* POSIX catgets */ + f.write_c("catgets(%s,%s,%d,", + g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), + g_project.i18n_pos_set.c_str(), + msgnum() + 1); f.write_cstring(tooltip()); f.write_c(")"); break; diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h index bcbafe4a1..b1773a501 100644 --- a/fluid/Fl_Widget_Type.h +++ b/fluid/Fl_Widget_Type.h @@ -57,7 +57,7 @@ protected: /// This variable is set for visible windows in batch mode. /// We can't open a window in batch mode, even if we want the "visible" flags /// set, so we need a second place to store this information while also - /// disabeling the output of the "hide" property by the Widget Type. + /// disabling the output of the "hide" property by the Widget Type. uchar override_visible_; void write_static(Fd_Code_Writer& f) FL_OVERRIDE; diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx index db9ec34ba..bc848ed75 100644 --- a/fluid/Fl_Window_Type.cxx +++ b/fluid/Fl_Window_Type.cxx @@ -73,19 +73,19 @@ void i18n_type_cb(Fl_Choice *c, void *v) { c->value(g_project.i18n_type); } else { undo_checkpoint(); - g_project.i18n_type = c->value(); + g_project.i18n_type = static_cast(c->value()); set_modflag(1); } switch (g_project.i18n_type) { - case 0 : /* None */ + case FD_I18N_NONE : /* None */ i18n_gnu_group->hide(); i18n_posix_group->hide(); break; - case 1 : /* GNU gettext */ + case FD_I18N_GNU : /* GNU gettext */ i18n_gnu_group->show(); i18n_posix_group->hide(); break; - case 2 : /* POSIX cat */ + case FD_I18N_POSIX : /* POSIX cat */ i18n_gnu_group->hide(); i18n_posix_group->show(); break; diff --git a/fluid/Fl_Window_Type.h b/fluid/Fl_Window_Type.h index 56abd630f..779c7b787 100644 --- a/fluid/Fl_Window_Type.h +++ b/fluid/Fl_Window_Type.h @@ -1,5 +1,5 @@ // -// Widget type header file for the Fast Light Tool Kit (FLTK). +// Window type header file for the Fast Light Tool Kit (FLTK). // // Type for creating all subclasses of Fl_Widget // This should have the widget pointer in it, but it is still in the diff --git a/fluid/code.cxx b/fluid/code.cxx index d220ab712..eef2aac47 100644 --- a/fluid/code.cxx +++ b/fluid/code.cxx @@ -94,7 +94,7 @@ int write_strings(const Fl_String &filename) { if (!fp) return 1; switch (g_project.i18n_type) { - case 0 : /* None, just put static text out */ + case FD_I18N_NONE : /* None, just put static text out */ fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); for (p = Fl_Type::first; p; p = p->next) { @@ -113,7 +113,7 @@ int write_strings(const Fl_String &filename) { } } break; - case 1 : /* GNU gettext, put a .po file out */ + case FD_I18N_GNU : /* GNU gettext, put a .po file out */ fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); for (p = Fl_Type::first; p; p = p->next) { @@ -142,7 +142,7 @@ int write_strings(const Fl_String &filename) { } } break; - case 2 : /* POSIX catgets, put a .msg file out */ + case FD_I18N_POSIX : /* POSIX catgets, put a .msg file out */ fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); fprintf(fp, "$set %s\n", g_project.i18n_pos_set.c_str()); @@ -844,7 +844,7 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview) } } Fl_String loc_include, loc_conditional; - if (g_project.i18n_type==1) { + if (g_project.i18n_type==FD_I18N_GNU) { loc_include = g_project.i18n_gnu_include; loc_conditional = g_project.i18n_gnu_conditional; } else { @@ -861,7 +861,7 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview) write_c("#%sinclude \"%s\"\n", indent(), loc_include.c_str()); else write_c("#%sinclude %s\n", indent(), loc_include.c_str()); - if (g_project.i18n_type == 2) { + if (g_project.i18n_type == FD_I18N_POSIX) { if (!g_project.i18n_pos_file.empty()) { write_c("extern nl_catd %s;\n", g_project.i18n_pos_file.c_str()); } else { @@ -873,14 +873,14 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview) } if (conditional) { write_c("#else\n"); - if (g_project.i18n_type == 1) { + if (g_project.i18n_type == FD_I18N_GNU) { if (!g_project.i18n_gnu_function.empty()) { write_c("#%sifndef %s\n", indent(), g_project.i18n_gnu_function.c_str()); write_c("#%sdefine %s(text) text\n", indent_plus(1), g_project.i18n_gnu_function.c_str()); write_c("#%sendif\n", indent()); } } - if (g_project.i18n_type == 2) { + if (g_project.i18n_type == FD_I18N_POSIX) { write_c("#%sifndef catgets\n", indent()); write_c("#%sdefine catgets(catalog, set, msgid, text) text\n", indent_plus(1)); write_c("#%sendif\n", indent()); @@ -888,7 +888,7 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview) indentation--; write_c("#endif\n"); } - if (g_project.i18n_type == 1 && g_project.i18n_gnu_static_function[0]) { + if (g_project.i18n_type == FD_I18N_GNU && g_project.i18n_gnu_static_function[0]) { write_c("#ifndef %s\n", g_project.i18n_gnu_static_function.c_str()); write_c("#%sdefine %s(text) text\n", indent_plus(1), g_project.i18n_gnu_static_function.c_str()); write_c("#endif\n"); diff --git a/fluid/file.cxx b/fluid/file.cxx index b20191291..a054a34cb 100644 --- a/fluid/file.cxx +++ b/fluid/file.cxx @@ -283,7 +283,7 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate goto CONTINUE; } if (!strcmp(c,"i18n_type")) { - g_project.i18n_type = atoi(read_word()); + g_project.i18n_type = static_cast(atoi(read_word())); goto CONTINUE; } if (!strcmp(c,"i18n_gnu_function")) { @@ -303,16 +303,16 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate goto CONTINUE; } if (!strcmp(c,"i18n_include")) { - if (g_project.i18n_type == 1) + if (g_project.i18n_type == FD_I18N_GNU) g_project.i18n_gnu_include = read_word(); - else if (g_project.i18n_type == 2) + 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 == 1) + if (g_project.i18n_type == FD_I18N_GNU) g_project.i18n_gnu_conditional = read_word(); - else if (g_project.i18n_type == 2) + else if (g_project.i18n_type == FD_I18N_POSIX) g_project.i18n_pos_conditional = read_word(); goto CONTINUE; } @@ -847,13 +847,15 @@ int Fd_Project_Writer::write_project(const char *filename, int selected_only, bo if (g_project.i18n_type) { write_string("\ni18n_type %d", g_project.i18n_type); switch (g_project.i18n_type) { - case 1 : /* GNU gettext */ + 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 2 : /* POSIX catgets */ + 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()) { diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx index 3b05b5708..42fe3d218 100644 --- a/fluid/fluid.cxx +++ b/fluid/fluid.cxx @@ -1,7 +1,7 @@ // // FLUID main entry for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -67,10 +67,13 @@ extern "C" // Globals.. // -/// Fluid-wide help dialog. -static Fl_Help_Dialog *help_dialog = 0; +/// 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. @@ -115,10 +118,10 @@ int reading_file = 0; // File history info... /// Stores the absolute filename of the last 10 design files, saved in app preferences. -char absolute_history[10][FL_PATH_MAX]; +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]; +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; @@ -143,7 +146,7 @@ Fl_Menu_Item *restricted_item = NULL; //////////////////////////////////////////////////////////////// -/// Filename of the current .fl design file +/// 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. @@ -172,105 +175,23 @@ int compile_strings = 0; // fluid -cs /// 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 override settings in the project file +/// command line arguments that overrides the generate code file extension or name Fl_String g_code_filename_arg; + +/// command line arguments that overrides the generate header file extension or name Fl_String g_header_filename_arg; + +/// current directory path at application launch Fl_String g_launch_path; +/// path to store temporary files during app run +/// \see tmpdir_create_called Fl_String tmpdir_path; + +/// true if the temporary file path was already created +/// \see tmpdir_path bool tmpdir_create_called = false; -/** \var int Fluid_Project::header_file_set - If set, command line overrides header file name in .fl file. - */ - -/** \var int Fluid_Project::code_file_set - If set, command line overrides source code file name in .fl file. - */ - -/** \var int Fluid_Project::header_file_name - Hold the default extension for header files, or the entire filename if set via command line. - */ - -/** \var int Fluid_Project::code_file_name - Hold the default extension for source code files, or the entire filename if set via command line. - */ - -/** \var int Fluid_Project::i18n_type - Saved in the .fl design file. - \todo document me - */ - -/** \var int Fluid_Project::i18n_gnu_include - Include file for GNU i18n, writes an #include statement into the - source file. - - This is usually `` or `"gettext.h"` for GNU gettext. - - Fluid accepts filenames in quotes or in \< and \>. If neither is found, - double quotes are added. - If this value is empty, no include statement will be generated. - - Saved in the .fl design file if GNU i18n is selected. - */ - -/** \var int Fluid_Project::i18n_pos_include - Include file for Posix i18n, write a #include statement into the - source file. - - This is usually `` for Posix catgets. - - Fluid accepts filenames in quotes or in \< and \>. If neither is found, - double quotes are added. - If this value is empty, no include statement will be generated. - - Saved in the .fl design file. - */ - -/** \var int Fluid_Project::i18n_gnu_conditional - Saved in the .fl design file. - \todo document me - */ - -/** \var int Fluid_Project::i18n_pos_conditional - Saved in the .fl design file. - \todo document me - */ - -/** \var int Fluid_Project::i18n_gnu_function - For the gettext/intl.h options, this is the function that translates text - at runtime. - - This is usually "gettext" or "_". - This should not be empty. - Saved in the .fl design file. - */ - -/** \var int Fluid_Project::i18n_gnu_static_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_". - This should not be empty. - Fluid will translate static text (usually in menu items) later when used - for the first time. - - Saved in the .fl design file. - */ - -/** \var int Fluid_Project::i18n_pos_file - Saved in the .fl design file. - \todo document me - */ - -/** \var int Fluid_Project::i18n_pos_set - Saved in the .fl design file. - \todo document me - */ - -/** \var int Fluid_Project::basename - \todo document me - */ /// Offset in pixels when adding widgets from an .fl file. int pasteoffset = 0; @@ -280,10 +201,14 @@ 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(0), + i18n_type(FD_I18N_NONE), include_H_from_C(1), use_FL_COMMAND(0), utf8_in_src(0), @@ -295,12 +220,19 @@ Fluid_Project::Fluid_Project() : 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 = 0; + i18n_type = FD_I18N_NONE; i18n_gnu_include = ""; i18n_gnu_conditional = ""; @@ -323,6 +255,9 @@ void Fluid_Project::reset() { 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); @@ -330,7 +265,11 @@ void Fluid_Project::update_settings_dialog() { } } -// make sure that a path name ends with a forward slash +/** + 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 Fl_String end_with_slash(const Fl_String &str) { char last = str[str.size()-1]; if (last !='/' && last != '\\') @@ -339,7 +278,8 @@ static Fl_String end_with_slash(const Fl_String &str) { return str; } -/** Generate a path to a directory for temporary data storage. +/** + Generate a path to a directory for temporary data storage. The path is stored in g_tmpdir. */ static void create_tmpdir() { @@ -396,11 +336,18 @@ static void create_tmpdir() { fl_make_path(path.c_str()); if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; } - if (tmpdir_path.empty()) - fl_alert("Can't create directory for temporary data storage."); + 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. */ +/** + Delete the temporary directory that was created in set_tmpdir. + */ static void delete_tmpdir() { // was a temporary directory created if (!tmpdir_create_called) @@ -421,7 +368,11 @@ static void delete_tmpdir() { // then delete the directory itself if (fl_rmdir(tmpdir_path.c_str()) < 0) { - fl_alert("WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); + 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)); + } } } @@ -429,7 +380,7 @@ static void delete_tmpdir() { Return the path to a temporary directory for this instance of FLUID. Fluid will do its best to clear and delete this directory when exiting. \return the path to the temporary directory, ending in a '/', or and empty - string is no directory could be created. + string if no directory could be created. */ const Fl_String &get_tmpdir() { if (!tmpdir_create_called) @@ -468,7 +419,13 @@ bool confirm_project_clear() { // ---- extern Fl_Window *the_panel; -// make sure that a currently changed text widgets propagates its contents + +/** + 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(); @@ -476,6 +433,7 @@ void flush_text_widgets() { Fl::focus(old_focus); } } + // ---- /** @@ -814,8 +772,13 @@ void revert_cb(Fl_Widget *,void *) { */ void exit_cb(Fl_Widget *,void *) { if (shell_command_running()) { - fl_alert("Previous shell command still running!"); - return; + 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(); @@ -874,6 +837,8 @@ void exit_cb(Fl_Widget *,void *) { 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. \return false if the operation was canceled */ bool new_project(bool user_must_confirm = true) { @@ -1122,6 +1087,7 @@ void apple_open_cb(const char *c) { /** Get the absolute path of the project file, for example `/Users/matt/dev/`. + \return the path ending in '/' */ Fl_String Fluid_Project::projectfile_path() const { return end_with_slash(fl_filename_absolute(fl_filename_path(filename), g_launch_path)); @@ -1129,6 +1095,7 @@ Fl_String Fluid_Project::projectfile_path() const { /** Get the project file name including extension, for example `test.fl`. + \return the file name without path */ Fl_String Fluid_Project::projectfile_name() const { return fl_filename_name(filename); @@ -1136,6 +1103,7 @@ Fl_String Fluid_Project::projectfile_name() const { /** Get the absolute path of the generated C++ code file, for example `/Users/matt/dev/src/`. + \return the path ending in '/' */ Fl_String Fluid_Project::codefile_path() const { Fl_String path = fl_filename_path(code_file_name); @@ -1147,6 +1115,7 @@ Fl_String Fluid_Project::codefile_path() const { /** Get the generated C++ code file name including extension, for example `test.cxx`. + \return the file name without path */ Fl_String Fluid_Project::codefile_name() const { Fl_String name = fl_filename_name(code_file_name); @@ -1161,6 +1130,7 @@ Fl_String Fluid_Project::codefile_name() const { /** Get the absolute path of the generated C++ header file, for example `/Users/matt/dev/src/`. + \return the path ending in '/' */ Fl_String Fluid_Project::headerfile_path() const { Fl_String path = fl_filename_path(header_file_name); @@ -1172,6 +1142,7 @@ Fl_String Fluid_Project::headerfile_path() const { /** Get the generated C++ header file name including extension, for example `test.cxx`. + \return the file name without path */ Fl_String Fluid_Project::headerfile_name() const { Fl_String name = fl_filename_name(header_file_name); @@ -1190,33 +1161,35 @@ Fl_String Fluid_Project::headerfile_name() const { 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 '/' */ Fl_String Fluid_Project::stringsfile_path() const { if (batch_mode) - return end_with_slash(g_launch_path); + 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 */ Fl_String Fluid_Project::stringsfile_name() const { switch (i18n_type) { default: return fl_filename_setext(fl_filename_name(filename), ".txt"); - case 1: return fl_filename_setext(fl_filename_name(filename), ".po"); - case 2: return fl_filename_setext(fl_filename_name(filename), ".msg"); + case FD_I18N_GNU: return fl_filename_setext(fl_filename_name(filename), ".po"); + case FD_I18N_POSIX: return fl_filename_setext(fl_filename_name(filename), ".msg"); } } /** Get the name of the project file without the filename extension. + \return the file name without path or extension */ Fl_String Fluid_Project::basename() const { return fl_filename_setext(fl_filename_name(filename), ""); } - /** Generate the C++ source and header filenames and write those files. @@ -1234,6 +1207,7 @@ Fl_String Fluid_Project::basename() const { 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) @@ -1670,7 +1644,7 @@ static void menu_file_open_history_cb(Fl_Widget *, void *v) { open_project_file( \c New_Menu creates new widgets and is explained in detail in another location. \see New_Menu - \todo This menu need some major modernisation. Menus are too long and their + \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. @@ -1772,6 +1746,8 @@ Fl_Menu_Item Main_Menu[] = { 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 *) { @@ -1860,10 +1836,16 @@ void toggle_widgetbin_cb(Fl_Widget *, void *) { } } +/** + Show or hide the code preview window. + */ void toggle_sourceview_cb(Fl_Double_Window *, void *) { sourceview_toggle_visibility(); } +/** + Show or hide the code preview window, button callback. + */ void toggle_sourceview_b_cb(Fl_Button*, void *) { sourceview_toggle_visibility(); } diff --git a/fluid/fluid.h b/fluid/fluid.h index d305598ac..b71baaeb7 100644 --- a/fluid/fluid.h +++ b/fluid/fluid.h @@ -1,7 +1,7 @@ // // FLUID main entry for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -100,6 +100,18 @@ extern Fl_String g_launch_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(); @@ -117,25 +129,46 @@ public: Fl_String stringsfile_name() const; Fl_String basename() const; - int i18n_type; + /// 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. Fl_String i18n_gnu_include; + // Optional name of a macro for conditional i18n compilation. Fl_String i18n_gnu_conditional; + /// For the gettext/intl.h options, this is the function that translates text + /// at runtime. This is usually "gettext" or "_". Fl_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_". Fl_String i18n_gnu_static_function; + /// Include file for Posix i18n, write a #include statement into the source + /// file. This is usually `` for Posix catgets. Fl_String i18n_pos_include; + // Optional name of a macro for conditional i18n compilation. Fl_String i18n_pos_conditional; + /// Name of the nl_catd database Fl_String i18n_pos_file; + /// Message set ID for the catalog. Fl_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. Fl_String header_file_name; + /// Hold the default extension for source code files, or the entire filename if set via command line. Fl_String code_file_name; };