diff options
Diffstat (limited to 'fluid')
| -rw-r--r-- | fluid/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | fluid/Project.cxx | 14 | ||||
| -rw-r--r-- | fluid/Project.h | 36 | ||||
| -rw-r--r-- | fluid/io/Code_Writer.cxx | 34 | ||||
| -rw-r--r-- | fluid/io/Project_Reader.cxx | 34 | ||||
| -rw-r--r-- | fluid/io/Project_Writer.cxx | 24 | ||||
| -rw-r--r-- | fluid/io/Project_Writer.h | 1 | ||||
| -rw-r--r-- | fluid/io/String_Writer.cxx | 6 | ||||
| -rw-r--r-- | fluid/nodes/Menu_Node.cxx | 28 | ||||
| -rw-r--r-- | fluid/nodes/Widget_Node.cxx | 16 | ||||
| -rw-r--r-- | fluid/nodes/Window_Node.cxx | 6 | ||||
| -rw-r--r-- | fluid/panels/codeview_panel.cxx | 2 | ||||
| -rw-r--r-- | fluid/panels/codeview_panel.fl | 2 | ||||
| -rw-r--r-- | fluid/panels/settings_panel.cxx | 32 | ||||
| -rw-r--r-- | fluid/panels/settings_panel.fl | 32 | ||||
| -rw-r--r-- | fluid/proj/i18n.cxx | 93 | ||||
| -rw-r--r-- | fluid/proj/i18n.h | 88 |
17 files changed, 272 insertions, 178 deletions
diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt index 62d53315e..9eeec492b 100644 --- a/fluid/CMakeLists.txt +++ b/fluid/CMakeLists.txt @@ -132,6 +132,7 @@ set(CPPFILES panels/widget_panel/Grid_Tab.cxx panels/widget_panel/Grid_Child_Tab.cxx proj/align_widget.cxx + proj/i18n.cxx proj/mergeback.cxx proj/undo.cxx rsrcs/pixmaps.cxx @@ -185,6 +186,7 @@ set(HEADERFILES panels/widget_panel/Grid_Child_Tab.h proj/align_widget.h proj/mergeback.h + proj/i18n.h proj/undo.h rsrcs/comments.h rsrcs/pixmaps.h diff --git a/fluid/Project.cxx b/fluid/Project.cxx index c7c517a1d..46432f709 100644 --- a/fluid/Project.cxx +++ b/fluid/Project.cxx @@ -44,17 +44,7 @@ Project::~Project() { */ void Project::reset() { ::delete_all(); - i18n_type = fld::I18n_Type::NONE; - - i18n_gnu_include = "<libintl.h>"; - i18n_gnu_conditional = ""; - i18n_gnu_function = "gettext"; - i18n_gnu_static_function = "gettext_noop"; - - i18n_pos_include = "<nl_types.h>"; - i18n_pos_conditional = ""; - i18n_pos_file = ""; - i18n_pos_set = "1"; + i18n.reset(); include_H_from_C = 1; use_FL_COMMAND = 0; @@ -167,7 +157,7 @@ std::string Project::stringsfile_path() const { \return the file name without path */ std::string Project::stringsfile_name() const { - switch (i18n_type) { + switch (i18n.type) { default: return fl_filename_setext_str(fl_filename_name(proj_filename), ".txt"); case fld::I18n_Type::GNU: return fl_filename_setext_str(fl_filename_name(proj_filename), ".po"); case fld::I18n_Type::POSIX: return fl_filename_setext_str(fl_filename_name(proj_filename), ".msg"); diff --git a/fluid/Project.h b/fluid/Project.h index e60f7bc26..f82529b1b 100644 --- a/fluid/Project.h +++ b/fluid/Project.h @@ -19,6 +19,7 @@ #define FLUID_PROJECT_H #include "proj/undo.h" +#include "proj/i18n.h" #include "nodes/Tree.h" #include <string> @@ -34,16 +35,6 @@ namespace app { } // namespace app /** - Enumeration of available internationalization types. - */ -enum class I18n_Type { - NONE = 0, ///< No i18n, all strings are litearals - GNU, ///< GNU gettext internationalization - POSIX ///< Posix catgets internationalization -}; - - -/** Data and settings for a FLUID project file. */ class Project @@ -55,29 +46,8 @@ public: // Member Variables // Manage the node tree of the project. node::Tree tree { *this }; - /// One of the available internationalization types. - fld::I18n_Type i18n_type = I18n_Type::NONE; - /// Include file for GNU i18n, writes an #include statement into the source - /// file. This is usually `<libintl.h>` or `"gettext.h"` for GNU gettext. - std::string i18n_gnu_include = "<libintl.h>"; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_gnu_conditional = ""; - /// For the gettext/intl.h options, this is the function that translates text - /// at runtime. This is usually "gettext" or "_". - std::string i18n_gnu_function = "gettext"; - /// For the gettext/intl.h options, this is the function that marks the translation - /// of text at initialisation time. This is usually "gettext_noop" or "N_". - std::string i18n_gnu_static_function = "gettext_noop"; - - /// Include file for Posix i18n, write a #include statement into the source - /// file. This is usually `<nl_types.h>` for Posix catgets. - std::string i18n_pos_include = "<nl_types.h>"; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_pos_conditional = ""; - /// Name of the nl_catd database - std::string i18n_pos_file = ""; - /// Message set ID for the catalog. - std::string i18n_pos_set = "1"; + // Project internationalization. + proj::I18n i18n { *this }; /// If set, generate code to include the header file form the c++ file int include_H_from_C = 1; diff --git a/fluid/io/Code_Writer.cxx b/fluid/io/Code_Writer.cxx index b7179826d..086244035 100644 --- a/fluid/io/Code_Writer.cxx +++ b/fluid/io/Code_Writer.cxx @@ -648,14 +648,14 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { } } std::string loc_include, loc_conditional; - if (proj_.i18n_type==fld::I18n_Type::GNU) { - loc_include = proj_.i18n_gnu_include; - loc_conditional = proj_.i18n_gnu_conditional; + if (proj_.i18n.type==fld::I18n_Type::GNU) { + loc_include = proj_.i18n.gnu_include; + loc_conditional = proj_.i18n.gnu_conditional; } else { - loc_include = proj_.i18n_pos_include; - loc_conditional = proj_.i18n_pos_conditional; + loc_include = proj_.i18n.posix_include; + loc_conditional = proj_.i18n.posix_conditional; } - if ((proj_.i18n_type != fld::I18n_Type::NONE) && !loc_include.empty()) { + if ((proj_.i18n.type != fld::I18n_Type::NONE) && !loc_include.empty()) { int conditional = !loc_conditional.empty(); if (conditional) { write_c("#ifdef %s\n", loc_conditional.c_str()); @@ -665,9 +665,9 @@ int 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 (proj_.i18n_type == fld::I18n_Type::POSIX) { - if (!proj_.i18n_pos_file.empty()) { - write_c("extern nl_catd %s;\n", proj_.i18n_pos_file.c_str()); + if (proj_.i18n.type == fld::I18n_Type::POSIX) { + if (!proj_.i18n.posix_file.empty()) { + write_c("extern nl_catd %s;\n", proj_.i18n.posix_file.c_str()); } else { write_c("// Initialize I18N stuff now for menus...\n"); write_c("#%sinclude <locale.h>\n", indent()); @@ -677,14 +677,14 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { } if (conditional) { write_c("#else\n"); - if (proj_.i18n_type == fld::I18n_Type::GNU) { - if (!proj_.i18n_gnu_function.empty()) { - write_c("#%sifndef %s\n", indent(), proj_.i18n_gnu_function.c_str()); - write_c("#%sdefine %s(text) text\n", indent_plus(1), proj_.i18n_gnu_function.c_str()); + if (proj_.i18n.type == fld::I18n_Type::GNU) { + if (!proj_.i18n.gnu_function.empty()) { + write_c("#%sifndef %s\n", indent(), proj_.i18n.gnu_function.c_str()); + write_c("#%sdefine %s(text) text\n", indent_plus(1), proj_.i18n.gnu_function.c_str()); write_c("#%sendif\n", indent()); } } - if (proj_.i18n_type == fld::I18n_Type::POSIX) { + if (proj_.i18n.type == fld::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()); @@ -692,9 +692,9 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { indentation--; write_c("#endif\n"); } - if (proj_.i18n_type == fld::I18n_Type::GNU && proj_.i18n_gnu_static_function[0]) { - write_c("#ifndef %s\n", proj_.i18n_gnu_static_function.c_str()); - write_c("#%sdefine %s(text) text\n", indent_plus(1), proj_.i18n_gnu_static_function.c_str()); + if (proj_.i18n.type == fld::I18n_Type::GNU && proj_.i18n.gnu_static_function[0]) { + write_c("#ifndef %s\n", proj_.i18n.gnu_static_function.c_str()); + write_c("#%sdefine %s(text) text\n", indent_plus(1), proj_.i18n.gnu_static_function.c_str()); write_c("#endif\n"); } } diff --git a/fluid/io/Project_Reader.cxx b/fluid/io/Project_Reader.cxx index 4ef0c6523..c420824aa 100644 --- a/fluid/io/Project_Reader.cxx +++ b/fluid/io/Project_Reader.cxx @@ -261,38 +261,8 @@ Node *Project_Reader::read_children(Node *p, int merge, Strategy strategy, char proj_.avoid_early_includes=1; goto CONTINUE; } - if (!strcmp(c,"i18n_type")) { - proj_.i18n_type = static_cast<fld::I18n_Type>(atoi(read_word())); - goto CONTINUE; - } - if (!strcmp(c,"i18n_gnu_function")) { - proj_.i18n_gnu_function = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_gnu_static_function")) { - proj_.i18n_gnu_static_function = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_pos_file")) { - proj_.i18n_pos_file = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_pos_set")) { - proj_.i18n_pos_set = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_include")) { - if (proj_.i18n_type == fld::I18n_Type::GNU) - proj_.i18n_gnu_include = read_word(); - else if (proj_.i18n_type == fld::I18n_Type::POSIX) - proj_.i18n_pos_include = read_word(); - goto CONTINUE; - } - if (!strcmp(c,"i18n_conditional")) { - if (proj_.i18n_type == fld::I18n_Type::GNU) - proj_.i18n_gnu_conditional = read_word(); - else if (proj_.i18n_type == fld::I18n_Type::POSIX) - proj_.i18n_pos_conditional = read_word(); + if (strncmp(c, "i18n_", 5) == 0) { + proj_.i18n.read(*this, c); goto CONTINUE; } if (!strcmp(c,"header_name")) { diff --git a/fluid/io/Project_Writer.cxx b/fluid/io/Project_Writer.cxx index bfe6e0566..1975ef85d 100644 --- a/fluid/io/Project_Writer.cxx +++ b/fluid/io/Project_Writer.cxx @@ -115,28 +115,8 @@ 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"); - if ((proj_.i18n_type != fld::I18n_Type::NONE)) { - write_string("\ni18n_type %d", static_cast<int>(proj_.i18n_type)); - switch (proj_.i18n_type) { - case fld::I18n_Type::NONE: - break; - case fld::I18n_Type::GNU : /* GNU gettext */ - write_string("\ni18n_include"); write_word(proj_.i18n_gnu_include.c_str()); - write_string("\ni18n_conditional"); write_word(proj_.i18n_gnu_conditional.c_str()); - write_string("\ni18n_gnu_function"); write_word(proj_.i18n_gnu_function.c_str()); - write_string("\ni18n_gnu_static_function"); write_word(proj_.i18n_gnu_static_function.c_str()); - break; - case fld::I18n_Type::POSIX : /* POSIX catgets */ - write_string("\ni18n_include"); write_word(proj_.i18n_pos_include.c_str()); - write_string("\ni18n_conditional"); write_word(proj_.i18n_pos_conditional.c_str()); - if (!proj_.i18n_pos_file.empty()) { - write_string("\ni18n_pos_file"); - write_word(proj_.i18n_pos_file.c_str()); - } - write_string("\ni18n_pos_set"); write_word(proj_.i18n_pos_set.c_str()); - break; - } - } + + proj_.i18n.write(*this); if (!selected_only) { write_string("\nheader_name"); write_word(proj_.header_file_name.c_str()); diff --git a/fluid/io/Project_Writer.h b/fluid/io/Project_Writer.h index 67aebb46e..4b21cf2fb 100644 --- a/fluid/io/Project_Writer.h +++ b/fluid/io/Project_Writer.h @@ -50,6 +50,7 @@ public: int open_write(const char *s); int close_write(); int write_project(const char *filename, int selected_only, bool codeview); + void NewFunction(); void write_word(const char *); void write_string(const char *,...) __fl_attr((__format__ (__printf__, 2, 3))); void write_indent(int n); diff --git a/fluid/io/String_Writer.cxx b/fluid/io/String_Writer.cxx index 6b70ec1f3..e96d2068e 100644 --- a/fluid/io/String_Writer.cxx +++ b/fluid/io/String_Writer.cxx @@ -56,7 +56,7 @@ static int write_escaped_strings(FILE *out, const char *text) { /** Write a file that contains all label and tooltip strings for internationalization. The user is responsible to set the right file name extension. The file format - is determined by `proj_.i18n_type`. + is determined by `proj_.i18n.type`. \param[in] filename file path and name to a file that will hold the strings \return 1 if the file could not be opened for writing, or the result of `fclose`. */ @@ -68,7 +68,7 @@ int fld::io::write_strings(Project &proj, const std::string &filename) { FILE *fp = fl_fopen(filename.c_str(), "wb"); if (!fp) return 1; - switch (proj.i18n_type) { + switch (proj.i18n.type) { case fld::I18n_Type::NONE : /* None, just put static text out */ fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); @@ -115,7 +115,7 @@ int fld::io::write_strings(Project &proj, const std::string &filename) { case fld::I18n_Type::POSIX : /* POSIX catgets, put a .msg file out */ fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); - fprintf(fp, "$set %s\n", proj.i18n_pos_set.c_str()); + fprintf(fp, "$set %s\n", proj.i18n.posix_set.c_str()); fputs("$quote \"\n", fp); for (i = 1, p = proj.tree.first; p; p = p->next) { diff --git a/fluid/nodes/Menu_Node.cxx b/fluid/nodes/Menu_Node.cxx index a4434a4dd..f5555644c 100644 --- a/fluid/nodes/Menu_Node.cxx +++ b/fluid/nodes/Menu_Node.cxx @@ -485,10 +485,10 @@ void Menu_Item_Node::write_item(fld::io::Code_Writer& f) { write_comment_inline_c(f, " "); f.write_c(" {"); if (label() && label()[0]) - switch (Fluid.proj.i18n_type) { + switch (Fluid.proj.i18n.type) { case fld::I18n_Type::GNU: // we will call i18n when the menu is instantiated for the first time - f.write_c("%s(", Fluid.proj.i18n_gnu_static_function.c_str()); + f.write_c("%s(", Fluid.proj.i18n.gnu_static_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; @@ -591,16 +591,16 @@ void Menu_Item_Node::write_code1(fld::io::Code_Writer& f) { f.write_c("%sml->labela = (char*)", f.indent()); image->write_inline(f); f.write_c(";\n"); - if (Fluid.proj.i18n_type==fld::I18n_Type::NONE) { + if (Fluid.proj.i18n.type==fld::I18n_Type::NONE) { f.write_c("%sml->labelb = o->label();\n", f.indent()); - } else if (Fluid.proj.i18n_type==fld::I18n_Type::GNU) { + } else if (Fluid.proj.i18n.type==fld::I18n_Type::GNU) { f.write_c("%sml->labelb = %s(o->label());\n", - f.indent(), Fluid.proj.i18n_gnu_function.c_str()); - } else if (Fluid.proj.i18n_type==fld::I18n_Type::POSIX) { + f.indent(), Fluid.proj.i18n.gnu_function.c_str()); + } else if (Fluid.proj.i18n.type==fld::I18n_Type::POSIX) { f.write_c("%sml->labelb = catgets(%s,%s,i+%d,o->label());\n", f.indent(), - Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), - Fluid.proj.i18n_pos_set.c_str(), msgnum()); + Fluid.proj.i18n.posix_file.empty() ? "_catalog" : Fluid.proj.i18n.posix_file.c_str(), + Fluid.proj.i18n.posix_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()); @@ -609,21 +609,21 @@ void Menu_Item_Node::write_code1(fld::io::Code_Writer& f) { image->write_code(f, 0, "o"); } } - if ((Fluid.proj.i18n_type != fld::I18n_Type::NONE) && label() && label()[0]) { + if ((Fluid.proj.i18n.type != fld::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 (Fluid.proj.i18n_type==fld::I18n_Type::GNU) { + if (Fluid.proj.i18n.type==fld::I18n_Type::GNU) { f.write_c("%so->label(%s(o->label()));\n", - f.indent(), Fluid.proj.i18n_gnu_function.c_str()); - } else if (Fluid.proj.i18n_type==fld::I18n_Type::POSIX) { + f.indent(), Fluid.proj.i18n.gnu_function.c_str()); + } else if (Fluid.proj.i18n.type==fld::I18n_Type::POSIX) { f.write_c("%so->label(catgets(%s,%s,i+%d,o->label()));\n", f.indent(), - Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), - Fluid.proj.i18n_pos_set.c_str(), msgnum()); + Fluid.proj.i18n.posix_file.empty() ? "_catalog" : Fluid.proj.i18n.posix_file.c_str(), + Fluid.proj.i18n.posix_set.c_str(), msgnum()); } } } diff --git a/fluid/nodes/Widget_Node.cxx b/fluid/nodes/Widget_Node.cxx index 95be9493d..2082941ce 100644 --- a/fluid/nodes/Widget_Node.cxx +++ b/fluid/nodes/Widget_Node.cxx @@ -1601,19 +1601,19 @@ void Widget_Node::write_code1(fld::io::Code_Writer& f) { } if (label() && *label()) { f.write_c(", "); - switch (Fluid.proj.i18n_type) { + switch (Fluid.proj.i18n.type) { case fld::I18n_Type::NONE : /* None */ f.write_cstring(label()); break; case fld::I18n_Type::GNU : /* GNU gettext */ - f.write_c("%s(", Fluid.proj.i18n_gnu_function.c_str()); + f.write_c("%s(", Fluid.proj.i18n.gnu_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; case fld::I18n_Type::POSIX : /* POSIX catgets */ f.write_c("catgets(%s,%s,%d,", - Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), - Fluid.proj.i18n_pos_set.c_str(), msgnum()); + Fluid.proj.i18n.posix_file.empty() ? "_catalog" : Fluid.proj.i18n.posix_file.c_str(), + Fluid.proj.i18n.posix_set.c_str(), msgnum()); f.write_cstring(label()); f.write_c(")"); break; @@ -1675,19 +1675,19 @@ void Widget_Node::write_widget_code(fld::io::Code_Writer& f) { if (tooltip() && *tooltip()) { f.write_c("%s%s->tooltip(",f.indent(), var); - switch (Fluid.proj.i18n_type) { + switch (Fluid.proj.i18n.type) { case fld::I18n_Type::NONE : /* None */ f.write_cstring(tooltip()); break; case fld::I18n_Type::GNU : /* GNU gettext */ - f.write_c("%s(", Fluid.proj.i18n_gnu_function.c_str()); + f.write_c("%s(", Fluid.proj.i18n.gnu_function.c_str()); f.write_cstring(tooltip()); f.write_c(")"); break; case fld::I18n_Type::POSIX : /* POSIX catgets */ f.write_c("catgets(%s,%s,%d,", - Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), - Fluid.proj.i18n_pos_set.c_str(), + Fluid.proj.i18n.posix_file.empty() ? "_catalog" : Fluid.proj.i18n.posix_file.c_str(), + Fluid.proj.i18n.posix_set.c_str(), msgnum() + 1); f.write_cstring(tooltip()); f.write_c(")"); diff --git a/fluid/nodes/Window_Node.cxx b/fluid/nodes/Window_Node.cxx index d6cbe80e6..5cc02a356 100644 --- a/fluid/nodes/Window_Node.cxx +++ b/fluid/nodes/Window_Node.cxx @@ -74,13 +74,13 @@ static void update_xywh() { void i18n_type_cb(Fl_Choice *c, void *v) { if (v == LOAD) { - c->value(static_cast<int>(Fluid.proj.i18n_type)); + c->value(static_cast<int>(Fluid.proj.i18n.type)); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_type = static_cast<fld::I18n_Type>(c->value()); + Fluid.proj.i18n.type = static_cast<fld::I18n_Type>(c->value()); Fluid.proj.set_modflag(1); } - switch (Fluid.proj.i18n_type) { + switch (Fluid.proj.i18n.type) { case fld::I18n_Type::NONE : /* None */ i18n_gnu_group->hide(); i18n_posix_group->hide(); diff --git a/fluid/panels/codeview_panel.cxx b/fluid/panels/codeview_panel.cxx index 3cf191618..3c46715bd 100644 --- a/fluid/panels/codeview_panel.cxx +++ b/fluid/panels/codeview_panel.cxx @@ -180,7 +180,7 @@ void update_codeview_cb(class Fl_Button*, void*) { char fn[FL_PATH_MAX+1]; fl_strlcpy(fn, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(fn, "strings", FL_PATH_MAX); - fl_filename_setext(fn, FL_PATH_MAX, exts[static_cast<int>(Fluid.proj.i18n_type)]); + fl_filename_setext(fn, FL_PATH_MAX, exts[static_cast<int>(Fluid.proj.i18n.type)]); fld::io::write_strings(Fluid.proj, fn); int top = cv_strings->top_line(); cv_strings->buffer()->loadfile(fn); diff --git a/fluid/panels/codeview_panel.fl b/fluid/panels/codeview_panel.fl index 3af688e16..612639c0d 100644 --- a/fluid/panels/codeview_panel.fl +++ b/fluid/panels/codeview_panel.fl @@ -209,7 +209,7 @@ and load those into the Code Viewer widgets.} open return_type void char fn[FL_PATH_MAX+1]; fl_strlcpy(fn, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(fn, "strings", FL_PATH_MAX); - fl_filename_setext(fn, FL_PATH_MAX, exts[static_cast<int>(Fluid.proj.i18n_type)]); + fl_filename_setext(fn, FL_PATH_MAX, exts[static_cast<int>(Fluid.proj.i18n.i18n_type)]); fld::io::write_strings(Fluid.proj, fn); int top = cv_strings->top_line(); cv_strings->buffer()->loadfile(fn); diff --git a/fluid/panels/settings_panel.cxx b/fluid/panels/settings_panel.cxx index a57c797c2..d695c535c 100644 --- a/fluid/panels/settings_panel.cxx +++ b/fluid/panels/settings_panel.cxx @@ -2137,10 +2137,10 @@ Fl_Input *i18n_gnu_include_input=(Fl_Input *)0; static void cb_i18n_gnu_include_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_include.c_str()); + o->value(Fluid.proj.i18n.gnu_include.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_include = o->value(); + Fluid.proj.i18n.gnu_include = o->value(); Fluid.proj.set_modflag(1); } } @@ -2149,10 +2149,10 @@ Fl_Input *i18n_gnu_conditional_input=(Fl_Input *)0; static void cb_i18n_gnu_conditional_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_conditional.c_str()); + o->value(Fluid.proj.i18n.gnu_conditional.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_conditional = o->value(); + Fluid.proj.i18n.gnu_conditional = o->value(); Fluid.proj.set_modflag(1); } } @@ -2161,10 +2161,10 @@ Fl_Input *i18n_gnu_function_input=(Fl_Input *)0; static void cb_i18n_gnu_function_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_function.c_str()); + o->value(Fluid.proj.i18n.gnu_function.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_function = o->value(); + Fluid.proj.i18n.gnu_function = o->value(); Fluid.proj.set_modflag(1); } } @@ -2173,10 +2173,10 @@ Fl_Input *i18n_gnu_static_function_input=(Fl_Input *)0; static void cb_i18n_gnu_static_function_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_static_function.c_str()); + o->value(Fluid.proj.i18n.gnu_static_function.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_static_function = o->value(); + Fluid.proj.i18n.gnu_static_function = o->value(); Fluid.proj.set_modflag(1); } } @@ -2191,10 +2191,10 @@ Fl_Input *i18n_pos_include_input=(Fl_Input *)0; static void cb_i18n_pos_include_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_include.c_str()); + o->value(Fluid.proj.i18n.posix_include.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_include = o->value(); + Fluid.proj.i18n.posix_include = o->value(); Fluid.proj.set_modflag(1); } } @@ -2203,10 +2203,10 @@ Fl_Input *i18n_pos_conditional_input=(Fl_Input *)0; static void cb_i18n_pos_conditional_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_conditional.c_str()); + o->value(Fluid.proj.i18n.posix_conditional.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_conditional = o->value(); + Fluid.proj.i18n.posix_conditional = o->value(); Fluid.proj.set_modflag(1); } } @@ -2215,10 +2215,10 @@ Fl_Input *i18n_pos_file_input=(Fl_Input *)0; static void cb_i18n_pos_file_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_file.c_str()); + o->value(Fluid.proj.i18n.posix_file.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_file = o->value(); + Fluid.proj.i18n.posix_file = o->value(); Fluid.proj.set_modflag(1); } } @@ -2231,10 +2231,10 @@ Fl_Int_Input *i18n_pos_set_input=(Fl_Int_Input *)0; static void cb_i18n_pos_set_input(Fl_Int_Input* o, void* v) { if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_set.c_str()); + o->value(Fluid.proj.i18n.posix_set.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_set = o->value(); + Fluid.proj.i18n.posix_set = o->value(); Fluid.proj.set_modflag(1); } } diff --git a/fluid/panels/settings_panel.fl b/fluid/panels/settings_panel.fl index dd1f61107..59c1a476d 100644 --- a/fluid/panels/settings_panel.fl +++ b/fluid/panels/settings_panel.fl @@ -1559,10 +1559,10 @@ if (v == LOAD) { Fl_Input i18n_gnu_include_input { label {\#include:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_include.c_str()); + o->value(Fluid.proj.i18n.i18n_gnu_include.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_include = o->value(); + Fluid.proj.i18n.i18n_gnu_include = o->value(); Fluid.proj.set_modflag(1); }} tooltip {The include file for internationalization.} xywh {100 103 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 @@ -1570,10 +1570,10 @@ if (v == LOAD) { Fl_Input i18n_gnu_conditional_input { label {Conditional:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_conditional.c_str()); + o->value(Fluid.proj.i18n.i18n_gnu_conditional.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_conditional = o->value(); + Fluid.proj.i18n.i18n_gnu_conditional = o->value(); Fluid.proj.set_modflag(1); }} tooltip {only include the header file if this preprocessor macro is defined, for example FLTK_GETTEXT_FOUND} xywh {100 128 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 @@ -1581,10 +1581,10 @@ if (v == LOAD) { Fl_Input i18n_gnu_function_input { label {Function:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_function.c_str()); + o->value(Fluid.proj.i18n.i18n_gnu_function.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_function = o->value(); + Fluid.proj.i18n.i18n_gnu_function = o->value(); Fluid.proj.set_modflag(1); }} 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 @@ -1592,10 +1592,10 @@ if (v == LOAD) { Fl_Input i18n_gnu_static_function_input { label {Static Function:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_gnu_static_function.c_str()); + o->value(Fluid.proj.i18n.i18n_gnu_static_function.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_gnu_static_function = o->value(); + Fluid.proj.i18n.i18n_gnu_static_function = o->value(); Fluid.proj.set_modflag(1); }} tooltip {function to call to translate static text, The function to call to internationalize labels and tooltips, usually "gettext_noop" or "N_"} xywh {100 178 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 @@ -1608,10 +1608,10 @@ if (v == LOAD) { Fl_Input i18n_pos_include_input { label {\#include:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_include.c_str()); + o->value(Fluid.proj.i18n.i18n_pos_include.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_include = o->value(); + Fluid.proj.i18n.i18n_pos_include = o->value(); Fluid.proj.set_modflag(1); }} tooltip {The include file for internationalization.} xywh {100 103 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 @@ -1619,10 +1619,10 @@ if (v == LOAD) { Fl_Input i18n_pos_conditional_input { label {Conditional:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_conditional.c_str()); + o->value(Fluid.proj.i18n.i18n_pos_conditional.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_conditional = o->value(); + Fluid.proj.i18n.i18n_pos_conditional = o->value(); Fluid.proj.set_modflag(1); }} tooltip {only include the header file if this preprocessor macro is defined, for example FLTK_GETTEXT_FOUND} xywh {100 128 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 @@ -1630,10 +1630,10 @@ if (v == LOAD) { Fl_Input i18n_pos_file_input { label {Catalog:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_file.c_str()); + o->value(Fluid.proj.i18n.i18n_pos_file.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_file = o->value(); + Fluid.proj.i18n.i18n_pos_file = o->value(); Fluid.proj.set_modflag(1); }} tooltip {The name of the message catalog.} xywh {100 153 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 @@ -1645,10 +1645,10 @@ if (v == LOAD) { Fl_Input i18n_pos_set_input { label {Set:} callback {if (v == LOAD) { - o->value(Fluid.proj.i18n_pos_set.c_str()); + o->value(Fluid.proj.i18n.i18n_pos_set.c_str()); } else { Fluid.proj.undo.checkpoint(); - Fluid.proj.i18n_pos_set = o->value(); + Fluid.proj.i18n.i18n_pos_set = o->value(); Fluid.proj.set_modflag(1); }} tooltip {The message set number.} xywh {100 178 80 20} type Int box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 diff --git a/fluid/proj/i18n.cxx b/fluid/proj/i18n.cxx new file mode 100644 index 000000000..a00dcf2f2 --- /dev/null +++ b/fluid/proj/i18n.cxx @@ -0,0 +1,93 @@ +// +// Fluid Project Internationalization code for the Fast Light Tool Kit (FLTK). +// +// Copyright 2025 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include "proj/i18n.h" + +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" + +using namespace fld; + +using namespace fld::proj; + + +/** + Reset all project setting to create a new empty project. + */ +void I18n::reset() { + type = fld::I18n_Type::NONE; + + gnu_include = "<libintl.h>"; + gnu_conditional = ""; + gnu_function = "gettext"; + gnu_static_function = "gettext_noop"; + + posix_include = "<nl_types.h>"; + posix_conditional = ""; + posix_file = ""; + posix_set = "1"; +} + +void I18n::read(io::Project_Reader &f, const char *key) { + if (!strcmp(key, "i18n_type")) { + type = static_cast<fld::I18n_Type>(atoi(f.read_word())); + } else if (!strcmp(key, "i18n_gnu_function")) { + gnu_function = f.read_word(); + } else if (!strcmp(key, "i18n_gnu_static_function")) { + gnu_static_function = f.read_word(); + } else if (!strcmp(key, "i18n_pos_file")) { + posix_file = f.read_word(); + } else if (!strcmp(key, "i18n_pos_set")) { + posix_set = f.read_word(); + } else if (!strcmp(key, "i18n_include")) { + if (type == fld::I18n_Type::GNU) { + gnu_include = f.read_word(); + } else if (type == fld::I18n_Type::POSIX) { + posix_include = f.read_word(); + } + } else if (!strcmp(key, "i18n_conditional")) { + if (type == fld::I18n_Type::GNU) { + gnu_conditional = f.read_word(); + } else if (type == fld::I18n_Type::POSIX) { + posix_conditional = f.read_word(); + } + } +} + +void I18n::write(io::Project_Writer &f) const { + if ((type != fld::I18n_Type::NONE)) { + f.write_string("\ni18n_type %d", static_cast<int>(type)); + switch (type) { + case fld::I18n_Type::NONE: + break; + case fld::I18n_Type::GNU : /* GNU gettext */ + f.write_string("\ni18n_include"); f.write_word(gnu_include.c_str()); + f.write_string("\ni18n_conditional"); f.write_word(gnu_conditional.c_str()); + f.write_string("\ni18n_gnu_function"); f.write_word(gnu_function.c_str()); + f.write_string("\ni18n_gnu_static_function"); f.write_word(gnu_static_function.c_str()); + break; + case fld::I18n_Type::POSIX : /* POSIX catgets */ + f.write_string("\ni18n_include"); f.write_word(posix_include.c_str()); + f.write_string("\ni18n_conditional"); f.write_word(posix_conditional.c_str()); + if (!posix_file.empty()) { + f.write_string("\ni18n_pos_file"); + f.write_word(posix_file.c_str()); + } + f.write_string("\ni18n_pos_set"); f.write_word(posix_set.c_str()); + break; + } + } +}
\ No newline at end of file diff --git a/fluid/proj/i18n.h b/fluid/proj/i18n.h new file mode 100644 index 000000000..30e09efae --- /dev/null +++ b/fluid/proj/i18n.h @@ -0,0 +1,88 @@ +// +// Fluid Project Internationalization header for the Fast Light Tool Kit (FLTK). +// +// Copyright 2025 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#ifndef FLUID_PROJ_I18N_H +#define FLUID_PROJ_I18N_H + +#include <string> + +namespace fld { + +class Project; + +/** + Enumeration of available internationalization types. + */ +enum class I18n_Type { + NONE = 0, ///< No i18n, all strings are litearals + GNU, ///< GNU gettext internationalization + POSIX ///< Posix catgets internationalization +}; + +namespace io { +class Project_Reader; +class Project_Writer; +} + +namespace proj { + +/** + Data and settings for a FLUID project file. + */ +class I18n +{ +public: + Project &project_; + + /// One of the available internationalization types. + fld::I18n_Type type = I18n_Type::NONE; + /// Include file for GNU i18n, writes an #include statement into the source + /// file. This is usually `<libintl.h>` or `"gettext.h"` for GNU gettext. + std::string gnu_include = "<libintl.h>"; + // Optional name of a macro for conditional i18n compilation. + std::string gnu_conditional = ""; + /// For the gettext/intl.h options, this is the function that translates text + /// at runtime. This is usually "gettext" or "_". + std::string gnu_function = "gettext"; + /// For the gettext/intl.h options, this is the function that marks the translation + /// of text at initialisation time. This is usually "gettext_noop" or "N_". + std::string gnu_static_function = "gettext_noop"; + + /// Include file for Posix i18n, write a #include statement into the source + /// file. This is usually `<nl_types.h>` for Posix catgets. + std::string posix_include = "<nl_types.h>"; + // Optional name of a macro for conditional i18n compilation. + std::string posix_conditional = ""; + /// Name of the nl_catd database + std::string posix_file = ""; + /// Message set ID for the catalog. + std::string posix_set = "1"; + +public: // Methods + I18n(Project &p) : project_(p) {}; + ~I18n() = default; + void reset(); + void read(io::Project_Reader &f, const char *key); + void write(io::Project_Writer &f) const; +}; + +} // namespace proj + +} // namespace fld + +#endif // FLUID_PROJ_I18N_H + + |
