From 7419c988cd792c462889fa70bb343e1ed029dc6c Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Wed, 13 Nov 2024 00:55:20 +0100 Subject: [PATCH] FLUID: Introducing namespaces, reducing globals --- fluid/ExternalCodeEditor_UNIX.cxx | 26 +-- fluid/ExternalCodeEditor_WIN32.cxx | 40 ++-- fluid/Fl_Function_Type.cxx | 4 +- fluid/Fl_Menu_Type.cxx | 30 +-- fluid/Fl_Type.cxx | 4 +- fluid/Fl_Widget_Type.cxx | 18 +- fluid/Fl_Window_Type.cxx | 2 +- fluid/Fluid_Image.cxx | 4 +- fluid/autodoc.cxx | 2 +- fluid/code.cxx | 63 +++---- fluid/code.h | 7 +- fluid/codeview_panel.cxx | 2 +- fluid/factory.cxx | 18 +- fluid/file.cxx | 102 +++++----- fluid/file.h | 12 +- fluid/fluid.cxx | 287 +++++++++++++++-------------- fluid/fluid.h | 70 +++++-- fluid/shell_command.cxx | 4 +- fluid/widget_panel.cxx | 1 - fluid/widget_panel.fl | 5 +- 20 files changed, 372 insertions(+), 329 deletions(-) diff --git a/fluid/ExternalCodeEditor_UNIX.cxx b/fluid/ExternalCodeEditor_UNIX.cxx index 4f0bea3f97..867778503d 100644 --- a/fluid/ExternalCodeEditor_UNIX.cxx +++ b/fluid/ExternalCodeEditor_UNIX.cxx @@ -68,7 +68,7 @@ ExternalCodeEditor::ExternalCodeEditor() { This also closes the external editor. */ ExternalCodeEditor::~ExternalCodeEditor() { - if ( G_debug ) + if ( Fluid.args.debug ) printf("ExternalCodeEditor() DTOR CALLED (this=%p, pid=%ld)\n", (void*)this, (long)pid_); close_editor(); // close editor, delete tmp file @@ -104,7 +104,7 @@ int ExternalCodeEditor::is_editing() { Wait for editor to close */ void ExternalCodeEditor::close_editor() { - if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pid_)); + if ( Fluid.args.debug ) printf("close_editor() called: pid=%ld\n", long(pid_)); // Wait until editor is closed + reaped while ( is_editing() ) { switch ( reap_editor() ) { @@ -140,7 +140,7 @@ void ExternalCodeEditor::close_editor() { The dtor calls this to ensure no editors remain running when fluid exits. */ void ExternalCodeEditor::kill_editor() { - if ( G_debug ) printf("kill_editor() called: pid=%ld\n", (long)pid_); + if ( Fluid.args.debug ) printf("kill_editor() called: pid=%ld\n", (long)pid_); if ( !is_editing() ) return; // editor not running? return.. kill(pid_, SIGTERM); // kill editor int wcount = 0; @@ -163,7 +163,7 @@ void ExternalCodeEditor::kill_editor() { } continue; case 1: // process reaped (reap_editor() sets pid_ to -1) - if ( G_debug ) + if ( Fluid.args.debug ) printf("*** REAPED KILLED EXTERNAL EDITOR: PID %ld\n", (long)pid_reaped); break; } @@ -238,7 +238,7 @@ int ExternalCodeEditor::remove_tmpfile() { if ( !tmpfile ) return 0; // Filename set? remove (if exists) and zero filename/mtime/size if ( is_file(tmpfile) ) { - if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile); + if ( Fluid.args.debug ) printf("Removing tmpfile '%s'\n", tmpfile); if ( remove(tmpfile) < 0 ) { fl_alert("WARNING: Can't remove() '%s': %s", tmpfile, strerror(errno)); return -1; @@ -267,7 +267,7 @@ const char* ExternalCodeEditor::tmpdir_name() { void ExternalCodeEditor::tmpdir_clear() { const char *tmpdir = tmpdir_name(); if ( is_dir(tmpdir) ) { - if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir); + if ( Fluid.args.debug ) printf("Removing tmpdir '%s'\n", tmpdir); if ( rmdir(tmpdir) < 0 ) { fl_alert("WARNING: Can't rmdir() '%s': %s", tmpdir, strerror(errno)); } @@ -382,7 +382,7 @@ void ExternalCodeEditor::open_alert_pipe() { */ int ExternalCodeEditor::start_editor(const char *editor_cmd, const char *filename) { - if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n", + if ( Fluid.args.debug ) printf("start_editor() cmd='%s', filename='%s'\n", editor_cmd, filename); char cmd[1024]; snprintf(cmd, sizeof(cmd), "%s %s", editor_cmd, filename); @@ -415,7 +415,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd, default: // parent if ( L_editors_open++ == 0 ) // first editor? start timers { start_update_timer(); } - if ( G_debug ) + if ( Fluid.args.debug ) printf("--- EDITOR STARTED: pid_=%ld #open=%d\n", (long)pid_, L_editors_open); break; } @@ -452,7 +452,7 @@ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) { { stop_update_timer(); } break; } - if ( G_debug ) + if ( Fluid.args.debug ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", long(wpid), L_editors_open); return 1; } @@ -491,7 +491,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, filename(), (long)pid_); return 0; case 1: // process reaped, wpid is pid reaped - if ( G_debug ) + if ( Fluid.args.debug ) printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", (long)wpid); break; // fall thru to open new editor instance } @@ -511,7 +511,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, file_mtime_ = sbuf.st_mtime; file_size_ = sbuf.st_size; if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor - if ( G_debug ) printf("Editor failed to start\n"); + if ( Fluid.args.debug ) printf("Editor failed to start\n"); return -1; // errors were shown in dialog } return 0; @@ -522,7 +522,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, */ void ExternalCodeEditor::start_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n"); + if ( Fluid.args.debug ) printf("--- TIMER: STARTING UPDATES\n"); Fl::add_timeout(2.0, L_update_timer_cb); } @@ -531,7 +531,7 @@ void ExternalCodeEditor::start_update_timer() { */ void ExternalCodeEditor::stop_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n"); + if ( Fluid.args.debug ) printf("--- TIMER: STOPPING UPDATES\n"); Fl::remove_timeout(L_update_timer_cb); } diff --git a/fluid/ExternalCodeEditor_WIN32.cxx b/fluid/ExternalCodeEditor_WIN32.cxx index bb7d5791a3..157ebeb991 100644 --- a/fluid/ExternalCodeEditor_WIN32.cxx +++ b/fluid/ExternalCodeEditor_WIN32.cxx @@ -27,8 +27,6 @@ #include // snprintf() #include -extern int G_debug; // defined in fluid.cxx - // Static local data static int L_editors_open = 0; // keep track of #editors open static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer callback @@ -136,7 +134,7 @@ static BOOL CALLBACK terminate_app_enum(HWND hwnd, LPARAM lParam) { GetWindowThreadProcessId(hwnd, &dwID); if (dwID == (DWORD)lParam) { PostMessage(hwnd, WM_CLOSE, 0, 0); - if ( G_debug ) + if ( Fluid.args.debug ) printf("terminate_app_enum() sends WIN_CLOSE to hwnd=%p\n", (void*)hwnd); } return TRUE; @@ -153,12 +151,12 @@ static int terminate_app(DWORD pid, DWORD msecTimeout) { // Wait on handle. If it closes, great. If it times out, use TerminateProcess() int ret = 0; if ( WaitForSingleObject(hProc, msecTimeout) != WAIT_OBJECT_0 ) { - if ( G_debug ) { + if ( Fluid.args.debug ) { printf("WARNING: sent WIN_CLOSE, but timeout after %ld msecs.." "trying TerminateProcess\n", msecTimeout); } if ( TerminateProcess(hProc, 0) == 0 ) { - if ( G_debug ) { + if ( Fluid.args.debug ) { printf("ERROR: TerminateProcess() for pid=%ld failed: %s\n", long(pid), get_ms_errmsg()); } @@ -175,7 +173,7 @@ static int terminate_app(DWORD pid, DWORD msecTimeout) { // [Protected] Wait for editor to close void ExternalCodeEditor::close_editor() { - if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pinfo_.dwProcessId)); + if ( Fluid.args.debug ) printf("close_editor() called: pid=%ld\n", long(pinfo_.dwProcessId)); // Wait until editor is closed + reaped while ( is_editing() ) { switch ( reap_editor() ) { @@ -209,7 +207,7 @@ void ExternalCodeEditor::close_editor() { // The dtor calls this to ensure no editors remain running when fluid exits. // void ExternalCodeEditor::kill_editor() { - if ( G_debug ) + if ( Fluid.args.debug ) printf("kill_editor() called: pid=%ld\n", (long)pinfo_.dwProcessId); if ( !is_editing() ) return; switch ( terminate_app(pinfo_.dwProcessId, 500) ) { // kill editor, wait up to 1/2 sec to die @@ -221,7 +219,7 @@ void ExternalCodeEditor::kill_editor() { case 0: { // success -- process reaped DWORD pid = pinfo_.dwProcessId; // save pid reap_cleanup(); // clears pinfo_ - if ( G_debug ) + if ( Fluid.args.debug ) printf("*** kill_editor() REAP pid=%ld #open=%ld\n", long(pid), long(L_editors_open)); break; @@ -314,18 +312,18 @@ int ExternalCodeEditor::handle_changes(const char **code, int force) { // int ExternalCodeEditor::remove_tmpfile() { const char *tmpfile = filename(); - if ( G_debug ) printf("remove_tmpfile() '%s'\n", tmpfile ? tmpfile : "(empty)"); + if ( Fluid.args.debug ) printf("remove_tmpfile() '%s'\n", tmpfile ? tmpfile : "(empty)"); if ( !tmpfile ) return 0; // Filename set? remove (if exists) and zero filename/mtime/size if ( is_file(tmpfile) ) { - if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile); + if ( Fluid.args.debug ) printf("Removing tmpfile '%s'\n", tmpfile); utf8_to_wchar(tmpfile, wbuf); if (DeleteFileW(wbuf) == 0) { fl_alert("WARNING: Can't DeleteFile() '%s': %s", tmpfile, get_ms_errmsg()); return -1; } } else { - if ( G_debug ) printf("remove_tmpfile(): is_file(%s) failed\n", tmpfile); + if ( Fluid.args.debug ) printf("remove_tmpfile(): is_file(%s) failed\n", tmpfile); } set_filename(0); memset(&file_mtime_, 0, sizeof(file_mtime_)); @@ -347,7 +345,7 @@ const char* ExternalCodeEditor::tmpdir_name() { static char dirname[100]; _snprintf(dirname, sizeof(dirname), "%s.fluid-%ld", tempdir, (long)GetCurrentProcessId()); - if ( G_debug ) printf("tmpdir_name(): '%s'\n", dirname); + if ( Fluid.args.debug ) printf("tmpdir_name(): '%s'\n", dirname); return dirname; } @@ -357,7 +355,7 @@ const char* ExternalCodeEditor::tmpdir_name() { void ExternalCodeEditor::tmpdir_clear() { const char *tmpdir = tmpdir_name(); if ( is_dir(tmpdir) ) { - if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir); + if ( Fluid.args.debug ) printf("Removing tmpdir '%s'\n", tmpdir); utf8_to_wchar(tmpdir, wbuf); if ( RemoveDirectoryW(wbuf) == 0 ) { fl_alert("WARNING: Can't RemoveDirectory() '%s': %s", @@ -458,7 +456,7 @@ static int save_file(const char *filename, // int ExternalCodeEditor::start_editor(const char *editor_cmd, const char *filename) { - if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n", + if ( Fluid.args.debug ) printf("start_editor() cmd='%s', filename='%s'\n", editor_cmd, filename); // Startup info STARTUPINFOW sinfo; @@ -489,7 +487,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd, } if ( L_editors_open++ == 0 ) // first editor? start timers { start_update_timer(); } - if ( G_debug ) + if ( Fluid.args.debug ) printf("--- EDITOR STARTED: pid_=%ld #open=%d\n", (long)pinfo_.dwProcessId, L_editors_open); return 0; @@ -533,7 +531,7 @@ int ExternalCodeEditor::reap_editor(DWORD *pid_reaped) { DWORD wpid = pinfo_.dwProcessId; // save pid reap_cleanup(); // clears pinfo_ if ( pid_reaped ) *pid_reaped = wpid; // return pid to caller - if ( G_debug ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", + if ( Fluid.args.debug ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", long(wpid), L_editors_open); return 1; } @@ -578,7 +576,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, filename(), long(pinfo_.dwProcessId)); return 0; case 1: // process reaped, wpid is pid reaped - if ( G_debug ) + if ( Fluid.args.debug ) printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", long(wpid)); break; // fall thru to open new editor instance } @@ -591,12 +589,12 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, return -1; // errors were shown in dialog } if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor - if ( G_debug ) printf("Editor failed to start\n"); + if ( Fluid.args.debug ) printf("Editor failed to start\n"); return -1; // errors were shown in dialog } // New editor opened -- start update timer (if not already) if ( L_update_timer_cb && !Fl::has_timeout(L_update_timer_cb) ) { - if ( G_debug ) printf("--- Editor opened: STARTING UPDATE TIMER\n"); + if ( Fluid.args.debug ) printf("--- Editor opened: STARTING UPDATE TIMER\n"); Fl::add_timeout(2.0, L_update_timer_cb); } return 0; @@ -605,14 +603,14 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, // [Public/Static] Start update timer void ExternalCodeEditor::start_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n"); + if ( Fluid.args.debug ) printf("--- TIMER: STARTING UPDATES\n"); Fl::add_timeout(2.0, L_update_timer_cb); } // [Public/Static] Stop update timer void ExternalCodeEditor::stop_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n"); + if ( Fluid.args.debug ) printf("--- TIMER: STOPPING UPDATES\n"); Fl::remove_timeout(L_update_timer_cb); } diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx index f490c9e115..fc12d3b1aa 100644 --- a/fluid/Fl_Function_Type.cxx +++ b/fluid/Fl_Function_Type.cxx @@ -1420,9 +1420,9 @@ void Fl_Data_Type::write_code1(Fd_Code_Writer& f) { } } // if we are in interactive mode, we pop up a warning dialog - // giving the error: (batch_mode && !write_codeview) ??? + // giving the error: (Fluid.batch_mode && !write_codeview) ??? if (message && !f.write_codeview) { - if (batch_mode) + if (Fluid.batch_mode) fprintf(stderr, "FLUID ERROR: %s %s\n", message, fn); else fl_alert("%s\n%s\n", message, fn); diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx index 50deffaa31..bcfde9ae0c 100644 --- a/fluid/Fl_Menu_Type.cxx +++ b/fluid/Fl_Menu_Type.cxx @@ -482,10 +482,10 @@ void Fl_Menu_Item_Type::write_item(Fd_Code_Writer& f) { write_comment_inline_c(f, " "); f.write_c(" {"); if (label() && label()[0]) - switch (g_project.i18n_type) { + switch (f.project().i18n_type) { case Fd_I18n_Type::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_c("%s(", f.project().i18n_gnu_static_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; @@ -499,7 +499,7 @@ void Fl_Menu_Item_Type::write_item(Fd_Code_Writer& f) { if (((Fl_Button*)o)->shortcut()) { int s = ((Fl_Button*)o)->shortcut(); f.write_c(", "); - if (g_project.use_FL_COMMAND) { + if (f.project().use_FL_COMMAND) { if (s & FL_CTRL) { f.write_c("FL_CONTROL|"); s &= ~FL_CTRL; } if (s & FL_META) { f.write_c("FL_COMMAND|"); s &= ~FL_META; } } else { @@ -588,16 +588,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==Fd_I18n_Type::NONE) { + if (f.project().i18n_type==Fd_I18n_Type::NONE) { f.write_c("%sml->labelb = o->label();\n", f.indent()); - } else if (g_project.i18n_type==Fd_I18n_Type::GNU) { + } else if (f.project().i18n_type==Fd_I18n_Type::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==Fd_I18n_Type::POSIX) { + f.indent(), f.project().i18n_gnu_function.c_str()); + } else if (f.project().i18n_type==Fd_I18n_Type::POSIX) { f.write_c("%sml->labelb = catgets(%s,%s,i+%d,o->label());\n", 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.project().i18n_pos_file.empty() ? "_catalog" : f.project().i18n_pos_file.c_str(), + f.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()); @@ -606,21 +606,21 @@ void Fl_Menu_Item_Type::write_code1(Fd_Code_Writer& f) { image->write_code(f, 0, "o"); } } - if ( (g_project.i18n_type!=Fd_I18n_Type::NONE) && label() && label()[0]) { + if ( (f.project().i18n_type!=Fd_I18n_Type::NONE) && label() && label()[0]) { Fl_Labeltype t = o->labeltype(); if (image) { // label was already copied a few lines up } 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==Fd_I18n_Type::GNU) { + if (f.project().i18n_type==Fd_I18n_Type::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==Fd_I18n_Type::POSIX) { + f.indent(), f.project().i18n_gnu_function.c_str()); + } else if (f.project().i18n_type==Fd_I18n_Type::POSIX) { f.write_c("%so->label(catgets(%s,%s,i+%d,o->label()));\n", 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.project().i18n_pos_file.empty() ? "_catalog" : f.project().i18n_pos_file.c_str(), + f.project().i18n_pos_set.c_str(), msgnum()); } } } diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx index 26db4584e4..cbc7f57c4b 100644 --- a/fluid/Fl_Type.cxx +++ b/fluid/Fl_Type.cxx @@ -382,7 +382,7 @@ static void delete_children(Fl_Type *p) { /** Delete all nodes in the Types tree and reset project settings, or delete selected nodes. Also calls the browser to refresh. - \note Please refactor this into two separate methods of Fluid_Project. + \note Please refactor this into two separate methods of FLUID::Project. \param[in] selected_only if set, delete only the selected widgets and don't reset the project. */ @@ -908,7 +908,7 @@ void Fl_Type::write(Fd_Project_Writer &f) { void Fl_Type::write_properties(Fd_Project_Writer &f) { // repeat this for each attribute: - if (g_project.write_mergeback_data && uid_) { + if (f.project().write_mergeback_data && uid_) { f.write_word("uid"); f.write_string("%04x", uid_); } diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx index 05c1b6e6aa..5e3a3c6731 100644 --- a/fluid/Fl_Widget_Type.cxx +++ b/fluid/Fl_Widget_Type.cxx @@ -3095,19 +3095,19 @@ void Fl_Widget_Type::write_code1(Fd_Code_Writer& f) { } if (label() && *label()) { f.write_c(", "); - switch (g_project.i18n_type) { + switch (f.project().i18n_type) { case Fd_I18n_Type::NONE : /* None */ f.write_cstring(label()); break; case Fd_I18n_Type::GNU : /* GNU gettext */ - f.write_c("%s(", g_project.i18n_gnu_function.c_str()); + f.write_c("%s(", f.project().i18n_gnu_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; case Fd_I18n_Type::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.project().i18n_pos_file.empty() ? "_catalog" : f.project().i18n_pos_file.c_str(), + f.project().i18n_pos_set.c_str(), msgnum()); f.write_cstring(label()); f.write_c(")"); break; @@ -3169,19 +3169,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) { + switch (f.project().i18n_type) { case Fd_I18n_Type::NONE : /* None */ f.write_cstring(tooltip()); break; case Fd_I18n_Type::GNU : /* GNU gettext */ - f.write_c("%s(", g_project.i18n_gnu_function.c_str()); + f.write_c("%s(", f.project().i18n_gnu_function.c_str()); f.write_cstring(tooltip()); f.write_c(")"); break; case Fd_I18n_Type::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(), + f.project().i18n_pos_file.empty() ? "_catalog" : f.project().i18n_pos_file.c_str(), + f.project().i18n_pos_set.c_str(), msgnum() + 1); f.write_cstring(tooltip()); f.write_c(")"); @@ -3206,7 +3206,7 @@ void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) { if (shortcut) { int s = shortcut; f.write_c("%s%s->shortcut(", f.indent(), var); - if (g_project.use_FL_COMMAND) { + if (f.project().use_FL_COMMAND) { if (s & FL_CTRL) { f.write_c("FL_CONTROL|"); s &= ~FL_CTRL; } if (s & FL_META) { f.write_c("FL_COMMAND|"); s &= ~FL_META; } } else { diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx index ca3bac6d03..1008a37dd9 100644 --- a/fluid/Fl_Window_Type.cxx +++ b/fluid/Fl_Window_Type.cxx @@ -1322,7 +1322,7 @@ void Fl_Window_Type::read_property(Fd_Project_Reader &f, const char *c) { } else if (!strcmp(c,"non_modal")) { non_modal = 1; } else if (!strcmp(c, "visible")) { - if (batch_mode) // don't actually open any windows in batch mode + if (Fluid.batch_mode) // don't actually open any windows in batch mode override_visible_ = 1; else // in interactive mode, we simply show the window open_(); diff --git a/fluid/Fluid_Image.cxx b/fluid/Fluid_Image.cxx index c57d54c856..41375dadd5 100644 --- a/fluid/Fluid_Image.cxx +++ b/fluid/Fluid_Image.cxx @@ -312,7 +312,7 @@ Fluid_Image* Fluid_Image::find(const char *iname) { enter_project_dir(); FILE *f = fl_fopen(iname,"rb"); if (!f) { - if (batch_mode) + if (Fluid.batch_mode) fprintf(stderr, "Can't open image file:\n%s\n%s",iname,strerror(errno)); else fl_message("Can't open image file:\n%s\n%s",iname,strerror(errno)); @@ -326,7 +326,7 @@ Fluid_Image* Fluid_Image::find(const char *iname) { if (!ret->img || !ret->img->w() || !ret->img->h()) { delete ret; ret = 0; - if (batch_mode) + if (Fluid.batch_mode) fprintf(stderr, "Can't read image file:\n%s\nunrecognized image format",iname); else fl_message("Can't read image file:\n%s\nunrecognized image format",iname); diff --git a/fluid/autodoc.cxx b/fluid/autodoc.cxx index 0f2ea8e4ad..d711443a70 100644 --- a/fluid/autodoc.cxx +++ b/fluid/autodoc.cxx @@ -380,7 +380,7 @@ void run_autodoc(const Fl_String &target_dir) { // Fl::scheme("gtk+"); // Create a silly project that contains all widgets that we want to document - new_project(false); + Fluid.new_project(false); /*Fl_Type *t_func = */ add_new_widget_from_user("Function", kAddAsLastChild, false); Fl_Window_Type *t_win = (Fl_Window_Type*)add_new_widget_from_user("Fl_Window", kAddAsLastChild, false); diff --git a/fluid/code.cxx b/fluid/code.cxx index 6d69f356bb..75050eba21 100644 --- a/fluid/code.cxx +++ b/fluid/code.cxx @@ -462,7 +462,7 @@ void Fd_Code_Writer::write_cstring(const char *s, int length) { break; } // if the UTF-8 option is checked, write unicode characters verbatim - if (g_project.utf8_in_src && (c&0x80)) { + if (project().utf8_in_src && (c&0x80)) { if ((c&0x40)) { // This is the first character in a utf-8 sequence (0b11......). // A line break would be ok here. Do not put linebreak in front of @@ -796,8 +796,8 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { header_file = f; } // Remember the last code file location for MergeBack - if (s && g_project.write_mergeback_data && !to_codeview) { - Fl_String proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); + if (s && project().write_mergeback_data && !to_codeview) { + Fl_String proj_filename = project().projectfile_path() + project().projectfile_name(); int i, n = proj_filename.size(); for (i=0; i"); } - if (t && g_project.include_H_from_C) { + if (t && project().include_H_from_C) { if (to_codeview) { write_c("#include \"CodeView.h\"\n"); - } else if (g_project.header_file_name[0] == '.' && strchr(g_project.header_file_name.c_str(), '/') == NULL) { + } else if (project().header_file_name[0] == '.' && strchr(project().header_file_name.c_str(), '/') == NULL) { write_c("#include \"%s\"\n", fl_filename_name(t)); } else { - write_c("#include \"%s\"\n", g_project.header_file_name.c_str()); + write_c("#include \"%s\"\n", project().header_file_name.c_str()); } } Fl_String loc_include, loc_conditional; - if (g_project.i18n_type==Fd_I18n_Type::GNU) { - loc_include = g_project.i18n_gnu_include; - loc_conditional = g_project.i18n_gnu_conditional; + if (project().i18n_type==Fd_I18n_Type::GNU) { + loc_include = project().i18n_gnu_include; + loc_conditional = project().i18n_gnu_conditional; } else { - loc_include = g_project.i18n_pos_include; - loc_conditional = g_project.i18n_pos_conditional; + loc_include = project().i18n_pos_include; + loc_conditional = project().i18n_pos_conditional; } - if ( (g_project.i18n_type!=Fd_I18n_Type::NONE) && !loc_include.empty()) { + if ( (project().i18n_type!=Fd_I18n_Type::NONE) && !loc_include.empty()) { int conditional = !loc_conditional.empty(); if (conditional) { write_c("#ifdef %s\n", loc_conditional.c_str()); @@ -866,26 +866,26 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { 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 == Fd_I18n_Type::POSIX) { - if (!g_project.i18n_pos_file.empty()) { - write_c("extern nl_catd %s;\n", g_project.i18n_pos_file.c_str()); + if (project().i18n_type == Fd_I18n_Type::POSIX) { + if (!project().i18n_pos_file.empty()) { + write_c("extern nl_catd %s;\n", project().i18n_pos_file.c_str()); } else { write_c("// Initialize I18N stuff now for menus...\n"); write_c("#%sinclude \n", indent()); write_c("static char *_locale = setlocale(LC_MESSAGES, \"\");\n"); - write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n", g_project.basename().c_str()); + write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n", project().basename().c_str()); } } if (conditional) { write_c("#else\n"); - if (g_project.i18n_type == Fd_I18n_Type::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()); + if (project().i18n_type == Fd_I18n_Type::GNU) { + if (!project().i18n_gnu_function.empty()) { + write_c("#%sifndef %s\n", indent(), project().i18n_gnu_function.c_str()); + write_c("#%sdefine %s(text) text\n", indent_plus(1), project().i18n_gnu_function.c_str()); write_c("#%sendif\n", indent()); } } - if (g_project.i18n_type == Fd_I18n_Type::POSIX) { + if (project().i18n_type == Fd_I18n_Type::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()); @@ -893,9 +893,9 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { indentation--; write_c("#endif\n"); } - if (g_project.i18n_type == Fd_I18n_Type::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()); + if (project().i18n_type == Fd_I18n_Type::GNU && project().i18n_gnu_static_function[0]) { + write_c("#ifndef %s\n", project().i18n_gnu_static_function.c_str()); + write_c("#%sdefine %s(text) text\n", indent_plus(1), project().i18n_gnu_static_function.c_str()); write_c("#endif\n"); } } @@ -955,8 +955,9 @@ void Fd_Code_Writer::write_public(int state) { /** Create and initialize a new C++ source code writer. */ -Fd_Code_Writer::Fd_Code_Writer() -: code_file(NULL), +Fd_Code_Writer::Fd_Code_Writer(FLUID::Project &project) +: project_(project), + code_file(NULL), header_file(NULL), id_root(NULL), text_in_header(NULL), @@ -995,7 +996,7 @@ Fd_Code_Writer::~Fd_Code_Writer() \param[in] uid the unique id of the current type */ void Fd_Code_Writer::tag(int type, unsigned short uid) { - if (g_project.write_mergeback_data) + if (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); } @@ -1062,7 +1063,7 @@ int Fd_Code_Writer::crc_printf(const char *format, ...) { \return see fprintf(FILE *, *const char*, ...) */ int Fd_Code_Writer::crc_vprintf(const char *format, va_list args) { - if (g_project.write_mergeback_data) { + if (project().write_mergeback_data) { int n = vsnprintf(block_buffer_, block_buffer_size_, format, args); if (n > block_buffer_size_) { block_buffer_size_ = n + 128; @@ -1083,7 +1084,7 @@ int Fd_Code_Writer::crc_vprintf(const char *format, va_list args) { \return see fputs(const char*, FILE*) */ int Fd_Code_Writer::crc_puts(const char *text) { - if (g_project.write_mergeback_data) { + if (project().write_mergeback_data) { crc_add(text); } return fputs(text, code_file); @@ -1096,7 +1097,7 @@ int Fd_Code_Writer::crc_puts(const char *text) { \return see fputc(int, FILE*) */ int Fd_Code_Writer::crc_putc(int c) { - if (g_project.write_mergeback_data) { + if (project().write_mergeback_data) { uchar uc = (uchar)c; crc_add(&uc, 1); } diff --git a/fluid/code.h b/fluid/code.h index dba552e4d0..db80e4a210 100644 --- a/fluid/code.h +++ b/fluid/code.h @@ -23,6 +23,8 @@ #include #include +#include "fluid.h" + class Fl_Type; struct Fd_Identifier_Tree; struct Fd_Text_Tree; @@ -34,6 +36,8 @@ int write_strings(const Fl_String &filename); class Fd_Code_Writer { protected: + /// Reference to the project that will be written. + FLUID::Project &project_; /// file pointer for the C++ code file FILE *code_file; /// file pointer for the C++ header file @@ -77,8 +81,9 @@ class Fd_Code_Writer int varused; public: - Fd_Code_Writer(); + Fd_Code_Writer(FLUID::Project &project); ~Fd_Code_Writer(); + FLUID::Project &project() { return project_; } const char* unique_id(void* o, const char*, const char*, const char*); /// Increment source code indentation level. void indent_more() { indentation++; } diff --git a/fluid/codeview_panel.cxx b/fluid/codeview_panel.cxx index 69e7be2dd4..53c52f3918 100644 --- a/fluid/codeview_panel.cxx +++ b/fluid/codeview_panel.cxx @@ -188,7 +188,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; + Fd_Code_Writer f { g_project }; // generate files if (f.write_code(cv_source_filename, cv_header_filename, true)) { diff --git a/fluid/factory.cxx b/fluid/factory.cxx index 56077020c4..84838b32e0 100644 --- a/fluid/factory.cxx +++ b/fluid/factory.cxx @@ -132,7 +132,7 @@ class Fl_Browser_Type : public Fl_Browser_Base_Type Fl_Browser* b = new Fl_Browser(x, y, w, h); // Fl_Browser::add calls fl_height(), which requires the X display open. // Avoid this when compiling so it works w/o a display: - if (!batch_mode) { + if (!Fluid.batch_mode) { char buffer[20]; for (int i = 1; i <= 20; i++) { sprintf(buffer,"Browser Line %d",i); @@ -165,7 +165,7 @@ class Fl_Check_Browser_Type : public Fl_Browser_Base_Type Fl_Check_Browser* b = new Fl_Check_Browser(x, y, w, h); // Fl_Check_Browser::add calls fl_height(), which requires the X display open. // Avoid this when compiling so it works w/o a display: - if (!batch_mode) { + if (!Fluid.batch_mode) { char buffer[20]; for (int i = 1; i <= 20; i++) { sprintf(buffer,"Browser Line %d",i); @@ -197,7 +197,7 @@ class Fl_File_Browser_Type : public Fl_Browser_Type const char *alt_type_name() FL_OVERRIDE { return "fltk::FileBrowser"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_File_Browser* b = new Fl_File_Browser(x, y, w, h); - if (!batch_mode) b->load("."); + if (!Fluid.batch_mode) b->load("."); return b; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_File_Browser_Type(); } @@ -231,7 +231,7 @@ class Fl_Tree_Type : public Fl_Widget_Type const char *alt_type_name() FL_OVERRIDE { return "fltk::TreeBrowser"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Tree* b = new Fl_Tree(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { b->add("/A1/B1/C1"); b->add("/A1/B1/C2"); b->add("/A1/B2/C1"); @@ -283,7 +283,7 @@ class Fl_Help_View_Type : public Fl_Widget_Type const char *alt_type_name() FL_OVERRIDE { return "fltk::HelpView"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Help_View *myo = new Fl_Help_View(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { myo->value("

Fl_Help_View Widget

" "

This is a Fl_Help_View widget.

"); } @@ -801,7 +801,7 @@ class Fl_Text_Display_Type : public Fl_Widget_Type const char *alt_type_name() FL_OVERRIDE { return "fltk::TextDisplay"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Text_Display *myo = new Fl_Text_Display(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { Fl_Text_Buffer *b = new Fl_Text_Buffer(); b->text("Lorem ipsum dolor\nsit amet, consetetur\nsadipscing elitr"); myo->buffer(b); @@ -828,7 +828,7 @@ class Fl_Text_Editor_Type : public Fl_Text_Display_Type const char *alt_type_name() FL_OVERRIDE {return "fltk::TextEditor";} Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Text_Editor *myo = new Fl_Text_Editor(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { Fl_Text_Buffer *b = new Fl_Text_Buffer(); b->text("Lorem ipsum dolor\nsit amet, consetetur\nsadipscing elitr"); myo->buffer(b); @@ -898,7 +898,7 @@ class Fl_Terminal_Type : public Fl_Widget_Type const char *alt_type_name() FL_OVERRIDE { return "Fl_Simple_Terminal"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Widget *ret = NULL; - if (batch_mode) { + if (Fluid.batch_mode) { ret = new Fl_Batchmode_Terminal(x, y, w, h); } else { Fl_Terminal_Proxy *term = new Fl_Terminal_Proxy(x, y, w+100, h); @@ -907,7 +907,7 @@ class Fl_Terminal_Type : public Fl_Widget_Type return ret; } int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - if (batch_mode) { + if (Fluid.batch_mode) { Fl_Batchmode_Terminal *myo = (Fl_Batchmode_Terminal*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: diff --git a/fluid/file.cxx b/fluid/file.cxx index c8dc034ccc..6a984bf95f 100644 --- a/fluid/file.cxx +++ b/fluid/file.cxx @@ -62,7 +62,7 @@ int fdesign_flip = 0; \return 0 if the operation failed, 1 if it succeeded */ int read_file(const char *filename, int merge, Strategy strategy) { - Fd_Project_Reader f; + Fd_Project_Reader f { g_project }; return f.read_project(filename, merge, strategy); } @@ -76,7 +76,7 @@ int read_file(const char *filename, int merge, Strategy strategy) { \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; + Fd_Project_Writer out { g_project }; return out.write_project(filename, selected_only, to_codeview); } @@ -114,8 +114,9 @@ void Fd_Project_Reader::expand_buffer(int length) { } /** \brief Construct local project reader. */ -Fd_Project_Reader::Fd_Project_Reader() -: fin(NULL), +Fd_Project_Reader::Fd_Project_Reader(FLUID::Project &project) +: project_(project), + fin(NULL), lineno(0), fname(NULL), buffer(NULL), @@ -268,63 +269,63 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate } if (!strcmp(c,"do_not_include_H_from_C")) { - g_project.include_H_from_C=0; + project().include_H_from_C=0; goto CONTINUE; } if (!strcmp(c,"use_FL_COMMAND")) { - g_project.use_FL_COMMAND=1; + project().use_FL_COMMAND=1; goto CONTINUE; } if (!strcmp(c,"utf8_in_src")) { - g_project.utf8_in_src=1; + project().utf8_in_src=1; goto CONTINUE; } if (!strcmp(c,"avoid_early_includes")) { - g_project.avoid_early_includes=1; + project().avoid_early_includes=1; goto CONTINUE; } if (!strcmp(c,"i18n_type")) { - g_project.i18n_type = static_cast(atoi(read_word())); + project().i18n_type = static_cast(atoi(read_word())); goto CONTINUE; } if (!strcmp(c,"i18n_gnu_function")) { - g_project.i18n_gnu_function = read_word(); + project().i18n_gnu_function = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_gnu_static_function")) { - g_project.i18n_gnu_static_function = read_word(); + project().i18n_gnu_static_function = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_pos_file")) { - g_project.i18n_pos_file = read_word(); + project().i18n_pos_file = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_pos_set")) { - g_project.i18n_pos_set = read_word(); + project().i18n_pos_set = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_include")) { - if (g_project.i18n_type == Fd_I18n_Type::GNU) - g_project.i18n_gnu_include = read_word(); - else if (g_project.i18n_type == Fd_I18n_Type::POSIX) - g_project.i18n_pos_include = read_word(); + if (project().i18n_type == Fd_I18n_Type::GNU) + project().i18n_gnu_include = read_word(); + else if (project().i18n_type == Fd_I18n_Type::POSIX) + project().i18n_pos_include = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_conditional")) { - if (g_project.i18n_type == Fd_I18n_Type::GNU) - g_project.i18n_gnu_conditional = read_word(); - else if (g_project.i18n_type == Fd_I18n_Type::POSIX) - g_project.i18n_pos_conditional = read_word(); + if (project().i18n_type == Fd_I18n_Type::GNU) + project().i18n_gnu_conditional = read_word(); + else if (project().i18n_type == Fd_I18n_Type::POSIX) + 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(); + if (!project().header_file_set) 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(); + if (!project().code_file_set) project().code_file_name = read_word(); else read_word(); goto CONTINUE; } @@ -350,7 +351,7 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate } if (!strcmp(c, "mergeback")) { - g_project.write_mergeback_data = read_int(); + project().write_mergeback_data = read_int(); goto CONTINUE; } } @@ -442,7 +443,7 @@ int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy st if (merge) deselect(); else - g_project.reset(); + project().reset(); read_children(Fl_Type::current, merge, strategy); // clear this Fl_Type::current = 0; @@ -464,7 +465,7 @@ int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy st g_shell_config->update_settings_dialog(); } g_layout_list.update_dialogs(); - g_project.update_settings_dialog(); + project().update_settings_dialog(); int ret = close_read(); undo_resume(); return ret; @@ -474,8 +475,8 @@ int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy st 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` + \note Matt: I am not sure why it is done this way. Shouldn't this depend on \c Fluid.batch_mode? + \todo Not happy about this function. Output channel should depend on `Fluid.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. @@ -784,8 +785,9 @@ void Fd_Project_Reader::read_fdesign() { // ---- Fd_Project_Writer ---------------------------------------------- MARK: - /** \brief Construct local project writer. */ -Fd_Project_Writer::Fd_Project_Writer() -: fout(NULL), +Fd_Project_Writer::Fd_Project_Writer(FLUID::Project &project) +: project_(project), + fout(NULL), needspace(0), write_codeview_(false) { @@ -843,45 +845,45 @@ int Fd_Project_Writer::write_project(const char *filename, int selected_only, bo } write_string("# data file for the Fltk User Interface Designer (fluid)\n" "version %.4f",FL_VERSION); - if(!g_project.include_H_from_C) + if(!project().include_H_from_C) write_string("\ndo_not_include_H_from_C"); - if(g_project.use_FL_COMMAND) + if(project().use_FL_COMMAND) write_string("\nuse_FL_COMMAND"); - if (g_project.utf8_in_src) + if (project().utf8_in_src) write_string("\nutf8_in_src"); - if (g_project.avoid_early_includes) + if (project().avoid_early_includes) write_string("\navoid_early_includes"); - if (g_project.i18n_type!=Fd_I18n_Type::NONE) { - write_string("\ni18n_type %d", g_project.i18n_type); - switch (g_project.i18n_type) { + if (project().i18n_type!=Fd_I18n_Type::NONE) { + write_string("\ni18n_type %d", project().i18n_type); + switch (project().i18n_type) { case Fd_I18n_Type::NONE: break; case Fd_I18n_Type::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()); + write_string("\ni18n_include"); write_word(project().i18n_gnu_include.c_str()); + write_string("\ni18n_conditional"); write_word(project().i18n_gnu_conditional.c_str()); + write_string("\ni18n_gnu_function"); write_word(project().i18n_gnu_function.c_str()); + write_string("\ni18n_gnu_static_function"); write_word(project().i18n_gnu_static_function.c_str()); break; case Fd_I18n_Type::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_include"); write_word(project().i18n_pos_include.c_str()); + write_string("\ni18n_conditional"); write_word(project().i18n_pos_conditional.c_str()); + if (!project().i18n_pos_file.empty()) { write_string("\ni18n_pos_file"); - write_word(g_project.i18n_pos_file.c_str()); + write_word(project().i18n_pos_file.c_str()); } - write_string("\ni18n_pos_set"); write_word(g_project.i18n_pos_set.c_str()); + write_string("\ni18n_pos_set"); write_word(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()); + write_string("\nheader_name"); write_word(project().header_file_name.c_str()); + write_string("\ncode_name"); write_word(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); + if (project().write_mergeback_data) + write_string("\nmergeback %d", project().write_mergeback_data); } for (Fl_Type *p = Fl_Type::first; p;) { diff --git a/fluid/file.h b/fluid/file.h index 71ee543a4f..0888b45ca2 100644 --- a/fluid/file.h +++ b/fluid/file.h @@ -19,6 +19,8 @@ #include "Fl_Type.h" +#include "fluid.h" + #include class Fl_Type; @@ -31,6 +33,8 @@ int write_file(const char *, int selected_only = 0, bool to_codeview = false); class Fd_Project_Reader { protected: + /// Reference to the project that will be read. + FLUID::Project &project_; /// Project input file FILE *fin; /// Number of most recently read line @@ -51,8 +55,9 @@ class Fd_Project_Reader double read_version; public: - Fd_Project_Reader(); + Fd_Project_Reader(FLUID::Project &project); ~Fd_Project_Reader(); + FLUID::Project &project() const { return project_; } int open_read(const char *s); int close_read(); const char *filename_name(); @@ -69,6 +74,8 @@ class Fd_Project_Reader class Fd_Project_Writer { protected: + /// Reference to the project that will be written. + FLUID::Project &project_; // 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 @@ -77,8 +84,9 @@ class Fd_Project_Writer bool write_codeview_; public: - Fd_Project_Writer(); + Fd_Project_Writer(FLUID::Project &project); ~Fd_Project_Writer(); + FLUID::Project &project() const { return project_; } int open_write(const char *s); int close_write(); int write_project(const char *filename, int selected_only, bool codeview); diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx index de47b79a78..7639be7c3b 100644 --- a/fluid/fluid.cxx +++ b/fluid/fluid.cxx @@ -99,9 +99,6 @@ 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]; @@ -151,38 +148,10 @@ 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 Fl_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 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 -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; - -/// if set, generate images for automatic documentation in this directory -Fl_String g_autodoc_path; - /// path to store temporary files during app run /// \see tmpdir_create_called Fl_String tmpdir_path; @@ -201,12 +170,15 @@ static int ipasteoffset = 0; // ---- project settings /// The current project, possibly a new, empty roject -Fluid_Project g_project; +FLUID::Project g_project; + +/// Global reference to FLUID application +FLUID::App Fluid; /** Reset all project setting to create a new empty project. */ -void Fluid_Project::reset() { +void FLUID::Project::reset() { ::delete_all(); i18n_type = Fd_I18n_Type::NONE; @@ -234,7 +206,7 @@ void Fluid_Project::reset() { /** Tell the project and i18n tab of the settings dialog to refresh themselves. */ -void Fluid_Project::update_settings_dialog() { +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); @@ -313,7 +285,7 @@ static void create_tmpdir() { if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; } if (tmpdir_path.empty()) { - if (batch_mode) { + if (Fluid.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."); @@ -344,7 +316,7 @@ static void delete_tmpdir() { // then delete the directory itself if (fl_rmdir(tmpdir_path.c_str()) < 0) { - if (batch_mode) { + if (Fluid.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)); @@ -386,7 +358,7 @@ bool confirm_project_clear() { case 0 : /* Cancel */ return false; case 1 : /* Save */ - save_cb(NULL, NULL); + FLUID::Callbacks::save(NULL, NULL); if (modflag) return false; // user canceled the "Save As" dialog } return true; @@ -441,8 +413,6 @@ void enter_project_dir() { 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(); // set the current directory to the path of our .fl file Fl_String project_path = fl_filename_path(fl_filename_absolute(filename)); if (fl_chdir(project_path.c_str()) == -1) { @@ -450,7 +420,6 @@ void enter_project_dir() { project_path.c_str(), strerror(errno)); return; } - //fprintf(stderr, "chdir from %s to %s\n", app_work_dir.c_str(), fl_getcwd().c_str()); } /** @@ -466,9 +435,9 @@ void leave_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) { + if (fl_chdir(Fluid.launch_path.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)); + Fluid.launch_path.c_str(), strerror(errno)); } } @@ -543,7 +512,7 @@ static char* cutfname(int which = 0) { */ 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 ( Fluid.args.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; @@ -578,7 +547,7 @@ static void external_editor_timer(void*) { verify with the user. \param[in] v if v is not NULL, or no filename is set, open a filechooser. */ -void save_cb(Fl_Widget *, void *v) { +void FLUID::Callbacks::save(Fl_Widget *, void *v) { flush_text_widgets(); Fl_Native_File_Chooser fnfc; const char *c = filename; @@ -817,22 +786,31 @@ void exit_cb(Fl_Widget *,void *) { user before resetting the project. Default is `true`. \return false if the operation was canceled */ -bool new_project(bool user_must_confirm) { +bool FLUID::App::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(); + project().reset(); set_filename(NULL); set_modflag(0, 0); widget_browser->rebuild(); - g_project.update_settings_dialog(); + project().update_settings_dialog(); // all is clear to continue return true; } +/** + * Return a reference to the current project. + */ +FLUID::Project &FLUID::App::project() +{ + return g_project; +} + + /** Open the template browser and load a new file from templates. @@ -843,7 +821,7 @@ bool new_project(bool user_must_confirm) { */ bool new_project_from_template() { // clear the current project first - if (new_project() == false) + if (Fluid.new_project() == false) return false; // Setup the template panel... @@ -1046,7 +1024,7 @@ bool open_project_file(const Fl_String &filename_arg) { } // clear the project and merge a file by the given name - new_project(false); + Fluid.new_project(false); return merge_project_file(new_filename); } @@ -1065,15 +1043,15 @@ 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)); +Fl_String FLUID::Project::projectfile_path() const { + return end_with_slash(fl_filename_absolute(fl_filename_path(filename), Fluid.launch_path)); } /** Get the project file name including extension, for example `test.fl`. \return the file name without path */ -Fl_String Fluid_Project::projectfile_name() const { +Fl_String FLUID::Project::projectfile_name() const { return fl_filename_name(filename); } @@ -1081,10 +1059,10 @@ 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 FLUID::Project::codefile_path() const { Fl_String path = fl_filename_path(code_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute(path, g_launch_path)); + if (Fluid.batch_mode) + return end_with_slash(fl_filename_absolute(path, Fluid.launch_path)); else return end_with_slash(fl_filename_absolute(path, projectfile_path())); } @@ -1093,7 +1071,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 FLUID::Project::codefile_name() const { Fl_String name = fl_filename_name(code_file_name); if (name.empty()) { return fl_filename_setext(fl_filename_name(filename), ".cxx"); @@ -1108,10 +1086,10 @@ 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 FLUID::Project::headerfile_path() const { Fl_String path = fl_filename_path(header_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute(path, g_launch_path)); + if (Fluid.batch_mode) + return end_with_slash(fl_filename_absolute(path, Fluid.launch_path)); else return end_with_slash(fl_filename_absolute(path, projectfile_path())); } @@ -1120,7 +1098,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 FLUID::Project::headerfile_name() const { Fl_String name = fl_filename_name(header_file_name); if (name.empty()) { return fl_filename_setext(fl_filename_name(filename), ".h"); @@ -1139,9 +1117,9 @@ Fl_String Fluid_Project::headerfile_name() const { batch mode. \return the path ending in '/' */ -Fl_String Fluid_Project::stringsfile_path() const { - if (batch_mode) - return g_launch_path; +Fl_String FLUID::Project::stringsfile_path() const { + if (Fluid.batch_mode) + return Fluid.launch_path; else return projectfile_path(); } @@ -1150,7 +1128,7 @@ Fl_String Fluid_Project::stringsfile_path() const { 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 { +Fl_String FLUID::Project::stringsfile_name() const { switch (i18n_type) { default: return fl_filename_setext(fl_filename_name(filename), ".txt"); case Fd_I18n_Type::GNU: return fl_filename_setext(fl_filename_name(filename), ".po"); @@ -1162,7 +1140,7 @@ Fl_String Fluid_Project::stringsfile_name() const { 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 { +Fl_String FLUID::Project::basename() const { return fl_filename_setext(fl_filename_name(filename), ""); } @@ -1186,29 +1164,29 @@ Fl_String Fluid_Project::basename() const { \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) +int FLUID::Project::write_code_files(bool dont_show_completion_dialog) { // -- handle user interface issues flush_text_widgets(); if (!filename) { - save_cb(0,0); + FLUID::Callbacks::save(0,0); if (!filename) return 1; } // -- generate the file names with absolute paths - Fd_Code_Writer f; + Fd_Code_Writer f { g_project }; Fl_String code_filename = g_project.codefile_path() + g_project.codefile_name(); Fl_String header_filename = g_project.headerfile_path() + g_project.headerfile_name(); // -- write the code and header files - if (!batch_mode) enter_project_dir(); + if (!Fluid.batch_mode) enter_project_dir(); int x = f.write_code(code_filename.c_str(), header_filename.c_str()); Fl_String code_filename_rel = fl_filename_relative(code_filename); Fl_String header_filename_rel = fl_filename_relative(header_filename); - if (!batch_mode) leave_project_dir(); + if (!Fluid.batch_mode) leave_project_dir(); // -- print error message in batch mode or pop up an error or confirmation dialog box - if (batch_mode) { + if (Fluid.batch_mode) { if (!x) { fprintf(stderr, "%s and %s: %s\n", code_filename_rel.c_str(), @@ -1238,7 +1216,7 @@ int write_code_files(bool dont_show_completion_dialog) Callback to write C++ code and header files. */ void write_cb(Fl_Widget *, void *) { - write_code_files(); + g_project.write_code_files(); } #if 0 @@ -1260,7 +1238,7 @@ int mergeback_code_files() Fl_String proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); Fl_String code_filename; #if 1 - if (!batch_mode) { + if (!Fluid.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(); @@ -1270,9 +1248,9 @@ int mergeback_code_files() #endif if (code_filename.empty()) code_filename = g_project.codefile_path() + g_project.codefile_name(); - if (!batch_mode) enter_project_dir(); + if (!Fluid.batch_mode) enter_project_dir(); int c = merge_back(code_filename, proj_filename, FD_MERGEBACK_INTERACTIVE); - if (!batch_mode) leave_project_dir(); + if (!Fluid.batch_mode) leave_project_dir(); if (c==0) fl_message("Comparing\n \"%s\"\nto\n \"%s\"\n\n" "MergeBack found no external modifications\n" @@ -1293,12 +1271,12 @@ void mergeback_cb(Fl_Widget *, void *) { void write_strings_cb(Fl_Widget *, void *) { flush_text_widgets(); if (!filename) { - save_cb(0,0); + FLUID::Callbacks::save(0,0); if (!filename) return; } Fl_String filename = g_project.stringsfile_path() + g_project.stringsfile_name(); int x = write_strings(filename); - if (batch_mode) { + if (Fluid.batch_mode) { if (x) { fprintf(stderr, "%s : %s\n", filename.c_str(), strerror(errno)); exit(1); @@ -1632,7 +1610,7 @@ void print_menu_cb(Fl_Widget *, void *) { 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_cb(Fl_Widget *, void *) { Fluid.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(""); } @@ -1659,9 +1637,9 @@ Fl_Menu_Item Main_Menu[] = { {"&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}, + {"&Save", FL_COMMAND+'s', FLUID::Callbacks::save, 0}, + {"Save &As...", FL_COMMAND+FL_SHIFT+'s', FLUID::Callbacks::save, (void*)1}, + {"Sa&ve A Copy...", 0, FLUID::Callbacks::save, (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}, @@ -1757,7 +1735,7 @@ Fl_Menu_Item Main_Menu[] = { \see init_scheme() for choice values and backwards compatibility */ void scheme_cb(Fl_Scheme_Choice *choice, void *) { - if (batch_mode) + if (Fluid.batch_mode) return; // set the new scheme only if the scheme was changed @@ -1864,7 +1842,7 @@ void toggle_codeview_b_cb(Fl_Button*, void *) { Build the main app window and create a few other dialogs. */ void make_main_window() { - if (!batch_mode) { + if (!Fluid.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); @@ -1884,7 +1862,7 @@ void make_main_window() { 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); + save_item = (Fl_Menu_Item*)main_menubar->find_item(FLUID::Callbacks::save); 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); @@ -1896,7 +1874,7 @@ void make_main_window() { main_window->end(); } - if (!batch_mode) { + if (!Fluid.batch_mode) { load_history(); g_shell_config = new Fd_Shell_Command_List; widget_browser->load_prefs(); @@ -2005,7 +1983,7 @@ void set_filename(const char *c) { if (filename) free((void *)filename); filename = c ? fl_strdup(c) : NULL; - if (filename && !batch_mode) + if (filename && !Fluid.batch_mode) update_history(filename); set_modflag(modflag); @@ -2064,53 +2042,56 @@ void set_modflag(int mf, int mfc) { codeview_defer_update(); } -// ---- Main program entry point - /** - Handle command line arguments. + Handle one command line argument. + + If an argument is not recognized, it is not supported and the function + returns 0. If the argument is supported, the function returns the number + of arguments used. The argument is then removed from the list. + \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) { +int FLUID::App_Args::arg(int argc, char** argv, int& i) { if (argv[i][0] != '-') return 0; if (argv[i][1] == 'd' && !argv[i][2]) { - G_debug=1; + Fluid.args.debug = true; i++; return 1; } if (argv[i][1] == 'u' && !argv[i][2]) { - update_file++; - batch_mode++; + Fluid.args.update = true; + Fluid.batch_mode = true; i++; return 1; } if (argv[i][1] == 'c' && !argv[i][2]) { - compile_file++; - batch_mode++; + Fluid.args.compile = true; + Fluid.batch_mode = true; i++; return 1; } if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) { - compile_file++; - compile_strings++; - batch_mode++; + Fluid.args.compile = true; + Fluid.args.strings = true; + Fluid.batch_mode = true; i++; return 1; } if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { - g_code_filename_arg = argv[i+1]; - batch_mode++; + Fluid.args.code_filename = argv[i+1]; + Fluid.batch_mode = true; i += 2; return 2; } #ifndef NDEBUG if ((i+1 < argc) && (strcmp(argv[i], "--autodoc") == 0)) { - g_autodoc_path = argv[i+1]; + Fluid.args.autodoc_path = argv[i+1]; i += 2; return 2; } #endif 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++; + Fluid.args.header_filename = argv[i+1]; + Fluid.batch_mode = true; i += 2; return 2; } else { @@ -2121,6 +2102,48 @@ static int arg(int argc, char** argv, int& i) { return 0; } +/** + * Parses the command line arguments and sets the appropriate flags in the + * FLUID::App_Args object. If an unsupported argument is found, or if the + * number of arguments is incorrect, prints an error message and returns false. + * Otherwise, returns true. + * + * \param[in] argc Number of arguments in the list. + * \param[in] argv Pointer to an array of arguments. + * \return True if the arguments are valid, false otherwise. + */ +bool FLUID::App_Args::read(int argc, char **argv) { + Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW + int i = 0; + if ( (Fl::args(argc, argv, i, arg) == 0) // unsupported argument found + || (Fluid.batch_mode && (i != argc-1)) // .fl filename missing + || (!Fluid.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" + " -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 + fl_message(msg, app_name); +#else + fprintf(stderr, msg, app_name); +#endif + return false; + } + return true; +} + +// ---- Main program entry point + #if ! (defined(_WIN32) && !defined (__CYGWIN__)) int quit_flag = 0; @@ -2167,36 +2190,14 @@ int main(int argc,char **argv) { 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()); // store the current path at launch + Fluid.launch_path = end_with_slash(fl_getcwd()); // 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" - " -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 - fl_message(msg, app_name); -#else - fprintf(stderr, msg, app_name); -#endif + if (Fluid.args.read(argc, argv)==false) { return 1; } const char *c = NULL; - if (g_autodoc_path.empty()) + if (Fluid.args.autodoc_path.empty()) c = argv[i]; fl_register_images(); @@ -2204,7 +2205,7 @@ int main(int argc,char **argv) { make_main_window(); if (c) set_filename(c); - if (!batch_mode) { + if (!Fluid.batch_mode) { #ifdef __APPLE__ fl_open_callback(apple_open_cb); #endif // __APPLE__ @@ -2221,14 +2222,14 @@ int main(int argc,char **argv) { 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()) { + if (!c && openlast_button->value() && absolute_history[0][0] && Fluid.args.autodoc_path.empty()) { // Open previous file when no file specified... open_project_file(absolute_history[0]); } } undo_suspend(); if (c && !read_file(c,0)) { - if (batch_mode) { + if (Fluid.batch_mode) { fprintf(stderr,"%s : %s\n", c, strerror(errno)); exit(1); } @@ -2238,32 +2239,32 @@ int main(int argc,char **argv) { // 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()) { + if (Fluid.batch_mode) { + if (!Fluid.args.code_filename.empty()) { g_project.code_file_set = 1; - g_project.code_file_name = g_code_filename_arg; + g_project.code_file_name = Fluid.args.code_filename; } - if (!g_header_filename_arg.empty()) { + if (!Fluid.args.header_filename.empty()) { g_project.header_file_set = 1; - g_project.header_file_name = g_header_filename_arg; + g_project.header_file_name = Fluid.args.header_filename; } } - if (update_file) { // fluid -u + if (Fluid.args.update) { // fluid -u write_file(c,0); - if (!compile_file) + if (!Fluid.args.compile) exit(0); } - if (compile_file) { // fluid -c[s] - if (compile_strings) + if (Fluid.args.compile) { // fluid -c[s] + if (Fluid.args.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) + if (Fluid.batch_mode) exit(0); #ifdef WIN32 @@ -2283,8 +2284,8 @@ int main(int argc,char **argv) { #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); + if (!Fluid.args.autodoc_path.empty()) { + run_autodoc(Fluid.args.autodoc_path); return 0; } #endif diff --git a/fluid/fluid.h b/fluid/fluid.h index 4486e1d170..b54ecad442 100644 --- a/fluid/fluid.h +++ b/fluid/fluid.h @@ -62,7 +62,6 @@ 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]; extern int reading_file; @@ -85,19 +84,8 @@ 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 Fl_String g_code_filename_arg; -extern Fl_String g_header_filename_arg; -extern Fl_String g_launch_path; - -extern Fl_String g_autodoc_path; - // ---- project class declaration /** @@ -109,17 +97,20 @@ enum class Fd_I18n_Type { POSIX ///< Posix catgets internationalization }; +namespace FLUID { + /** Data and settings for a FLUID project file. */ -class Fluid_Project { +class Project { public: /// Project constructor - Fluid_Project() = default; + Project() = default; /// Project destructor - not implemented - ~Fluid_Project() = default; + ~Project() = default; void reset(); void update_settings_dialog(); + int write_code_files(bool dont_show_completion_dialog=false); Fl_String projectfile_path() const; Fl_String projectfile_name() const; @@ -174,11 +165,54 @@ class Fluid_Project { Fl_String code_file_name { ".cxx" }; }; -extern Fluid_Project g_project; +class App_Args { +public: + /// Read command line args. + bool read(int argc, char **argv); + /// Read one command line argument + static int arg(int argc, char** argv, int& i); + /// `-o filename`: override the generate code file extension or name + Fl_String code_filename { }; + /// `-h filename`: override the generate header file extension or name + Fl_String header_filename { }; + /// `--autodoc path`: if set, generate images for automatic documentation in this directory + Fl_String autodoc_path { }; + /// `-u`: update the project file + bool update { false }; + /// `-c`: compile the project file into source code + bool compile { false }; + /// `-cs`: compile the project file into source code and write i18n strings file + bool strings { false }; + /// `-d`: debug mode (used by external code editor) + bool debug { false }; +}; + +class Callbacks { +public: + static void save(Fl_Widget *, void *v); +}; + +class App { +public: + /// Command line arguments. + App_Args args; + /// Set if the application is running from the command line and not in interactive mode. + bool batch_mode { false }; + /// current directory path at application launch + Fl_String launch_path { }; + + bool new_project(bool user_must_confirm = true); + Project &project(); +}; + + +}; // namespace FLUID + +extern FLUID::Project g_project; +extern FLUID::App Fluid; // ---- public functions -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); @@ -188,12 +222,10 @@ extern const Fl_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 *); diff --git a/fluid/shell_command.cxx b/fluid/shell_command.cxx index 9001154e3a..f12596ecb3 100644 --- a/fluid/shell_command.cxx +++ b/fluid/shell_command.cxx @@ -304,10 +304,10 @@ static bool prepare_shell_command(int flags) { return false; } if (flags & Fd_Shell_Command::SAVE_PROJECT) { - save_cb(0, 0); + FLUID::Callbacks::save(0, 0); } if (flags & Fd_Shell_Command::SAVE_SOURCECODE) { - write_code_files(true); + g_project.write_code_files(true); } if (flags & Fd_Shell_Command::SAVE_STRINGS) { write_strings_cb(0, 0); diff --git a/fluid/widget_panel.cxx b/fluid/widget_panel.cxx index 61ea1314e7..e705a620df 100644 --- a/fluid/widget_panel.cxx +++ b/fluid/widget_panel.cxx @@ -21,7 +21,6 @@ #include "Fl_Widget_Type.h" #include "Fl_Grid_Type.h" #include -extern void set_modflag(int mf, int mfc=-1); Fl_Double_Window *image_panel_window=(Fl_Double_Window *)0; diff --git a/fluid/widget_panel.fl b/fluid/widget_panel.fl index 5d01fa96d7..9a46452340 100644 --- a/fluid/widget_panel.fl +++ b/fluid/widget_panel.fl @@ -40,9 +40,6 @@ decl {\#include } {private global decl {\#include "custom_widgets.h"} {public global } -decl {extern void set_modflag(int mf, int mfc=-1);} {private local -} - Function {make_image_panel()} { comment {Create a panel for editing widget image data} open } { @@ -332,7 +329,7 @@ Function {make_widget_panel()} { comment {Create a panel that can be used with all known widgets} open } { Fl_Window {} { - comment {Use a Double Window to avoid flickering.} open selected + comment {Use a Double Window to avoid flickering.} open xywh {372 208 420 400} type Double labelsize 11 align 80 resizable hotspot code0 {o->size_range(o->w(), o->h());} size_range {420 400 0 0} visible } {