summaryrefslogtreecommitdiff
path: root/fluid/Fl_Function_Type.cxx
diff options
context:
space:
mode:
authorMatthias Melcher <git@matthiasm.com>2021-12-08 15:52:15 +0100
committerMatthias Melcher <git@matthiasm.com>2021-12-08 15:52:15 +0100
commit16dae3ea063ae134b8b87ca199575e904dfbb7d4 (patch)
treeff0ce9e635bb39f49bfcce2c5e7fe099334a0d15 /fluid/Fl_Function_Type.cxx
parent2d18c6f650c0001319c8883f8deb819d12984ac0 (diff)
Fluid: restructuring and commenting.
tl;dr : making Fluid maintainable, no changes in code execution and logic. This is a pretty extensive restructuring of the Fluid source tree. It was neccessary because source and header files were getting much too big to handle. Many source files had no header, and many headers declared functions that were in diffrent source files. Reorganized much of the include statements. Added comments to some of the files. Added Doxygen configuration file for standalone Fluid docs. Tested everything by rebuilding Fluid .fl designs with the resorted version of Fluid.
Diffstat (limited to 'fluid/Fl_Function_Type.cxx')
-rw-r--r--fluid/Fl_Function_Type.cxx619
1 files changed, 503 insertions, 116 deletions
diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx
index 2ece47e38..f8b9cd276 100644
--- a/fluid/Fl_Function_Type.cxx
+++ b/fluid/Fl_Function_Type.cxx
@@ -13,46 +13,58 @@
//
// https://www.fltk.org/bugs.php
//
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Preferences.H>
-#include <FL/Fl_File_Chooser.H>
+
+#include "Fl_Function_Type.h"
+
+#include "fluid.h"
+#include "Fl_Window_Type.h"
+#include "Fl_Group_Type.h"
+#include "widget_browser.h"
+#include "file.h"
+#include "code.h"
+#include "function_panel.h"
+#include "comments.h"
+
#include <FL/fl_string.h>
-#include "Fl_Type.h"
-#include <FL/fl_show_input.H>
#include <FL/Fl_File_Chooser.H>
-#include "alignment_panel.h"
+#include <FL/fl_ask.H>
#include "../src/flstring.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _WIN32
- #include "ExternalCodeEditor_WIN32.h"
-#else
- #include "ExternalCodeEditor_UNIX.h"
-#endif
-
-extern int i18n_type;
-extern const char* i18n_include;
-extern const char* i18n_function;
-extern const char* i18n_file;
-extern const char* i18n_set;
-extern char i18n_program[];
-
-extern int batch_mode;
-
-extern void redraw_browser();
-extern void goto_source_dir();
-extern void leave_source_dir();
-extern Fl_Window *main_window;
+
+/// Set a current class, so that the code of the children is generated correctly.
+Fl_Class_Type *current_class = NULL;
+
+/**
+ Return 1 if the list contains a function with the given signature at the top level.
+ \param[in] rtype return type
+ \param[in] sig function signature
+ \return 1 if found.
+ */
+int has_toplevel_function(const char *rtype, const char *sig) {
+ Fl_Type *child;
+ for (child = Fl_Type::first; child; child = child->next) {
+ if (!child->is_in_class() && strcmp(child->type_name(), "Function")==0) {
+ const Fl_Function_Type *fn = (const Fl_Function_Type*)child;
+ if (fn->has_signature(rtype, sig))
+ return 1;
+ }
+ }
+ return 0;
+}
+
////////////////////////////////////////////////////////////////
// quick check of any C code for legality, returns an error message
static char buffer[128]; // for error messages
-// check a quoted string ending in either " or ' or >:
+/**
+ Check a quoted string contains a character.
+ This is used to find a matchin " or ' in a string.
+ \param[inout] c start searching here, return where we found \c type
+ \param[in] type find this character
+ \return NULL if the character was found, else a pointer to a static string
+ with an error message
+ */
const char *_q_check(const char * & c, int type) {
for (;;) switch (*c++) {
case '\0':
@@ -66,7 +78,15 @@ const char *_q_check(const char * & c, int type) {
}
}
-// check normal code, match braces and parenthesis:
+/**
+ Check normal code, match brackets and parenthesis.
+ Recursively run a line of code and make sure that
+ {, ", ', and ( are matched.
+ \param[inout] c start searching here, return the end of the search
+ \param[in] type find this character match
+ \return NULL if the character was found, else a pointer to a static string
+ with an error message
+ */
const char *_c_check(const char * & c, int type) {
const char *d;
for (;;) switch (*c++) {
@@ -117,14 +137,58 @@ const char *_c_check(const char * & c, int type) {
}
}
+/**
+ Check legality of c code (sort of) and return error:
+ Make sure that {, ", ', and ( are matched.
+ \param[in] c start searching here
+ \param[in] type find this character match
+ \return NULL if the character was found, else a pointer to a static string
+ with an error message
+ \note This function checks every conceivable line of code, which is not
+ always wanted. It can't differentiate characters in comments, and the
+ user may well intend to leave a curly bracket open
+ (i.e. namesapece { ... } ). We should make this option user selectable.
+ */
const char *c_check(const char *c, int type) {
return _c_check(c,type);
}
-////////////////////////////////////////////////////////////////
+// ---- Fl_Function_Type implemntation
+
+/** \class Fl_Function_Type
+ Manage a C++ function node in the Fluid design.
+
+ A function can have a signature (name followed by arguments), a return type
+ and a comment section. If can be local or global, and it can be declared a C
+ or C++ function.
+ */
+
+/// Prototype for a function to be used by the factory.
+Fl_Function_Type Fl_Function_type;
+
+/**
+ Create a new function.
+ */
+Fl_Function_Type::Fl_Function_Type() :
+ Fl_Type(),
+ return_type(0L),
+ public_(0),
+ cdecl_(0),
+ constructor(0),
+ havewidgets(0)
+{ }
-int Fl_Function_Type::is_public() const {return public_;}
+/**
+ Destructor.
+ */
+Fl_Function_Type::~Fl_Function_Type() {
+ if (return_type) free((void*)return_type);
+}
+/**
+ Create a new function for the widget tree.
+ \return the new node
+ */
Fl_Type *Fl_Function_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_decl_block()) p = p->parent;
@@ -138,6 +202,12 @@ Fl_Type *Fl_Function_Type::make() {
return o;
}
+/**
+ Write function specific properties to an .fl file.
+ - "private"/"public" indicates the state of the function
+ - "C" is written if we want a C signature instead of C++
+ - "return_type" is followed by the return type of the function
+ */
void Fl_Function_Type::write_properties() {
Fl_Type::write_properties();
switch (public_) {
@@ -151,6 +221,10 @@ void Fl_Function_Type::write_properties() {
}
}
+/**
+ Read function specific properties fron an .fl file.
+ \param[in] c read from this string
+ */
void Fl_Function_Type::read_property(const char *c) {
if (!strcmp(c,"private")) {
public_ = 0;
@@ -165,9 +239,9 @@ void Fl_Function_Type::read_property(const char *c) {
}
}
-#include "function_panel.h"
-#include <FL/fl_ask.H>
-
+/**
+ Open the function_panel dialog box to edit this function.
+ */
void Fl_Function_Type::open() {
if (!function_panel) make_function_panel();
f_return_type_input->static_value(return_type);
@@ -240,10 +314,19 @@ BREAK2:
function_panel->hide();
}
-Fl_Function_Type Fl_Function_type;
-
-extern const char* subclassname(Fl_Type*);
+/**
+ Return 1 if the function is global.
+ \return 1 if public, 0 if local.
+ */
+int Fl_Function_Type::is_public() const {
+ return public_;
+}
+/**
+ Write the code for the source and the header file.
+ This writes the code that goes \b before all children of this class.
+ \see write_code2()
+ */
void Fl_Function_Type::write_code1() {
constructor=0;
havewidgets = 0;
@@ -397,6 +480,11 @@ void Fl_Function_Type::write_code1() {
indentation += 2;
}
+/**
+ Write the code for the source and the header file.
+ This writes the code that goes \b after all children of this class.
+ \see write_code1()
+ */
void Fl_Function_Type::write_code2() {
Fl_Type *child;
const char *var = "w";
@@ -417,6 +505,12 @@ void Fl_Function_Type::write_code2() {
indentation = 0;
}
+/**
+ Check if the return type and signature s match.
+ \param[in] rtype function return type
+ \param[in] sig function name followed by arguments
+ \return 1 if they match, 0 if not
+ */
int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const {
if (rtype && !return_type) return 0;
if (!name()) return 0;
@@ -427,8 +521,35 @@ int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const {
return 0;
}
-////////////////////////////////////////////////////////////////
+// ---- Fl_Code_Type declaration
+
+/** \class Fl_Code_Type
+ Manage a block of C++ code in the Fluid design.
+
+ This node manages an arbitrary block of code inside a function that will
+ be written into the source code file. Fl_Code_Block has no comment field.
+ However, the first line of code will be shown in the widget browser.
+
+ \todo Fl_Code_Block stores the cursor position in text editor, but it does not
+ store the view position (scrollbars). Make sure that we can always see
+ the cursor when opening the dialog. (it's not stored in the .fl file)
+ */
+
+/// Prototype for code to be used by the factory.
+Fl_Code_Type Fl_Code_type;
+
+/**
+ Constructor.
+ */
+Fl_Code_Type::Fl_Code_Type() {
+ cursor_position_ = 0;
+}
+/**
+ Make a new code node.
+ If the parent node is not a function, a message box will pop up and
+ the request will be ignored.
+ */
Fl_Type *Fl_Code_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_code_block()) p = p->parent;
@@ -443,6 +564,9 @@ Fl_Type *Fl_Code_Type::make() {
return o;
}
+/**
+ Open the code_panel or an external editor to edit this code section.
+ */
void Fl_Code_Type::open() {
// Using an external code editor? Open it..
if ( G_use_external_editor && G_external_editor_command[0] ) {
@@ -477,8 +601,9 @@ BREAK2:
code_panel->hide();
}
-Fl_Code_Type Fl_Code_type;
-
+/**
+ Grab changes from an external editor and write this node.
+ */
void Fl_Code_Type::write() {
// External editor changes? If so, load changes into ram, update mtime/size
if ( handle_editor_changes() == 1 ) {
@@ -487,6 +612,9 @@ void Fl_Code_Type::write() {
Fl_Type::write();
}
+/**
+ Write the code block with the correct indentation.
+ */
void Fl_Code_Type::write_code1() {
// External editor changes? If so, load changes into ram, update mtime/size
if ( handle_editor_changes() == 1 ) {
@@ -513,10 +641,82 @@ void Fl_Code_Type::write_code1() {
write_c("\n");
}
-void Fl_Code_Type::write_code2() {}
+/**
+ See if external editor is open.
+ */
+int Fl_Code_Type::is_editing() {
+ return editor_.is_editing();
+}
-////////////////////////////////////////////////////////////////
+/**
+ Reap the editor's pid
+ \return -2: editor not open
+ \return -1: wait failed
+ \return 0: process still running
+ \return \>0: process finished + reaped (returns pid)
+ */
+int Fl_Code_Type::reap_editor() {
+ return editor_.reap_editor();
+}
+
+/**
+ Handle external editor file modifications.
+ If changed, record keeping is updated and file's contents is loaded into ram
+ \return 0: file unchanged or not editing
+ \return 1: file changed, internal records updated, 'code' has new content
+ \return -1: error getting file info (get_ms_errmsg() has reason)
+ \todo Figure out how saving a fluid file can be intercepted to grab
+ current contents of editor file..
+ */
+int Fl_Code_Type::handle_editor_changes() {
+ const char *newcode = 0;
+ switch ( editor_.handle_changes(&newcode) ) {
+ case 1: { // (1)=changed
+ name(newcode); // update value in ram
+ free((void*)newcode);
+ return 1;
+ }
+ case -1: return -1; // (-1)=error -- couldn't read file (dialog showed reason)
+ default: break; // (0)=no change
+ }
+ return 0;
+}
+
+// ---- Fl_CodeBlock_Type implemntation
+
+/** \class Fl_CodeBlock_Type
+ Manage two blocks of C++ code enclosing its children.
+
+ This node manages two lines of code that enclose all children
+ of this node. This is usually an if..then clause.
+
+ \todo this node could support multiple lines of code for each block.
+ */
+
+/// Prototype for a block of code to be used by the factory.
+Fl_CodeBlock_Type Fl_CodeBlock_type;
+/**
+ Constructor.
+ */
+Fl_CodeBlock_Type::Fl_CodeBlock_Type() :
+ Fl_Type(),
+ after(NULL)
+{ }
+
+/**
+ Destructor.
+ */
+Fl_CodeBlock_Type::~Fl_CodeBlock_Type() {
+ if (after)
+ free((void*)after);
+}
+
+/**
+ Make a new code block.
+ If the parent node is not a function or another codeblock, a message box will
+ pop up and the request will be ignored.
+ */
Fl_Type *Fl_CodeBlock_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_code_block()) p = p->parent;
@@ -532,6 +732,11 @@ Fl_Type *Fl_CodeBlock_Type::make() {
return o;
}
+/**
+ Write the specific properties for this node.
+ - "after" is followed by the code that comes after the children
+ The "before" code is stored in the name() field.
+ */
void Fl_CodeBlock_Type::write_properties() {
Fl_Type::write_properties();
if (after) {
@@ -540,6 +745,9 @@ void Fl_CodeBlock_Type::write_properties() {
}
}
+/**
+ Read the node specifc properties.
+ */
void Fl_CodeBlock_Type::read_property(const char *c) {
if (!strcmp(c,"after")) {
storestring(read_word(),after);
@@ -548,6 +756,9 @@ void Fl_CodeBlock_Type::read_property(const char *c) {
}
}
+/**
+ Open the codeblock_panel.
+ */
void Fl_CodeBlock_Type::open() {
if (!codeblock_panel) make_codeblock_panel();
code_before_input->static_value(name());
@@ -574,22 +785,49 @@ BREAK2:
codeblock_panel->hide();
}
-Fl_CodeBlock_Type Fl_CodeBlock_type;
-
+/**
+ Write the "before" code.
+ */
void Fl_CodeBlock_Type::write_code1() {
const char* c = name();
write_c("%s%s {\n", indent(), c ? c : "");
indentation += 2;
}
+/**
+ Write the "after" code.
+ */
void Fl_CodeBlock_Type::write_code2() {
indentation -= 2;
if (after) write_c("%s} %s\n", indent(), after);
else write_c("%s}\n", indent());
}
-////////////////////////////////////////////////////////////////
+// ---- Fl_Decl_Type declaration
+/** \class Fl_Decl_Type
+ Manage the C/C++ declaration of a variable.
+
+ This node manages a single line of code that can be in the header or the source
+ code, and can be made static.
+
+ \todo this node could support multiple lines.
+ */
+
+/// Prototype for a declaration to be used by the factory.
+Fl_Decl_Type Fl_Decl_type;
+
+/**
+ Constructor.
+ */
+Fl_Decl_Type::Fl_Decl_Type() :
+ public_(0),
+ static_(1)
+{ }
+
+/**
+ Return 1 if this declaration and its parents are public.
+ */
int Fl_Decl_Type::is_public() const
{
Fl_Type *p = parent;
@@ -601,6 +839,9 @@ int Fl_Decl_Type::is_public() const
return 0;
}
+/**
+ Make a new declaration.
+ */
Fl_Type *Fl_Decl_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_decl_block()) p = p->parent;
@@ -613,6 +854,11 @@ Fl_Type *Fl_Decl_Type::make() {
return o;
}
+/**
+ Write the specific properties.
+ - "private"/"public"/"protected"
+ - "local"/"global" if this is static or not
+ */
void Fl_Decl_Type::write_properties() {
Fl_Type::write_properties();
switch (public_) {
@@ -626,6 +872,9 @@ void Fl_Decl_Type::write_properties() {
write_string("global");
}
+/**
+ Read the specific properties.
+ */
void Fl_Decl_Type::read_property(const char *c) {
if (!strcmp(c,"public")) {
public_ = 1;
@@ -642,6 +891,9 @@ void Fl_Decl_Type::read_property(const char *c) {
}
}
+/**
+ Open the decl_panel to edit this node.
+ */
void Fl_Decl_Type::open() {
if (!decl_panel) make_decl_panel();
decl_input->static_value(name());
@@ -701,8 +953,11 @@ BREAK2:
decl_panel->hide();
}
-Fl_Decl_Type Fl_Decl_type;
-
+/**
+ Write the code to the source and header files.
+ \todo There are a lot of side effect in this node depending on the given text
+ and the parent node which should really be documented.
+ */
void Fl_Decl_Type::write_code1() {
const char* c = name();
if (!c) return;
@@ -767,10 +1022,38 @@ void Fl_Decl_Type::write_code1() {
}
}
-void Fl_Decl_Type::write_code2() {}
+// ---- Fl_Data_Type declaration
-////////////////////////////////////////////////////////////////
+/** \class Fl_Data_Type
+ Manage data from an external arbitrary file.
+ The content of the file will be stored in binary inside the generated
+ code. This can be used to store images inline in the source code,
+ */
+
+/// Prototype for a data node to be used by the factory.
+Fl_Data_Type Fl_Data_type;
+
+/**
+ Constructor.
+ */
+Fl_Data_Type::Fl_Data_Type() :
+ Fl_Decl_Type(),
+ filename_(NULL),
+ text_mode_(0)
+{ }
+
+/**
+ Destructor.
+ */
+Fl_Data_Type::~Fl_Data_Type() {
+ if (filename_)
+ free((void*)filename_);
+}
+
+/**
+ Create an empty inline data node.
+ */
Fl_Type *Fl_Data_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_decl_block()) p = p->parent;
@@ -785,6 +1068,11 @@ Fl_Type *Fl_Data_Type::make() {
return o;
}
+/**
+ Write additional properties.
+ - "filename" followed by the filename of the file to inline
+ - "textmode" if data is written in ASCII vs. binary
+ */
void Fl_Data_Type::write_properties() {
Fl_Decl_Type::write_properties();
if (filename_) {
@@ -796,6 +1084,9 @@ void Fl_Data_Type::write_properties() {
}
}
+/**
+ Read specific properties.
+ */
void Fl_Data_Type::read_property(const char *c) {
if (!strcmp(c,"filename")) {
storestring(read_word(), filename_, 1);
@@ -806,6 +1097,9 @@ void Fl_Data_Type::read_property(const char *c) {
}
}
+/**
+ Open the data_panel to edit this node.
+ */
void Fl_Data_Type::open() {
if (!data_panel) make_data_panel();
data_input->static_value(name());
@@ -908,8 +1202,9 @@ BREAK2:
data_panel->hide();
}
-Fl_Data_Type Fl_Data_type;
-
+/**
+ Write the content of the external file inline into the source code.
+ */
void Fl_Data_Type::write_code1() {
const char *message = 0;
const char *c = name();
@@ -1005,12 +1300,43 @@ void Fl_Data_Type::write_code1() {
if (data) free(data);
}
-void Fl_Data_Type::write_code2() {}
+// ---- Fl_DeclBlock_Type declaration
-////////////////////////////////////////////////////////////////
+/** \class Fl_DeclBlock_Type
+ Manage a declaration block.
+
+ Declaration blocks have two text field that are written before and after
+ the children of this block. This block is located at the top level and
+ is written to the source file, and to the header file, if declared public.
+ */
+/// Prototype for a declaration block to be used by the factory.
+Fl_DeclBlock_Type Fl_DeclBlock_type;
+
+/**
+ Constructor.
+ */
+Fl_DeclBlock_Type::Fl_DeclBlock_Type() :
+ Fl_Type(),
+ after(NULL)
+{ }
+
+/**
+ Destructor.
+ */
+Fl_DeclBlock_Type::~Fl_DeclBlock_Type() {
+ if (after)
+ free((void*)after);
+}
+
+/**
+ Return 1 if this block is public.
+ */
int Fl_DeclBlock_Type::is_public() const {return public_;}
+/**
+ Create a new declaration block.
+ */
Fl_Type *Fl_DeclBlock_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_decl_block()) p = p->parent;
@@ -1023,6 +1349,11 @@ Fl_Type *Fl_DeclBlock_Type::make() {
return o;
}
+/**
+ Write the specific properties.
+ - "public"/"protected"
+ - "after" followed by the second code block.
+ */
void Fl_DeclBlock_Type::write_properties() {
Fl_Type::write_properties();
switch (public_) {
@@ -1033,6 +1364,9 @@ void Fl_DeclBlock_Type::write_properties() {
write_word(after);
}
+/**
+ Read the specific properties.
+ */
void Fl_DeclBlock_Type::read_property(const char *c) {
if(!strcmp(c,"public")) {
public_ = 1;
@@ -1045,6 +1379,9 @@ void Fl_DeclBlock_Type::read_property(const char *c) {
}
}
+/**
+ Open the declblock_panel to edit this node.
+ */
void Fl_DeclBlock_Type::open() {
if (!declblock_panel) make_declblock_panel();
decl_before_input->static_value(name());
@@ -1081,8 +1418,10 @@ BREAK2:
declblock_panel->hide();
}
-Fl_DeclBlock_Type Fl_DeclBlock_type;
-
+/**
+ Write the \b before code to the source file, and to the header file if declared public.
+ The before code is stored in the name() field.
+ */
void Fl_DeclBlock_Type::write_code1() {
const char* c = name();
if (public_)
@@ -1090,6 +1429,9 @@ void Fl_DeclBlock_Type::write_code1() {
write_c("%s\n", c);
}
+/**
+ Write the \b after code to the source file, and to the header file if declared public.
+ */
void Fl_DeclBlock_Type::write_code2() {
const char* c = after;
if (public_)
@@ -1097,8 +1439,31 @@ void Fl_DeclBlock_Type::write_code2() {
write_c("%s\n", c);
}
-////////////////////////////////////////////////////////////////
+// ---- Fl_Comment_Type declaration
+
+/** \class Fl_Comment_Type
+ Manage a comment node.
+
+ The comment field takes one or more lines of ASCII text. If the text starts
+ with a '/' and a '*', Fluid assumes that the text is already formatted. If not,
+ every line will be preceded with "// ".
+ */
+/// Prototype for a comment node to be used by the factory.
+Fl_Comment_Type Fl_Comment_type;
+
+/**
+ Constructor.
+ */
+Fl_Comment_Type::Fl_Comment_Type() :
+ in_c_(1),
+ in_h_(1),
+ style_(0)
+{ }
+
+/**
+ Make a new comment node.
+ */
Fl_Type *Fl_Comment_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_code_block()) p = p->parent;
@@ -1113,12 +1478,20 @@ Fl_Type *Fl_Comment_Type::make() {
return o;
}
+/**
+ Write respective properties.
+ - "in_source"/"not_in_source" if the comment will be written to the source code
+ - "in_header"/"not_in_header" if the comment will be written to the header file
+ */
void Fl_Comment_Type::write_properties() {
Fl_Type::write_properties();
if (in_c_) write_string("in_source"); else write_string("not_in_source");
if (in_h_) write_string("in_header"); else write_string("not_in_header");
}
+/**
+ Read extra properties.
+ */
void Fl_Comment_Type::read_property(const char *c) {
if (!strcmp(c,"in_source")) {
in_c_ = 1;
@@ -1133,8 +1506,12 @@ void Fl_Comment_Type::read_property(const char *c) {
}
}
-#include "comments.h"
-
+/**
+ Load available preset comments.
+ Fluid comes with GPL and LGPL preset for comments. Users can
+ add their own presets which are stored per user in a seperate
+ preferences database.
+ */
static void load_comments_preset(Fl_Preferences &menu) {
static const char * const predefined_comment[] = {
"GNU Public License/GPL Header", "GNU Public License/GPL Footer",
@@ -1149,6 +1526,9 @@ static void load_comments_preset(Fl_Preferences &menu) {
}
}
+/**
+ Open the comment_panel to edit this node.
+ */
void Fl_Comment_Type::open() {
if (!comment_panel) make_comment_panel();
const char *text = name();
@@ -1268,6 +1648,9 @@ BREAK2:
comment_panel->hide();
}
+/**
+ Create a title for the Widget Browser by extracting the first 50 characters of the comment.
+ */
const char *Fl_Comment_Type::title() {
const char* n = name();
if (!n || !*n) return type_name();
@@ -1289,8 +1672,9 @@ const char *Fl_Comment_Type::title() {
return title_buf;
}
-Fl_Comment_Type Fl_Comment_type;
-
+/**
+ Write the comment to the files.
+ */
void Fl_Comment_Type::write_code1() {
const char* c = name();
if (!c) return;
@@ -1331,66 +1715,74 @@ void Fl_Comment_Type::write_code1() {
free(txt);
}
-void Fl_Comment_Type::write_code2() {}
+// ---- Fl_Class_Type declaration
-////////////////////////////////////////////////////////////////
+/** \class Fl_Class_Type
+ Manage a class declaration and implementation.
-const char* Fl_Type::class_name(const int need_nest) const {
- Fl_Type* p = parent;
- while (p) {
- if (p->is_class()) {
- // see if we are nested in another class, we must fully-qualify name:
- // this is lame but works...
- const char* q = 0;
- if(need_nest) q=p->class_name(need_nest);
- if (q) {
- static char s[256];
- if (q != s) strlcpy(s, q, sizeof(s));
- strlcat(s, "::", sizeof(s));
- strlcat(s, p->name(), sizeof(s));
- return s;
- }
- return p->name();
- }
- p = p->parent;
- }
- return 0;
-}
+ \todo This is pretty complex and needs to be revisited to give
+ a good description.
+ */
+
+/// Prototype for a class node to be used by the factory.
+Fl_Class_Type Fl_Class_type;
/**
- If this Type resides inside a class, this function returns the class type, or null.
+ Constructor.
*/
-const Fl_Class_Type *Fl_Type::is_in_class() const {
- Fl_Type* p = parent;
- while (p) {
- if (p->is_class()) {
- return (Fl_Class_Type*)p;
- }
- p = p->parent;
- }
- return 0;
+Fl_Class_Type::Fl_Class_Type() :
+ Fl_Type(),
+ subclass_of(NULL),
+ public_(1),
+ class_prefix(NULL)
+{ }
+
+/**
+ Destructor.
+ */
+Fl_Class_Type::~Fl_Class_Type() {
+ if (subclass_of)
+ free((void*)subclass_of);
+ if (class_prefix)
+ free((void*)class_prefix);
}
-int Fl_Class_Type::is_public() const {return public_;}
+/**
+ Return 1 if this class is marked public.
+ */
+int Fl_Class_Type::is_public() const {
+ return public_;
+}
+/**
+ Set the prefixx string.
+ */
void Fl_Class_Type::prefix(const char*p) {
free((void*) class_prefix);
class_prefix=fl_strdup(p ? p : "" );
}
+/**
+ Make a new class node.
+ */
Fl_Type *Fl_Class_Type::make() {
Fl_Type *p = Fl_Type::current;
while (p && !p->is_decl_block()) p = p->parent;
Fl_Class_Type *o = new Fl_Class_Type();
o->name("UserInterface");
- o->class_prefix=0;
- o->subclass_of = 0;
+ o->class_prefix = NULL;
+ o->subclass_of = NULL;
o->public_ = 1;
o->add(p);
o->factory = this;
return o;
}
+/**
+ Write the respective properties.
+ - ":" followed by the super class
+ - "private"/"protected"
+ */
void Fl_Class_Type::write_properties() {
Fl_Type::write_properties();
if (subclass_of) {
@@ -1403,6 +1795,9 @@ void Fl_Class_Type::write_properties() {
}
}
+/**
+ Read additional properties.
+ */
void Fl_Class_Type::read_property(const char *c) {
if (!strcmp(c,"private")) {
public_ = 0;
@@ -1415,6 +1810,9 @@ void Fl_Class_Type::read_property(const char *c) {
}
}
+/**
+ Open the class_panel to edit the class name and superclass name.
+ */
void Fl_Class_Type::open() {
if (!class_panel) make_class_panel();
char fullname[FL_PATH_MAX]="";
@@ -1485,23 +1883,9 @@ BREAK2:
class_panel->hide();
}
-Fl_Class_Type Fl_Class_type;
-
-Fl_Class_Type *current_class;
-extern Fl_Widget_Class_Type *current_widget_class;
-void write_public(int state) {
- if (!current_class && !current_widget_class) return;
- if (current_class && current_class->write_public_state == state) return;
- if (current_widget_class && current_widget_class->write_public_state == state) return;
- if (current_class) current_class->write_public_state = state;
- if (current_widget_class) current_widget_class->write_public_state = state;
- switch (state) {
- case 0: write_h("private:\n"); break;
- case 1: write_h("public:\n"); break;
- case 2: write_h("protected:\n"); break;
- }
-}
-
+/**
+ Write the header code that declares this class.
+ */
void Fl_Class_Type::write_code1() {
parent_class = current_class;
current_class = this;
@@ -1516,6 +1900,9 @@ void Fl_Class_Type::write_code1() {
write_h("{\n");
}
+/**
+ Write the header code that ends the declaration of this class.
+ */
void Fl_Class_Type::write_code2() {
write_h("};\n");
current_class = parent_class;