summaryrefslogtreecommitdiff
path: root/fluid
diff options
context:
space:
mode:
Diffstat (limited to 'fluid')
-rw-r--r--fluid/Project.cxx1
-rw-r--r--fluid/Project.h4
-rw-r--r--fluid/io/Code_Writer.cxx59
-rw-r--r--fluid/io/Project_Reader.cxx5
-rw-r--r--fluid/io/Project_Writer.cxx3
-rw-r--r--fluid/panels/settings_panel.cxx38
-rw-r--r--fluid/panels/settings_panel.fl40
-rw-r--r--fluid/panels/settings_panel.h1
8 files changed, 123 insertions, 28 deletions
diff --git a/fluid/Project.cxx b/fluid/Project.cxx
index 46432f709..2c7dca6e5 100644
--- a/fluid/Project.cxx
+++ b/fluid/Project.cxx
@@ -54,6 +54,7 @@ void Project::reset() {
code_file_set = 0;
header_file_name = ".h";
code_file_name = ".cxx";
+ include_guard = "";
write_mergeback_data = 0;
}
diff --git a/fluid/Project.h b/fluid/Project.h
index f82529b1b..065c7d383 100644
--- a/fluid/Project.h
+++ b/fluid/Project.h
@@ -69,6 +69,8 @@ public: // Member Variables
std::string header_file_name = ".h";
/// Hold the default extension for source code files, or the entire filename if set via command line.
std::string code_file_name = ".cxx";
+ /// Macro used in header file for #ifdef MACRO \n #defined MACRO \n ... \n #endif
+ std::string include_guard = "";
/// Used as a counter to set the .fl project dir as the current directory.
int in_project_dir { 0 };
@@ -101,7 +103,7 @@ public: // Methods
void enter_project_dir();
void leave_project_dir();
-
+
void set_filename(const char *c);
void write_strings();
diff --git a/fluid/io/Code_Writer.cxx b/fluid/io/Code_Writer.cxx
index 086244035..8bcef2f33 100644
--- a/fluid/io/Code_Writer.cxx
+++ b/fluid/io/Code_Writer.cxx
@@ -27,6 +27,11 @@
#include <zlib.h>
+#include <string>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
using namespace fld;
using namespace fld::io;
using namespace fld::proj;
@@ -624,15 +629,51 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) {
// generated by Fast Light User Interface Designer (fluid) version %.4f\n\n";
fprintf(header_file, hdr, FL_VERSION);
crc_printf(hdr, FL_VERSION);
-
- {char define_name[102];
- const char* a = fl_filename_name(t);
- char* b = define_name;
- if (!isalpha(*a)) {*b++ = '_';}
- while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;}
- *b = 0;
- fprintf(header_file, "#ifndef %s\n", define_name);
- fprintf(header_file, "#define %s\n", define_name);
+ {
+ // Creating the include guard is more involved than it seems at first glance.
+ // The include guard is deduced from header filename. However, if the
+ // filename contains unicode characters, they need to be encoded using
+ // \Uxxxxxxxx or \\uxxxx encoding to form a valid macro identifier.
+ //
+ // But that approach is not portable. Windows does not normalize Unicode
+ // (ö is the letter \u00F6). macOS normalizes to NFD (ö is \u006F\u0308,
+ // o followed by a Combining Diaresis ¨).
+ //
+ // To make the include guard consistent across l=platforms, it can be
+ // explicitly set by the user in the Project Settings.
+ std::string macro_name_str = proj_.include_guard;
+ if (macro_name_str.empty()) {
+ std::ostringstream macro_name;
+ std::string header_name;
+ const char* a = nullptr;
+ if (write_codeview) {
+ header_name = proj_.headerfile_name();
+ a = header_name.c_str();
+ } else {
+ a = fl_filename_name(t);
+ }
+ const char* b = a + strlen(a);
+ int len = 0;
+ unsigned ucs = fl_utf8decode(a, b, &len);
+ if ((ucs > 127) || (!isalpha(ucs) && (ucs != '_')))
+ macro_name << '_';
+ while (a < b) {
+ ucs = fl_utf8decode(a, b, &len);
+ if ((ucs == '.') || (ucs == '_')) {
+ macro_name << '_';
+ } else if (ucs > 0x0000ffff) { // large unicode character
+ macro_name << "\\U" << std::setw(8) << std::setfill('0') << std::hex << ucs;
+ } else if ((ucs > 127) || !isalnum(ucs)) { // small unicode character or not an ASCI letter or digit
+ macro_name << "\\u" << std::setw(4) << std::setfill('0') << std::hex << ucs;
+ } else {
+ macro_name << (char)ucs;
+ }
+ a += len;
+ }
+ macro_name_str = macro_name.str();
+ }
+ fprintf(header_file, "#ifndef %s\n", macro_name_str.c_str());
+ fprintf(header_file, "#define %s\n", macro_name_str.c_str());
}
if (proj_.avoid_early_includes==0) {
diff --git a/fluid/io/Project_Reader.cxx b/fluid/io/Project_Reader.cxx
index c420824aa..0e2809685 100644
--- a/fluid/io/Project_Reader.cxx
+++ b/fluid/io/Project_Reader.cxx
@@ -277,6 +277,11 @@ Node *Project_Reader::read_children(Node *p, int merge, Strategy strategy, char
goto CONTINUE;
}
+ if (!strcmp(c,"include_guard")) {
+ proj_.include_guard = read_word();
+ goto CONTINUE;
+ }
+
if (!strcmp(c, "snap")) {
Fluid.layout_list.read(this);
goto CONTINUE;
diff --git a/fluid/io/Project_Writer.cxx b/fluid/io/Project_Writer.cxx
index 1975ef85d..387c0093f 100644
--- a/fluid/io/Project_Writer.cxx
+++ b/fluid/io/Project_Writer.cxx
@@ -115,12 +115,13 @@ int Project_Writer::write_project(const char *filename, int selected_only, bool
write_string("\nutf8_in_src");
if (proj_.avoid_early_includes)
write_string("\navoid_early_includes");
-
+
proj_.i18n.write(*this);
if (!selected_only) {
write_string("\nheader_name"); write_word(proj_.header_file_name.c_str());
write_string("\ncode_name"); write_word(proj_.code_file_name.c_str());
+ write_string("\ninclude_guard"); write_word(proj_.include_guard.c_str());
Fluid.layout_list.write(this);
if (g_shell_config)
g_shell_config->write(this);
diff --git a/fluid/panels/settings_panel.cxx b/fluid/panels/settings_panel.cxx
index 0ba267c76..84db80b34 100644
--- a/fluid/panels/settings_panel.cxx
+++ b/fluid/panels/settings_panel.cxx
@@ -408,6 +408,19 @@ static void cb_include_H_from_C_button(Fl_Check_Button* o, void* v) {
}
}
+Fl_Input *include_guard_input=(Fl_Input *)0;
+
+static void cb_include_guard_input(Fl_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value(Fluid.proj.include_guard.c_str());
+ } else {
+ if (strcmp(Fluid.proj.include_guard.c_str(), o->value())) {
+ Fluid.proj.include_guard = o->value();
+ Fluid.proj.set_modflag(1);
+ }
+ }
+}
+
Fl_Check_Button *use_FL_COMMAND_button=(Fl_Check_Button *)0;
static void cb_use_FL_COMMAND_button(Fl_Check_Button* o, void* v) {
@@ -2452,7 +2465,6 @@ Fl_Double_Window* make_settings_window() {
w_settings_general_tab->image( image_general_64() );
w_settings_general_tab->image()->scale(36, 24, 0, 1);
w_settings_general_tab->labelsize(11);
- w_settings_general_tab->hide();
{ Fl_Group* o = new Fl_Group(120, 78, 130, 25);
o->callback((Fl_Callback*)cb_);
{ scheme_choice = new Fl_Scheme_Choice(120, 78, 120, 25, "Scheme: ");
@@ -2638,18 +2650,29 @@ Fl_Double_Window* make_settings_window() {
include_H_from_C_button->labelsize(11);
include_H_from_C_button->callback((Fl_Callback*)cb_include_H_from_C_button);
} // Fl_Check_Button* include_H_from_C_button
- { Fl_Box* o = new Fl_Box(100, 205, 0, 20, "Options: ");
+ { include_guard_input = new Fl_Input(100, 182, 220, 20, "Include Guard:");
+ include_guard_input->tooltip("Name of macro used as\nan include guard in header file:\n\n#ifdef GUARD\n#def"
+"ine GUARD\n...\n#endif");
+ include_guard_input->box(FL_THIN_DOWN_BOX);
+ include_guard_input->labelfont(1);
+ include_guard_input->labelsize(11);
+ include_guard_input->textfont(4);
+ include_guard_input->textsize(11);
+ include_guard_input->callback((Fl_Callback*)cb_include_guard_input, (void*)(1));
+ include_guard_input->when(FL_WHEN_CHANGED);
+ } // Fl_Input* include_guard_input
+ { Fl_Box* o = new Fl_Box(100, 225, 0, 20, "Options: ");
o->labelfont(1);
o->labelsize(11);
o->align(Fl_Align(FL_ALIGN_LEFT));
} // Fl_Box* o
- { use_FL_COMMAND_button = new Fl_Check_Button(100, 205, 220, 20, "Menu shortcuts use FL_COMMAND");
+ { use_FL_COMMAND_button = new Fl_Check_Button(100, 225, 220, 20, "Menu shortcuts use FL_COMMAND");
use_FL_COMMAND_button->tooltip("Replace FL_CTRL and FL_META with FL_COMMAND when generating menu shortcuts");
use_FL_COMMAND_button->down_box(FL_DOWN_BOX);
use_FL_COMMAND_button->labelsize(11);
use_FL_COMMAND_button->callback((Fl_Callback*)cb_use_FL_COMMAND_button);
} // Fl_Check_Button* use_FL_COMMAND_button
- { utf8_in_src_button = new Fl_Check_Button(100, 230, 220, 20, "allow Unicode UTF-8 in source code");
+ { utf8_in_src_button = new Fl_Check_Button(100, 250, 220, 20, "allow Unicode UTF-8 in source code");
utf8_in_src_button->tooltip("For older compilers, characters outside of the printable ASCII range are esca"
"ped using octal notation `\\0123`. If this option is checked, Fluid will write"
" UTF-8 characters unchanged.");
@@ -2657,18 +2680,18 @@ Fl_Double_Window* make_settings_window() {
utf8_in_src_button->labelsize(11);
utf8_in_src_button->callback((Fl_Callback*)cb_utf8_in_src_button);
} // Fl_Check_Button* utf8_in_src_button
- { avoid_early_includes_button = new Fl_Check_Button(100, 255, 220, 20, "avoid early include of Fl.H");
+ { avoid_early_includes_button = new Fl_Check_Button(100, 275, 220, 20, "avoid early include of Fl.H");
avoid_early_includes_button->tooltip("Do not emit #include <FL//Fl.H> until it is needed by another include file.");
avoid_early_includes_button->down_box(FL_DOWN_BOX);
avoid_early_includes_button->labelsize(11);
avoid_early_includes_button->callback((Fl_Callback*)cb_avoid_early_includes_button);
} // Fl_Check_Button* avoid_early_includes_button
- { Fl_Box* o = new Fl_Box(100, 283, 0, 20, "Experimental: ");
+ { Fl_Box* o = new Fl_Box(100, 303, 0, 20, "Experimental: ");
o->labelfont(1);
o->labelsize(11);
o->align(Fl_Align(FL_ALIGN_LEFT));
} // Fl_Box* o
- { w_proj_mergeback = new Fl_Check_Button(100, 283, 220, 20, "generate MergeBack data");
+ { w_proj_mergeback = new Fl_Check_Button(100, 303, 220, 20, "generate MergeBack data");
w_proj_mergeback->tooltip("MergeBack is a feature under construction that allows changes in code files t"
"o be merged back into the project file. Checking this option will generate add"
"itional data in code and project files.");
@@ -3230,6 +3253,7 @@ Fl_Double_Window* make_settings_window() {
w_settings_i18n_tab->image()->scale(36, 24, 0, 1);
w_settings_i18n_tab->labelsize(11);
w_settings_i18n_tab->callback((Fl_Callback*)cb_w_settings_i18n_tab);
+ w_settings_i18n_tab->hide();
{ Fl_Group* o = new Fl_Group(100, 78, 170, 20);
o->callback((Fl_Callback*)propagate_load);
{ i18n_type_chooser = new Fl_Choice(100, 78, 160, 20, "i18n Library:");
diff --git a/fluid/panels/settings_panel.fl b/fluid/panels/settings_panel.fl
index efa015065..8684d7f83 100644
--- a/fluid/panels/settings_panel.fl
+++ b/fluid/panels/settings_panel.fl
@@ -2,6 +2,7 @@
version 1.0500
header_name {.h}
code_name {.cxx}
+include_guard {}
snap {
ver 1
current_suite FLTK
@@ -198,8 +199,8 @@ Function {make_settings_window()} {open
xywh {10 10 320 530} selection_color 12 labelsize 11 labelcolor 255 resizable
} {
Fl_Group w_settings_general_tab {
- label General open
- scale_image {36 24} image {../icons/general_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide resizable
+ label General open selected
+ scale_image {36 24} image {../icons/general_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 resizable
} {
Fl_Group {} {
callback {propagate_load(o, v);} open
@@ -386,9 +387,28 @@ or just ".ext" to set extension.}
}}
tooltip {Include the header file from the code file.} xywh {100 162 220 20} down_box DOWN_BOX labelsize 11
}
+ Fl_Input include_guard_input {
+ label {Include Guard:}
+ user_data 1 user_data_type {void*}
+ callback {if (v == LOAD) {
+ o->value(Fluid.proj.include_guard.c_str());
+} else {
+ if (strcmp(Fluid.proj.include_guard.c_str(), o->value())) {
+ Fluid.proj.include_guard = o->value();
+ Fluid.proj.set_modflag(1);
+ }
+}}
+ tooltip {Name of macro used as
+an include guard in header file:
+
+\#ifdef GUARD
+\#define GUARD
+...
+\#endif} xywh {100 182 220 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 when 1 textfont 4 textsize 11
+ }
Fl_Box {} {
label {Options: }
- xywh {100 205 0 20} labelfont 1 labelsize 11 align 4
+ xywh {100 225 0 20} labelfont 1 labelsize 11 align 4
}
Fl_Check_Button use_FL_COMMAND_button {
label {Menu shortcuts use FL_COMMAND}
@@ -400,7 +420,7 @@ or just ".ext" to set extension.}
Fluid.proj.use_FL_COMMAND = o->value();
}
}}
- tooltip {Replace FL_CTRL and FL_META with FL_COMMAND when generating menu shortcuts} xywh {100 205 220 20} down_box DOWN_BOX labelsize 11
+ tooltip {Replace FL_CTRL and FL_META with FL_COMMAND when generating menu shortcuts} xywh {100 225 220 20} down_box DOWN_BOX labelsize 11
}
Fl_Check_Button utf8_in_src_button {
label {allow Unicode UTF-8 in source code}
@@ -412,7 +432,7 @@ or just ".ext" to set extension.}
Fluid.proj.utf8_in_src = o->value();
}
}}
- tooltip {For older compilers, characters outside of the printable ASCII range are escaped using octal notation `\\0123`. If this option is checked, Fluid will write UTF-8 characters unchanged.} xywh {100 230 220 20} down_box DOWN_BOX labelsize 11
+ tooltip {For older compilers, characters outside of the printable ASCII range are escaped using octal notation `\\0123`. If this option is checked, Fluid will write UTF-8 characters unchanged.} xywh {100 250 220 20} down_box DOWN_BOX labelsize 11
}
Fl_Check_Button avoid_early_includes_button {
label {avoid early include of Fl.H}
@@ -424,11 +444,11 @@ or just ".ext" to set extension.}
Fluid.proj.avoid_early_includes = o->value();
}
}}
- tooltip {Do not emit \#include <FL//Fl.H> until it is needed by another include file.} xywh {100 255 220 20} down_box DOWN_BOX labelsize 11
+ tooltip {Do not emit \#include <FL//Fl.H> until it is needed by another include file.} xywh {100 275 220 20} down_box DOWN_BOX labelsize 11
}
Fl_Box {} {
label {Experimental: }
- xywh {100 283 0 20} labelfont 1 labelsize 11 align 4
+ xywh {100 303 0 20} labelfont 1 labelsize 11 align 4
}
Fl_Check_Button w_proj_mergeback {
label {generate MergeBack data}
@@ -440,7 +460,7 @@ or just ".ext" to set extension.}
Fluid.proj.write_mergeback_data = o->value();
}
}}
- tooltip {MergeBack is a feature under construction that allows changes in code files to be merged back into the project file. Checking this option will generate additional data in code and project files.} xywh {100 283 220 20} down_box DOWN_BOX labelsize 11
+ tooltip {MergeBack is a feature under construction that allows changes in code files to be merged back into the project file. Checking this option will generate additional data in code and project files.} xywh {100 303 220 20} down_box DOWN_BOX labelsize 11
}
Fl_Box {} {
xywh {100 530 220 10} hide resizable
@@ -1524,7 +1544,7 @@ if (v == LOAD) {
Fl_Group w_settings_i18n_tab {
label Locale
callback {propagate_load(o, v);} open
- scale_image {36 24} image {../icons/language_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11
+ scale_image {36 24} image {../icons/language_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide
} {
Fl_Group {} {
callback propagate_load open
@@ -1586,7 +1606,7 @@ if (v == LOAD) {
Fluid.proj.undo.checkpoint();
Fluid.proj.i18n.gnu_function = o->value();
Fluid.proj.set_modflag(1);
-}} selected
+}}
tooltip {The function to call to translate labels and tooltips, usually "gettext" or "_"} xywh {100 153 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11
}
Fl_Input i18n_gnu_static_function_input {
diff --git a/fluid/panels/settings_panel.h b/fluid/panels/settings_panel.h
index 45c1457a6..f57195680 100644
--- a/fluid/panels/settings_panel.h
+++ b/fluid/panels/settings_panel.h
@@ -70,6 +70,7 @@ extern Fl_Group *w_settings_project_tab;
extern Fl_Input *header_file_input;
extern Fl_Input *code_file_input;
extern Fl_Check_Button *include_H_from_C_button;
+extern Fl_Input *include_guard_input;
extern Fl_Check_Button *use_FL_COMMAND_button;
extern Fl_Check_Button *utf8_in_src_button;
extern Fl_Check_Button *avoid_early_includes_button;