#1276: New code to generate include guard
- generating macro identifier with unicode encoding if the filename has international character - optional user defined include guard
This commit is contained in:
parent
5c33d3051f
commit
66b73c8e76
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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:");
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user