summaryrefslogtreecommitdiff
path: root/fluid
diff options
context:
space:
mode:
Diffstat (limited to 'fluid')
-rw-r--r--fluid/CMakeLists.txt13
-rw-r--r--fluid/CodeEditor.cxx97
-rw-r--r--fluid/CodeEditor.h36
-rw-r--r--fluid/ExternalCodeEditor_UNIX.cxx230
-rw-r--r--fluid/ExternalCodeEditor_UNIX.h7
-rw-r--r--fluid/Fl_Function_Type.cxx619
-rw-r--r--fluid/Fl_Function_Type.h230
-rw-r--r--fluid/Fl_Group_Type.cxx17
-rw-r--r--fluid/Fl_Group_Type.h158
-rw-r--r--fluid/Fl_Menu_Type.cxx31
-rw-r--r--fluid/Fl_Menu_Type.h212
-rw-r--r--fluid/Fl_Type.cxx846
-rw-r--r--fluid/Fl_Type.h842
-rw-r--r--fluid/Fl_Widget_Type.cxx40
-rw-r--r--fluid/Fl_Widget_Type.h91
-rw-r--r--fluid/Fl_Window_Type.cxx29
-rw-r--r--fluid/Fl_Window_Type.h125
-rw-r--r--fluid/Fluid_Image.cxx18
-rw-r--r--fluid/Fluid_Image.h5
-rw-r--r--fluid/Makefile2
-rw-r--r--fluid/Shortcut_Button.h6
-rw-r--r--fluid/StyleParse.cxx3
-rw-r--r--fluid/about_panel.cxx2
-rw-r--r--fluid/about_panel.fl10
-rw-r--r--fluid/about_panel.h2
-rw-r--r--fluid/align_widget.cxx8
-rw-r--r--fluid/align_widget.h25
-rw-r--r--fluid/alignment_panel.fl65
-rw-r--r--fluid/alignment_panel.h9
-rw-r--r--fluid/code.cxx114
-rw-r--r--fluid/code.h44
-rw-r--r--fluid/factory.cxx11
-rw-r--r--fluid/factory.h29
-rw-r--r--fluid/file.cxx195
-rw-r--r--fluid/file.h40
-rw-r--r--fluid/fluid.cxx835
-rw-r--r--fluid/fluid.h118
-rw-r--r--fluid/function_panel.cxx10
-rw-r--r--fluid/function_panel.fl79
-rw-r--r--fluid/print_panel.cxx9
-rw-r--r--fluid/print_panel.fl19
-rw-r--r--fluid/shell_command.cxx234
-rw-r--r--fluid/shell_command.h67
-rw-r--r--fluid/template_panel.cxx13
-rw-r--r--fluid/template_panel.fl28
-rw-r--r--fluid/undo.cxx15
-rw-r--r--fluid/undo.h4
-rw-r--r--fluid/widget_browser.cxx507
-rw-r--r--fluid/widget_browser.h62
-rw-r--r--fluid/widget_panel.cxx2
-rw-r--r--fluid/widget_panel.fl12
51 files changed, 3800 insertions, 2425 deletions
diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt
index ffcb4c4c1..d45b7b1b7 100644
--- a/fluid/CMakeLists.txt
+++ b/fluid/CMakeLists.txt
@@ -33,8 +33,10 @@ set (CPPFILES
fluid.cxx
function_panel.cxx
pixmaps.cxx
+ shell_command.cxx
template_panel.cxx
undo.cxx
+ widget_browser.cxx
widget_panel.cxx
)
@@ -42,19 +44,30 @@ set (CPPFILES
set (HEADERFILES
CodeEditor.h
+ Fl_Function_Type.h
+ Fl_Group_Type.h
+ Fl_Menu_Type.h
Fl_Type.h
Fl_Widget_Type.h
+ Fl_Window_Type.h
Fluid_Image.h
Shortcut_Button.h
StyleParse.h
about_panel.h
+ align_widget.h
alignment_panel.h
+ code.h
comments.h
+ factory.h
+ file.h
+ fluid.h
function_panel.h
print_panel.h
pixmaps.h
+ shell_command.h
template_panel.h
undo.h
+ widget_browser.h
widget_panel.h
)
diff --git a/fluid/CodeEditor.cxx b/fluid/CodeEditor.cxx
index a6bfecc48..773a19000 100644
--- a/fluid/CodeEditor.cxx
+++ b/fluid/CodeEditor.cxx
@@ -19,12 +19,26 @@
// Include necessary headers...
//
+#include "CodeEditor.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include "CodeEditor.h"
+// ---- CodeEditor implementation
+
+/** \class CodeEditor
+ A widget derived from Fl_Text_Editor that implements C++ code highlighting.
+
+ CodeEditor is used in Fluid whenever the user can edit C++ source
+ code or header text.
+ */
+
+/**
+ Lookup table for all supported styles.
+ Every table entry describes a rendering style for the corresponding text.
+ */
Fl_Text_Display::Style_Table_Entry CodeEditor::
styletable[] = { // Style table
{ FL_FOREGROUND_COLOR, FL_COURIER, 11 }, // A - Plain
@@ -37,18 +51,13 @@ Fl_Text_Display::Style_Table_Entry CodeEditor::
{ 220, /* med cyan */ FL_COURIER, 11 } // H - Single quote chars
};
-// attempt to make the fluid code editor widget honour textsize setting
-void CodeEditor::textsize(Fl_Fontsize s) {
- Fl_Text_Editor::textsize(s); // call base class method
- // now attempt to update our styletable to honour the new size...
- int entries = sizeof(styletable) / sizeof(styletable[0]);
- for(int iter = 0; iter < entries; iter++) {
- styletable[iter].size = s;
- }
-} // textsize
-
-
-// 'style_parse()' - Parse text and produce style data.
+/**
+ Parse text and produce style data.
+ \param[in] in_tbuff text buffer to parse
+ \param[inout] in_sbuf style buffer we modify
+ \param[in] in_len byte length to parse
+ \param[in] in_style starting style letter
+ */
void CodeEditor::style_parse(const char *in_tbuff, // text buffer to parse
char *in_sbuff, // style buffer we modify
int in_len, // byte length to parse
@@ -99,10 +108,19 @@ void CodeEditor::style_parse(const char *in_tbuff, // text buffer to par
}
}
-// 'style_unfinished_cb()' - Update unfinished styles.
-void CodeEditor::style_unfinished_cb(int, void*) { }
+/**
+ Update unfinished styles.
+ */
+void CodeEditor::style_unfinished_cb(int, void*) {
+}
-// 'style_update()' - Update the style buffer...
+/**
+ Update the style buffer.
+ \param[in] pos insert position in text
+ \param[in] nInserted number of bytes inserted
+ \param[in] nDeleted number of bytes deleted
+ \param[in] cbArg pointer back to the code editr
+ */
void CodeEditor::style_update(int pos, int nInserted, int nDeleted,
int /*nRestyled*/, const char * /*deletedText*/,
void *cbArg) {
@@ -150,6 +168,10 @@ void CodeEditor::style_update(int pos, int nInserted, int nDeleted,
free(style);
}
+/**
+ Find the right indentation depth after pressing the Enter key.
+ \param[in] e pointer back to the code editor
+ */
int CodeEditor::auto_indent(int, CodeEditor* e) {
if (e->buffer()->selected()) {
e->insert_position(e->buffer()->primary_selection()->start());
@@ -183,7 +205,11 @@ int CodeEditor::auto_indent(int, CodeEditor* e) {
return 1;
}
-// Create a CodeEditor widget...
+/**
+ Create a CodeEditor widget.
+ \param[in] X, Y, W, H position and size of the widget
+ \param[in] L optional label
+ */
CodeEditor::CodeEditor(int X, int Y, int W, int H, const char *L) :
Fl_Text_Editor(X, Y, W, H, L) {
buffer(new Fl_Text_Buffer);
@@ -209,7 +235,9 @@ CodeEditor::CodeEditor(int X, int Y, int W, int H, const char *L) :
(Fl_Text_Editor::Key_Func)auto_indent);
}
-// Destroy a CodeEditor widget...
+/**
+ Destroy a CodeEditor widget.
+ */
CodeEditor::~CodeEditor() {
Fl_Text_Buffer *buf = mStyleBuffer;
mStyleBuffer = 0;
@@ -220,7 +248,35 @@ CodeEditor::~CodeEditor() {
delete buf;
}
+/**
+ Attempt to make the fluid code editor widget honour textsize setting.
+ This works by updating the fontsizes in the style table.
+ \param[in] s the new general height of the text font
+ */
+void CodeEditor::textsize(Fl_Fontsize s) {
+ Fl_Text_Editor::textsize(s); // call base class method
+ // now attempt to update our styletable to honour the new size...
+ int entries = sizeof(styletable) / sizeof(styletable[0]);
+ for(int iter = 0; iter < entries; iter++) {
+ styletable[iter].size = s;
+ }
+} // textsize
+
+// ---- CodeViewer implementation
+/** \class CodeViewer
+ A widget derived from CodeEditor with highlighting for code blocks.
+
+ This widget is used by the SourceView system to show the design's
+ source an header code. The secondary highlighting show the text
+ part that corresponds to the selected widget(s).
+ */
+
+/**
+ Create a CodeViewer widget.
+ \param[in] X, Y, W, H position and size of the widget
+ \param[in] L optional label
+ */
CodeViewer::CodeViewer(int X, int Y, int W, int H, const char *L)
: CodeEditor(X, Y, W, H, L)
{
@@ -229,10 +285,11 @@ CodeViewer::CodeViewer(int X, int Y, int W, int H, const char *L)
cursor_style(CARET_CURSOR);
}
-
+/**
+ Tricking Fl_Text_Display into using bearable colors for this specific task.
+ */
void CodeViewer::draw()
{
- // Tricking Fl_Text_Display into using bearable colors for this specific task
Fl_Color c = Fl::get_color(FL_SELECTION_COLOR);
Fl::set_color(FL_SELECTION_COLOR, fl_color_average(FL_BACKGROUND_COLOR, FL_FOREGROUND_COLOR, 0.9f));
CodeEditor::draw();
diff --git a/fluid/CodeEditor.h b/fluid/CodeEditor.h
index bf4b7b499..d30f1b680 100644
--- a/fluid/CodeEditor.h
+++ b/fluid/CodeEditor.h
@@ -1,7 +1,8 @@
//
// Code editor widget for the Fast Light Tool Kit (FLTK).
+// Syntax highlighting rewritten by erco@seriss.com 09/15/20.
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2021 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
@@ -21,51 +22,44 @@
// Include necessary headers...
//
+#include "StyleParse.h"
+
+#include <FL/Fl.H>
+#include <FL/Fl_Text_Buffer.H>
+#include <FL/Fl_Text_Editor.H>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include <FL/Fl.H>
-#include <FL/Fl_Text_Buffer.H>
-#include <FL/Fl_Text_Editor.H>
-#include "StyleParse.h"
+
+// ---- CodeEditor declaration
class CodeEditor : public Fl_Text_Editor {
friend class StyleParse;
static Fl_Text_Display::Style_Table_Entry styletable[];
-
- // 'style_parse()' - Parse text and produce style data.
static void style_parse(const char *tbuff, char *sbuff, int len, char style);
-
- // 'style_unfinished_cb()' - Update unfinished styles.
static void style_unfinished_cb(int, void*);
-
- // 'style_update()' - Update the style buffer...
static void style_update(int pos, int nInserted, int nDeleted,
int /*nRestyled*/, const char * /*deletedText*/,
void *cbArg);
-
static int auto_indent(int, CodeEditor* e);
- public:
-
+public:
CodeEditor(int X, int Y, int W, int H, const char *L=0);
~CodeEditor();
int top_line() { return get_absolute_top_line_number(); }
-
- // attempt to make the fluid code editor widget honour textsize setting
void textsize(Fl_Fontsize s);
};
-class CodeViewer : public CodeEditor {
-
- public:
+// ---- CodeViewer declaration
+class CodeViewer : public CodeEditor {
+public:
CodeViewer(int X, int Y, int W, int H, const char *L=0);
- protected:
-
+protected:
int handle(int ev) { return Fl_Text_Display::handle(ev); }
void draw();
};
diff --git a/fluid/ExternalCodeEditor_UNIX.cxx b/fluid/ExternalCodeEditor_UNIX.cxx
index c0f753550..8ff27d036 100644
--- a/fluid/ExternalCodeEditor_UNIX.cxx
+++ b/fluid/ExternalCodeEditor_UNIX.cxx
@@ -3,6 +3,14 @@
//
// Note: This entire file Unix only
+#include "ExternalCodeEditor_UNIX.h"
+
+#include "fluid.h"
+
+#include <FL/Fl.H> /* Fl_Timeout_Handler.. */
+#include <FL/fl_ask.H> /* fl_alert() */
+#include <FL/fl_string.h> /* fl_strdup() */
+
#include <errno.h> /* errno */
#include <string.h> /* strerror() */
#include <sys/types.h> /* stat().. */
@@ -14,14 +22,6 @@
#include <stdlib.h> /* free().. */
#include <stdio.h> /* snprintf().. */
-#include <FL/Fl.H> /* Fl_Timeout_Handler.. */
-#include <FL/fl_ask.H> /* fl_alert() */
-#include <FL/fl_string.h> /* fl_strdup() */
-
-#include "ExternalCodeEditor_UNIX.h"
-
-extern int G_debug; // defined in fluid.cxx
-
// Static local data
static int L_editors_open = 0; // keep track of #editors open
static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer callback
@@ -40,7 +40,20 @@ static int is_dir(const char *dirname) {
return(S_ISDIR(buf.st_mode) ? 1 : 0); // a dir?
}
-// CTOR
+// ---- ExternalCodeEditor implementation
+
+/** \class ExternalCodeEditor
+ Support for an external C++ code editor for Fluid Code block.
+
+ This class can launch and quit a user defined program for editiing
+ code outside of Fluid.
+ It observes changes in the external file and updates the Fluid
+ widget to stay synchronized.
+ */
+
+/**
+ Create the manager for external code editors.
+ */
ExternalCodeEditor::ExternalCodeEditor() {
pid_ = -1;
filename_ = 0;
@@ -48,7 +61,10 @@ ExternalCodeEditor::ExternalCodeEditor() {
file_size_ = 0;
}
-// DTOR
+/**
+ Destroy the manager.
+ This also closes the external editor.
+ */
ExternalCodeEditor::~ExternalCodeEditor() {
if ( G_debug )
printf("ExternalCodeEditor() DTOR CALLED (this=%p, pid=%ld)\n",
@@ -57,20 +73,28 @@ ExternalCodeEditor::~ExternalCodeEditor() {
set_filename(0); // free()s filename
}
-// [Protected] Set the filename. Handles memory allocation/free
-// If set to NULL, frees memory.
-//
+/**
+ Set the filename for the file we wish to edit.
+ Handles memory allocation/free.
+ If set to NULL, frees memory.
+ \param[in] val new filename
+ */
void ExternalCodeEditor::set_filename(const char *val) {
if ( filename_ ) free((void*)filename_);
filename_ = val ? fl_strdup(val) : 0;
}
-// [Public] Is editor running?
+/**
+ Is editor running?
+ \return 1 if we are currently editing a file.
+ */
int ExternalCodeEditor::is_editing() {
return( (pid_ != -1) ? 1 : 0 );
}
-// [Protected] Wait for editor to close
+/**
+ Wait for editor to close
+ */
void ExternalCodeEditor::close_editor() {
if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pid_));
// Wait until editor is closed + reaped
@@ -101,10 +125,12 @@ void ExternalCodeEditor::close_editor() {
}
}
-// [Protected] Kill the running editor (if any)
-// Kills the editor, reaps the process, and removes the tmp file.
-// The dtor calls this to ensure no editors remain running when fluid exits.
-//
+/**
+ Kill the running editor (if any).
+
+ Kills the editor, reaps the process, and removes the tmp file.
+ The dtor calls this to ensure no editors remain running when fluid exits.
+ */
void ExternalCodeEditor::kill_editor() {
if ( G_debug ) printf("kill_editor() called: pid=%ld\n", (long)pid_);
if ( !is_editing() ) return; // editor not running? return..
@@ -137,15 +163,18 @@ void ExternalCodeEditor::kill_editor() {
return;
}
-// [Public] Handle if file changed since last check, and update records if so.
-// Load new data into 'code', which caller must free().
-// If 'force' set, forces reload even if file size/time didn't change.
-//
-// Returns:
-// 0 -- file unchanged or not editing
-// 1 -- file changed, internal records updated, 'code' has new content
-// -1 -- error getting file info (strerror() has reason)
-//
+/**
+ Handle if file changed since last check, and update records if so.
+
+ Load new data into 'code', which caller must free().
+ If 'force' set, forces reload even if file size/time didn't change.
+
+ \param[in] code
+ \param[in] force
+ \return 0 if file unchanged or not editing
+ \return 1 if file changed, internal records updated, 'code' has new content
+ \return -1 error getting file info (strerror() has reason)
+*/
int ExternalCodeEditor::handle_changes(const char **code, int force) {
code[0] = 0;
if ( !is_editing() ) return 0;
@@ -190,12 +219,12 @@ int ExternalCodeEditor::handle_changes(const char **code, int force) {
return ret;
}
-// [Public] Remove the tmp file (if it exists), and zero out filename/mtime/size
-// Returns:
-// -1 -- on error (dialog is posted as to why)
-// 0 -- no file to remove
-// 1 -- file was removed
-//
+/**
+ Remove the tmp file (if it exists), and zero out filename/mtime/size.
+ \return -1 on error (dialog is posted as to why)
+ \return 0 no file to remove
+ \return 1 -- file was removed
+ */
int ExternalCodeEditor::remove_tmpfile() {
const char *tmpfile = filename();
if ( !tmpfile ) return 0;
@@ -213,18 +242,20 @@ int ExternalCodeEditor::remove_tmpfile() {
return 1;
}
-// [Static/Public] Return tmpdir name for this fluid instance.
-// Returns pointer to static memory.
-//
+/**
+ Return tmpdir name for this fluid instance.
+ \return pointer to static memory.
+ */
const char* ExternalCodeEditor::tmpdir_name() {
static char dirname[100];
snprintf(dirname, sizeof(dirname), "/tmp/.fluid-%ld", (long)getpid());
return dirname;
}
-// [Static/Public] Clear the external editor's tempdir
-// Static so that the main program can call it on exit to clean up.
-//
+/**
+ Clear the external editor's tempdir.
+ Static so that the main program can call it on exit to clean up.
+ */
void ExternalCodeEditor::tmpdir_clear() {
const char *tmpdir = tmpdir_name();
if ( is_dir(tmpdir) ) {
@@ -235,9 +266,11 @@ void ExternalCodeEditor::tmpdir_clear() {
}
}
-// [Protected] Creates temp dir (if doesn't exist) and returns the dirname
-// as a static string. Returns NULL on error, dialog shows reason.
-//
+/**
+ Creates temp dir (if doesn't exist) and returns the dirname
+ as a static string.
+ \return NULL on error, dialog shows reason.
+ */
const char* ExternalCodeEditor::create_tmpdir() {
const char *dirname = tmpdir_name();
if ( ! is_dir(dirname) ) {
@@ -250,26 +283,26 @@ const char* ExternalCodeEditor::create_tmpdir() {
return dirname;
}
-// [Protected] Returns temp filename in static buffer.
-// Returns NULL if can't, posts dialog explaining why.
-//
+/**
+ Returns temp filename in static buffer.
+ \return NULL if can't, posts dialog explaining why.
+ */
const char* ExternalCodeEditor::tmp_filename() {
static char path[512];
const char *tmpdir = create_tmpdir();
if ( !tmpdir ) return 0;
- extern const char *code_file_name; // fluid's global
const char *ext = code_file_name; // e.g. ".cxx"
snprintf(path, sizeof(path), "%s/%p%s", tmpdir, (void*)this, ext);
path[sizeof(path)-1] = 0;
return path;
}
-// [Static/Local] Save string 'code' to 'filename', returning file's mtime/size
-// 'code' can be NULL -- writes an empty file if so.
-// Returns:
-// 0 on success
-// -1 on error (posts dialog with reason)
-//
+/**
+ Save string 'code' to 'filename', returning file's mtime/size.
+ 'code' can be NULL -- writes an empty file if so.
+ \return 0 on success
+ \return -1 on error (posts dialog with reason)
+ */
static int save_file(const char *filename, const char *code) {
int fd = open(filename, O_WRONLY|O_CREAT, 0666);
if ( fd == -1 ) {
@@ -291,14 +324,14 @@ static int save_file(const char *filename, const char *code) {
return(ret);
}
-// [Static/Local] Convert string 's' to array of argv[], useful for execve()
-// o 's' will be modified (words will be NULL separated)
-// o argv[] will end up pointing to the words of 's'
-// o Caller must free argv with: free(argv);
-// Returns:
-// o -1 in case of memory allocation error
-// o number of arguments in argv (same value as in argc)
-//
+/**
+ Convert string 's' to array of argv[], useful for execve().
+ - 's' will be modified (words will be NULL separated)
+ - argv[] will end up pointing to the words of 's'
+ - Caller must free argv with: free(argv);
+ \return -1 in case of memory allocation error
+ \return number of arguments in argv (same value as in argc)
+ */
static int make_args(char *s, // string containing words (gets trashed!)
int *aargc, // pointer to argc
char ***aargv) { // pointer to argv
@@ -316,11 +349,11 @@ static int make_args(char *s, // string containing words (gets trashed!)
return(t);
}
-// [Protected] Start editor in background (fork/exec)
-// Returns:
-// > 0 on success, leaves editor child process running as 'pid_'
-// > -1 on error, posts dialog with reason (child exits)
-//
+/**
+ Start editor in background (fork/exec)
+ \return 0 on success, leaves editor child process running as 'pid_'
+ \return -1 on error, posts dialog with reason (child exits)
+ */
int ExternalCodeEditor::start_editor(const char *editor_cmd,
const char *filename) {
if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n",
@@ -354,17 +387,18 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd,
return 0;
}
-// [Public] Try to reap external editor process
-// If 'pid_reaped' not NULL, returns PID of reaped editor.
-// Returns:
-// -2 -- editor not open
-// -1 -- waitpid() failed (errno has reason)
-// 0 -- process still running
-// 1 -- process finished + reaped ('pid_reaped' has pid), pid_ set to -1.
-// Handles removing tmpfile/zeroing file_mtime/file_size/filename
-//
-// If return value <=0, 'pid_reaped' is set to zero.
-//
+/**
+ Try to reap external editor process.
+
+ If 'pid_reaped' not NULL, returns PID of reaped editor.
+
+ \return -2: editor not open
+ \return -1: waitpid() failed (errno has reason)
+ \return 0: process still running
+ \return 1: process finished + reaped ('pid_reaped' has pid), pid_ set to -1.
+ Handles removing tmpfile/zeroing file_mtime/file_size/filename
+ \return If return value <=0, 'pid_reaped' is set to zero.
+ */
int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) {
if ( pid_reaped ) *pid_reaped = 0;
if ( !is_editing() ) return -2;
@@ -388,14 +422,15 @@ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) {
return 1;
}
-// [Public] Open external editor using 'editor_cmd' to edit 'code'
-// 'code' contains multiline code to be edited as a temp file.
-//
-// Returns:
-// 0 if succeeds
-// -1 if can't open editor (already open, etc),
-// errors were shown to user in a dialog
-//
+/**
+ Open external editor using 'editor_cmd' to edit 'code'.
+
+ 'code' contains multiline code to be edited as a temp file.
+
+ \return 0 if succeeds
+ \return -1 if can't open editor (already open, etc),
+ errors were shown to user in a dialog
+ */
int ExternalCodeEditor::open_editor(const char *editor_cmd,
const char *code) {
// Make sure a temp filename exists
@@ -446,31 +481,38 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
return 0;
}
-// [Public/Static] Start update timer
+/**
+ Start update timer.
+ */
void ExternalCodeEditor::start_update_timer() {
if ( !L_update_timer_cb ) return;
if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n");
Fl::add_timeout(2.0, L_update_timer_cb);
}
-// [Public/Static] Stop update timer
+/**
+ Stop update timer.
+ */
void ExternalCodeEditor::stop_update_timer() {
if ( !L_update_timer_cb ) return;
if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n");
Fl::remove_timeout(L_update_timer_cb);
}
-// [Public/Static] Set app's external editor update timer callback
-// This is the app's callback callback we start while editors are open,
-// and stop when all editors are closed.
-//
+/**
+ Set app's external editor update timer callback.
+
+ This is the app's callback callback we start while editors are open,
+ and stop when all editors are closed.
+ */
void ExternalCodeEditor::set_update_timer_callback(Fl_Timeout_Handler cb) {
L_update_timer_cb = cb;
}
-// [Static/Public] See if any external editors are open.
-// App's timer cb can see if any editors need checking..
-//
+/**
+ See if any external editors are open.
+ App's timer cb can see if any editors need checking..
+ */
int ExternalCodeEditor::editors_open() {
return L_editors_open;
}
diff --git a/fluid/ExternalCodeEditor_UNIX.h b/fluid/ExternalCodeEditor_UNIX.h
index d366a95c1..186a5b5ec 100644
--- a/fluid/ExternalCodeEditor_UNIX.h
+++ b/fluid/ExternalCodeEditor_UNIX.h
@@ -7,24 +7,29 @@
#ifndef _EXTCODEEDITOR_H
#define _EXTCODEEDITOR_H
+#include <FL/Fl.H>
+
#include <errno.h> /* errno */
#include <string.h> /* strerror() */
-
#include <sys/types.h> /* stat().. */
#include <sys/stat.h>
#include <unistd.h>
+// ---- ExternalCodeEditor declaration
+
class ExternalCodeEditor {
int pid_;
time_t file_mtime_; // last modify time of the file (used to determine if file changed)
size_t file_size_; // last file size (used to determine if changed)
const char *filename_;
+
protected:
void kill_editor();
const char *create_tmpdir();
const char *tmp_filename();
int start_editor(const char *cmd, const char *filename);
void set_filename(const char *val);
+
public:
ExternalCodeEditor();
~ExternalCodeEditor();
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;
diff --git a/fluid/Fl_Function_Type.h b/fluid/Fl_Function_Type.h
new file mode 100644
index 000000000..d5b0087c0
--- /dev/null
+++ b/fluid/Fl_Function_Type.h
@@ -0,0 +1,230 @@
+//
+// C function type header file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_FL_FUNCTION_TYPE_H
+#define _FLUID_FL_FUNCTION_TYPE_H
+
+#include "Fl_Type.h"
+
+#include "Fluid_Image.h"
+#ifdef _WIN32
+#include "ExternalCodeEditor_WIN32.h"
+#else
+#include "ExternalCodeEditor_UNIX.h"
+#endif
+
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Menu.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_attr.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+extern Fl_Class_Type *current_class;
+
+int has_toplevel_function(const char *rtype, const char *sig);
+
+const char *c_check(const char *c, int type = 0);
+
+// ---- Fl_Function_Type declaration
+
+class Fl_Function_Type : public Fl_Type {
+ const char* return_type;
+ char public_, cdecl_, constructor, havewidgets;
+
+public:
+ Fl_Function_Type();
+ ~Fl_Function_Type();
+ Fl_Type *make();
+ void write_code1();
+ void write_code2();
+ void open();
+ int ismain() {return name_ == 0;}
+ virtual const char *type_name() {return "Function";}
+ virtual const char *title() {
+ return name() ? name() : "main()";
+ }
+ int is_parent() const {return 1;}
+ int is_code_block() const {return 1;}
+ virtual int is_public() const;
+ int pixmapID() { return 7; }
+ void write_properties();
+ void read_property(const char *);
+ int has_signature(const char *, const char*) const;
+};
+
+// ---- Fl_Code_Type declaration
+
+class Fl_Code_Type : public Fl_Type {
+ ExternalCodeEditor editor_;
+ int cursor_position_;
+
+public:
+ Fl_Code_Type();
+ Fl_Type *make();
+ void write();
+ void write_code1();
+ void write_code2() { }
+ void open();
+ virtual const char *type_name() {return "code";}
+ int is_code_block() const {return 0;}
+ int is_code() const {return 1;}
+ int pixmapID() { return 8; }
+ virtual int is_public() const { return -1; }
+ int is_editing();
+ int reap_editor();
+ int handle_editor_changes();
+};
+
+// ---- Fl_CodeBlock_Type declaration
+
+class Fl_CodeBlock_Type : public Fl_Type {
+ const char* after;
+
+public:
+ Fl_CodeBlock_Type();
+ ~Fl_CodeBlock_Type();
+ Fl_Type *make();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "codeblock";}
+ int is_code_block() const {return 1;}
+ int is_parent() const {return 1;}
+ virtual int is_public() const { return -1; }
+ int pixmapID() { return 9; }
+ void write_properties();
+ void read_property(const char *);
+};
+
+// ---- Fl_Decl_Type declaration
+
+class Fl_Decl_Type : public Fl_Type {
+
+protected:
+ char public_;
+ char static_;
+
+public:
+ Fl_Decl_Type();
+ Fl_Type *make();
+ void write_code1();
+ void write_code2() { }
+ void open();
+ virtual const char *type_name() {return "decl";}
+ void write_properties();
+ void read_property(const char *);
+ virtual int is_public() const;
+ int pixmapID() { return 10; }
+};
+
+// ---- Fl_Data_Type declaration
+
+class Fl_Data_Type : public Fl_Decl_Type {
+ const char *filename_;
+ int text_mode_;
+
+public:
+ Fl_Data_Type();
+ ~Fl_Data_Type();
+ Fl_Type *make();
+ void write_code1();
+ void write_code2() {}
+ void open();
+ virtual const char *type_name() {return "data";}
+ void write_properties();
+ void read_property(const char *);
+ int pixmapID() { return 49; }
+};
+
+// ---- Fl_DeclBlock_Type declaration
+
+class Fl_DeclBlock_Type : public Fl_Type {
+ const char* after;
+ char public_;
+
+public:
+ Fl_DeclBlock_Type();
+ ~Fl_DeclBlock_Type();
+ Fl_Type *make();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "declblock";}
+ void write_properties();
+ void read_property(const char *);
+ int is_parent() const {return 1;}
+ int is_decl_block() const {return 1;}
+ virtual int is_public() const;
+ int pixmapID() { return 11; }
+};
+
+// ---- Fl_Comment_Type declaration
+
+class Fl_Comment_Type : public Fl_Type {
+ char in_c_, in_h_, style_;
+ char title_buf[64];
+
+public:
+ Fl_Comment_Type();
+ Fl_Type *make();
+ void write_code1();
+ void write_code2() { }
+ void open();
+ virtual const char *type_name() {return "comment";}
+ virtual const char *title(); // string for browser
+ void write_properties();
+ void read_property(const char *);
+ virtual int is_public() const { return 1; }
+ virtual int is_comment() const { return 1; }
+ int pixmapID() { return 46; }
+};
+
+// ---- Fl_Class_Type declaration
+
+class Fl_Class_Type : public Fl_Type {
+ const char* subclass_of;
+ char public_;
+ const char* class_prefix;
+
+public:
+ Fl_Class_Type();
+ ~Fl_Class_Type();
+ // state variables for output:
+ char write_public_state; // true when public: has been printed
+ Fl_Class_Type* parent_class; // save class if nested
+//
+ Fl_Type *make();
+ void write_code1();
+ void write_code2();
+ void open();
+ virtual const char *type_name() {return "class";}
+ int is_parent() const {return 1;}
+ int is_decl_block() const {return 1;}
+ int is_class() const {return 1;}
+ virtual int is_public() const;
+ int pixmapID() { return 12; }
+ void write_properties();
+ void read_property(const char *);
+
+ // class prefix attribute access
+ void prefix(const char* p);
+ const char* prefix() const {return class_prefix;}
+ int has_function(const char*, const char*) const;
+};
+
+#endif // _FLUID_FL_FUNCTION_TYPE_H
diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx
index cc6fb59a6..a2a45a541 100644
--- a/fluid/Fl_Group_Type.cxx
+++ b/fluid/Fl_Group_Type.cxx
@@ -18,13 +18,22 @@
// https://www.fltk.org/bugs.php
//
+#include "Fl_Group_Type.h"
+
+#include "fluid.h"
+#include "file.h"
+#include "code.h"
+
#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Table.H>
+#include <FL/Fl_Menu_Item.H>
#include <FL/fl_message.H>
-#include "Fl_Widget_Type.h"
+#include <FL/Fl_Scroll.H>
#include "../src/flstring.h"
+#include <stdio.h>
+
// Override group's resize behavior to do nothing to children:
void igroup::resize(int X, int Y, int W, int H) {
Fl_Widget::resize(X,Y,W,H);
@@ -55,8 +64,6 @@ void fix_group_size(Fl_Type *tt) {
t->o->resize(X,Y,R-X,B-Y);
}
-extern int force_parent;
-
void group_cb(Fl_Widget *, void *) {
// Find the current widget:
Fl_Type *qq = Fl_Type::current;
@@ -106,8 +113,6 @@ void ungroup_cb(Fl_Widget *, void *) {
////////////////////////////////////////////////////////////////
-#include <stdio.h>
-
void Fl_Group_Type::write_code1() {
Fl_Widget_Type::write_code1();
}
@@ -380,8 +385,6 @@ void Fl_Group_Type::copy_properties() {
////////////////////////////////////////////////////////////////
// some other group subclasses that fluid does not treat specially:
-#include <FL/Fl_Scroll.H>
-
const char scroll_type_name[] = "Fl_Scroll";
Fl_Widget *Fl_Scroll_Type::enter_live_mode(int) {
diff --git a/fluid/Fl_Group_Type.h b/fluid/Fl_Group_Type.h
new file mode 100644
index 000000000..a55e0dfd2
--- /dev/null
+++ b/fluid/Fl_Group_Type.h
@@ -0,0 +1,158 @@
+//
+// Widget type header file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_FL_GROUP_TYPE_H
+#define _FLUID_FL_GROUP_TYPE_H
+
+#include "Fl_Widget_Type.h"
+
+#include <FL/Fl_Tabs.H>
+#include <FL/Fl_Pack.H>
+#include <FL/Fl_Wizard.H>
+
+void group_cb(Fl_Widget *, void *);
+void ungroup_cb(Fl_Widget *, void *);
+
+class igroup : public Fl_Group {
+public:
+ void resize(int,int,int,int);
+ void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); }
+ igroup(int X,int Y,int W,int H) : Fl_Group(X,Y,W,H) {Fl_Group::current(0);}
+};
+
+class itabs : public Fl_Tabs {
+public:
+ void resize(int,int,int,int);
+ void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); }
+ itabs(int X,int Y,int W,int H) : Fl_Tabs(X,Y,W,H) {}
+};
+
+class iwizard : public Fl_Wizard {
+public:
+ void resize(int,int,int,int);
+ void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); }
+ iwizard(int X,int Y,int W,int H) : Fl_Wizard(X,Y,W,H) {}
+};
+
+class Fl_Group_Type : public Fl_Widget_Type {
+public:
+ virtual const char *type_name() {return "Fl_Group";}
+ virtual const char *alt_type_name() {return "fltk::Group";}
+ Fl_Widget *widget(int X,int Y,int W,int H) {
+ igroup *g = new igroup(X,Y,W,H); Fl_Group::current(0); return g;}
+ Fl_Widget_Type *_make() {return new Fl_Group_Type();}
+ Fl_Type *make();
+ void write_code1();
+ void write_code2();
+ void add_child(Fl_Type*, Fl_Type*);
+ void move_child(Fl_Type*, Fl_Type*);
+ void remove_child(Fl_Type*);
+ int is_parent() const {return 1;}
+ int is_group() const {return 1;}
+ int pixmapID() { return 6; }
+
+ virtual Fl_Widget *enter_live_mode(int top=0);
+ virtual void leave_live_mode();
+ virtual void copy_properties();
+};
+
+extern const char pack_type_name[];
+extern Fl_Menu_Item pack_type_menu[];
+
+class Fl_Pack_Type : public Fl_Group_Type {
+ Fl_Menu_Item *subtypes() {return pack_type_menu;}
+public:
+ virtual const char *type_name() {return pack_type_name;}
+ virtual const char *alt_type_name() {return "fltk::PackedGroup";}
+ Fl_Widget_Type *_make() {return new Fl_Pack_Type();}
+ int pixmapID() { return 22; }
+ void copy_properties();
+};
+
+extern const char table_type_name[];
+
+class Fl_Table_Type : public Fl_Group_Type {
+public:
+ virtual const char *type_name() {return table_type_name;}
+ virtual const char *alt_type_name() {return "fltk::TableGroup";}
+ Fl_Widget_Type *_make() {return new Fl_Table_Type();}
+ Fl_Widget *widget(int X,int Y,int W,int H);
+ int pixmapID() { return 51; }
+ virtual Fl_Widget *enter_live_mode(int top=0);
+ void add_child(Fl_Type*, Fl_Type*);
+ void move_child(Fl_Type*, Fl_Type*);
+ void remove_child(Fl_Type*);
+};
+
+extern const char tabs_type_name[];
+
+class Fl_Tabs_Type : public Fl_Group_Type {
+public:
+ virtual void ideal_spacing(int &x, int &y) {
+ x = 10;
+ fl_font(o->labelfont(), o->labelsize());
+ y = fl_height() + o->labelsize() - 6;
+ }
+ virtual const char *type_name() {return tabs_type_name;}
+ virtual const char *alt_type_name() {return "fltk::TabGroup";}
+ Fl_Widget *widget(int X,int Y,int W,int H) {
+ itabs *g = new itabs(X,Y,W,H); Fl_Group::current(0); return g;}
+ Fl_Widget_Type *_make() {return new Fl_Tabs_Type();}
+ Fl_Type* click_test(int,int);
+ void add_child(Fl_Type*, Fl_Type*);
+ void remove_child(Fl_Type*);
+ int pixmapID() { return 13; }
+ Fl_Widget *enter_live_mode(int top=0);
+};
+
+extern const char scroll_type_name[];
+extern Fl_Menu_Item scroll_type_menu[];
+
+class Fl_Scroll_Type : public Fl_Group_Type {
+ Fl_Menu_Item *subtypes() {return scroll_type_menu;}
+public:
+ virtual const char *type_name() {return scroll_type_name;}
+ virtual const char *alt_type_name() {return "fltk::ScrollGroup";}
+ Fl_Widget_Type *_make() {return new Fl_Scroll_Type();}
+ int pixmapID() { return 19; }
+ Fl_Widget *enter_live_mode(int top=0);
+ void copy_properties();
+};
+
+extern const char tile_type_name[];
+
+class Fl_Tile_Type : public Fl_Group_Type {
+public:
+ virtual const char *type_name() {return tile_type_name;}
+ virtual const char *alt_type_name() {return "fltk::TileGroup";}
+ Fl_Widget_Type *_make() {return new Fl_Tile_Type();}
+ int pixmapID() { return 20; }
+ void copy_properties();
+};
+
+extern const char wizard_type_name[];
+
+class Fl_Wizard_Type : public Fl_Group_Type {
+public:
+ virtual const char *type_name() {return wizard_type_name;}
+ virtual const char *alt_type_name() {return "fltk::WizardGroup";}
+ Fl_Widget *widget(int X,int Y,int W,int H) {
+ iwizard *g = new iwizard(X,Y,W,H); Fl_Group::current(0); return g;}
+ Fl_Widget_Type *_make() {return new Fl_Wizard_Type();}
+ int pixmapID() { return 21; }
+};
+
+#endif // _FLUID_FL_GROUP_TYPE_H
diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx
index 5c1a56f30..a93538de6 100644
--- a/fluid/Fl_Menu_Type.cxx
+++ b/fluid/Fl_Menu_Type.cxx
@@ -20,15 +20,27 @@
// https://www.fltk.org/bugs.php
//
-#include <FL/Fl.H>
-#include "Fl_Widget_Type.h"
+#include "Fl_Menu_Type.h"
+
+#include "fluid.h"
+#include "Fl_Window_Type.h"
#include "alignment_panel.h"
+#include "file.h"
+#include "code.h"
+#include "Fluid_Image.h"
+#include "Shortcut_Button.h"
+
+#include <FL/Fl.H>
#include <FL/fl_message.H>
#include <FL/Fl_Menu_.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Input.H>
#include <FL/Fl_Text_Display.H>
+#include <FL/Fl_Menu_Button.H>
+#include <FL/Fl_Output.H>
+#include <FL/fl_draw.H>
#include "../src/flstring.h"
+
#include <stdio.h>
#include <stdlib.h>
@@ -38,14 +50,6 @@ Fl_Menu_Item menu_item_type_menu[] = {
{"Radio",0,0,(void*)FL_MENU_RADIO},
{0}};
-extern int reading_file;
-extern int force_parent;
-extern int i18n_type;
-extern const char* i18n_include;
-extern const char* i18n_function;
-extern const char* i18n_file;
-extern const char* i18n_set;
-
static char submenuflag;
static uchar menuitemtype = 0;
@@ -174,8 +178,6 @@ const char* Fl_Menu_Item_Type::menu_name(int& i) {
return unique_id(t, "menu", t->name(), t->label());
}
-#include "Fluid_Image.h"
-
void Fl_Menu_Item_Type::write_static() {
if (callback() && is_name(callback()) && !user_defined(callback()))
write_declare("extern void %s(Fl_Menu_*, %s);", callback(),
@@ -525,7 +527,6 @@ void Fl_Menu_Type::copy_properties() {
////////////////////////////////////////////////////////////////
-#include <FL/Fl_Menu_Button.H>
Fl_Menu_Item button_type_menu[] = {
{"normal",0,0,(void*)0},
{"popup1",0,0,(void*)Fl_Menu_Button::POPUP1},
@@ -582,10 +583,6 @@ Fl_Menu_Bar_Type Fl_Menu_Bar_type;
////////////////////////////////////////////////////////////////
// Shortcut entry item in panel:
-#include <FL/Fl_Output.H>
-#include "Shortcut_Button.h"
-#include <FL/fl_draw.H>
-
void Shortcut_Button::draw() {
if (value()) draw_box(FL_DOWN_BOX, (Fl_Color)9);
else draw_box(FL_UP_BOX, FL_WHITE);
diff --git a/fluid/Fl_Menu_Type.h b/fluid/Fl_Menu_Type.h
new file mode 100644
index 000000000..b42798d61
--- /dev/null
+++ b/fluid/Fl_Menu_Type.h
@@ -0,0 +1,212 @@
+//
+// Widget type header file for the Fast Light Tool Kit (FLTK).
+//
+// Type for creating all subclasses of Fl_Widget
+// This should have the widget pointer in it, but it is still in the
+// Fl_Type base class.
+//
+// Copyright 1998-2010 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_FL_MENU_TYPE_H
+#define _FLUID_FL_MENU_TYPE_H
+
+#include "Fl_Widget_Type.h"
+
+#include <FL/Fl_Menu_.H>
+#include <FL/Fl_Menu_Button.H>
+#include <FL/Fl_Input_Choice.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Menu_Bar.H>
+
+extern Fl_Menu_Item menu_item_type_menu[];
+
+class Fl_Menu_Item_Type : public Fl_Widget_Type {
+public:
+ Fl_Menu_Item* subtypes() {return menu_item_type_menu;}
+ const char* type_name() {return "MenuItem";}
+ const char* alt_type_name() {return "fltk::Item";}
+ Fl_Type* make();
+ int is_menu_item() const {return 1;}
+ int is_button() const {return 1;} // this gets shortcut to work
+ Fl_Widget* widget(int,int,int,int) {return 0;}
+ Fl_Widget_Type* _make() {return 0;}
+ const char* menu_name(int& i);
+ int flags();
+ void write_static();
+ void write_item();
+ void write_code1();
+ void write_code2();
+ int pixmapID() { return 16; }
+};
+
+class Fl_Radio_Menu_Item_Type : public Fl_Menu_Item_Type {
+public:
+ const char* type_name() {return "RadioMenuItem";}
+ Fl_Type* make();
+ int pixmapID() { return 55; }
+};
+
+class Fl_Checkbox_Menu_Item_Type : public Fl_Menu_Item_Type {
+public:
+ const char* type_name() {return "CheckMenuItem";}
+ Fl_Type* make();
+ int pixmapID() { return 54; }
+};
+
+class Fl_Submenu_Type : public Fl_Menu_Item_Type {
+public:
+ Fl_Menu_Item* subtypes() {return 0;}
+ const char* type_name() {return "Submenu";}
+ const char* alt_type_name() {return "fltk::ItemGroup";}
+ int is_parent() const {return 1;}
+ int is_button() const {return 0;} // disable shortcut
+ Fl_Type* make();
+ // changes to submenu must propagate up so build_menu is called
+ // on the parent Fl_Menu_Type:
+ void add_child(Fl_Type*a, Fl_Type*b) {parent->add_child(a,b);}
+ void move_child(Fl_Type*a, Fl_Type*b) {parent->move_child(a,b);}
+ void remove_child(Fl_Type*a) {parent->remove_child(a);}
+ int pixmapID() { return 18; }
+};
+
+class Fl_Menu_Type : public Fl_Widget_Type {
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break;
+ case 1: myo->textfont(f); break;
+ case 2: myo->textsize(s); break;
+ case 3: myo->textcolor(c); break;
+ }
+ return 1;
+ }
+public:
+ int is_menu_button() const {return 1;}
+ int is_parent() const {return 1;}
+ int menusize;
+ virtual void build_menu();
+ Fl_Menu_Type() : Fl_Widget_Type() {menusize = 0;}
+ ~Fl_Menu_Type() {
+ if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu());
+ }
+ void add_child(Fl_Type*, Fl_Type*) {build_menu();}
+ void move_child(Fl_Type*, Fl_Type*) {build_menu();}
+ void remove_child(Fl_Type*) {build_menu();}
+ Fl_Type* click_test(int x, int y);
+ void write_code2();
+ void copy_properties();
+};
+
+extern Fl_Menu_Item button_type_menu[];
+
+class Fl_Menu_Button_Type : public Fl_Menu_Type {
+ Fl_Menu_Item *subtypes() {return button_type_menu;}
+public:
+ virtual void ideal_size(int &w, int &h) {
+ Fl_Widget_Type::ideal_size(w, h);
+ w += 2 * ((o->labelsize() - 3) & ~1) + o->labelsize() - 4;
+ h = (h / 5) * 5;
+ if (h < 15) h = 15;
+ if (w < (15 + h)) w = 15 + h;
+ }
+ virtual const char *type_name() {return "Fl_Menu_Button";}
+ virtual const char *alt_type_name() {return "fltk::MenuButton";}
+ Fl_Widget *widget(int X,int Y,int W,int H) {
+ return new Fl_Menu_Button(X,Y,W,H,"menu");}
+ Fl_Widget_Type *_make() {return new Fl_Menu_Button_Type();}
+ int pixmapID() { return 26; }
+};
+
+extern Fl_Menu_Item dummymenu[];
+
+#include <FL/Fl_Choice.H>
+class Fl_Choice_Type : public Fl_Menu_Type {
+public:
+ virtual void ideal_size(int &w, int &h) {
+ Fl_Widget_Type::ideal_size(w, h);
+ int w1 = o->h() - Fl::box_dh(o->box());
+ if (w1 > 20) w1 = 20;
+ w1 = (w1 - 4) / 3;
+ if (w1 < 1) w1 = 1;
+ w += 2 * w1 + o->labelsize() - 4;
+ h = (h / 5) * 5;
+ if (h < 15) h = 15;
+ if (w < (15 + h)) w = 15 + h;
+ }
+ virtual const char *type_name() {return "Fl_Choice";}
+ virtual const char *alt_type_name() {return "fltk::Choice";}
+ Fl_Widget *widget(int X,int Y,int W,int H) {
+ Fl_Choice *myo = new Fl_Choice(X,Y,W,H,"choice:");
+ myo->menu(dummymenu);
+ return myo;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Choice_Type();}
+ int pixmapID() { return 15; }
+};
+
+class Fl_Input_Choice_Type : public Fl_Menu_Type {
+ int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+ Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+ switch (w) {
+ case 4:
+ case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break;
+ case 1: myo->textfont(f); break;
+ case 2: myo->textsize(s); break;
+ case 3: myo->textcolor(c); break;
+ }
+ return 1;
+ }
+public:
+ virtual void ideal_size(int &w, int &h) {
+ Fl_Input_Choice *myo = (Fl_Input_Choice *)o;
+ fl_font(myo->textfont(), myo->textsize());
+ h = fl_height() + myo->textsize() - 6;
+ w = o->w() - 20 - Fl::box_dw(o->box());
+ int ww = (int)fl_width('m');
+ w = ((w + ww - 1) / ww) * ww + 20 + Fl::box_dw(o->box());
+ if (h < 15) h = 15;
+ if (w < (15 + h)) w = 15 + h;
+ }
+ virtual const char *type_name() {return "Fl_Input_Choice";}
+ virtual const char *alt_type_name() {return "fltk::ComboBox";}
+ virtual Fl_Type* click_test(int,int);
+ Fl_Widget *widget(int X,int Y,int W,int H) {
+ Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:");
+ myo->menu(dummymenu);
+ myo->value("input");
+ return myo;
+ }
+ Fl_Widget_Type *_make() {return new Fl_Input_Choice_Type();}
+ virtual void build_menu();
+ int pixmapID() { return 53; }
+ void copy_properties();
+};
+
+class Fl_Menu_Bar_Type : public Fl_Menu_Type {
+public:
+ virtual void ideal_size(int &w, int &h) {
+ w = o->window()->w();
+ h = ((o->labelsize() + Fl::box_dh(o->box()) + 4) / 5) * 5;
+ if (h < 15) h = 15;
+ }
+ virtual const char *type_name() {return "Fl_Menu_Bar";}
+ virtual const char *alt_type_name() {return "fltk::MenuBar";}
+ Fl_Widget *widget(int X,int Y,int W,int H) {return new Fl_Menu_Bar(X,Y,W,H);}
+ Fl_Widget_Type *_make() {return new Fl_Menu_Bar_Type();}
+ int pixmapID() { return 17; }
+};
+
+
+#endif // _FLUID_FL_MENU_TYPE_H
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
index 04b469b8d..68094850f 100644
--- a/fluid/Fl_Type.cxx
+++ b/fluid/Fl_Type.cxx
@@ -14,415 +14,201 @@
// https://www.fltk.org/bugs.php
//
-// Each object described by Fluid is one of these objects. They
-// are all stored in a double-linked list.
-//
-// The "type" of the object is covered by the virtual functions.
-// There will probably be a lot of these virtual functions.
-//
-// The type browser is also a list of these objects, but they
-// are "factory" instances, not "real" ones. These objects exist
-// only so the "make" method can be called on them. They are
-// not in the linked list and are not written to files or
-// copied or otherwise examined.
-
-#include <FL/Fl.H>
-#include <FL/Fl_Browser_.H>
-#include <FL/fl_draw.H>
-#include <stdlib.h>
-#include "../src/flstring.h"
-#include <stdio.h>
+/** \class Fl_Type
+Each object described by Fluid is one of these objects. They
+are all stored in a double-linked list.
+
+The "type" of the object is covered by the virtual functions.
+There will probably be a lot of these virtual functions.
+
+The type browser is also a list of these objects, but they
+are "factory" instances, not "real" ones. These objects exist
+only so the "make" method can be called on them. They are
+not in the linked list and are not written to files or
+copied or otherwise examined.
+*/
#include "Fl_Type.h"
-#include "undo.h"
+#include "fluid.h"
+#include "Fl_Function_Type.h"
+#include "Fl_Widget_Type.h"
+#include "Fl_Window_Type.h"
+#include "widget_browser.h"
+#include "file.h"
+#include "code.h"
+#include "undo.h"
#include "pixmaps.h"
-extern int show_comments;
-
-////////////////////////////////////////////////////////////////
-
-// Copy the given string str to buffer p with no more than maxl characters.
-// Add "..." if string was truncated.
-// If parameter quote is true (not 0) the string is quoted with "".
-// Quote characters are NOT counted.
-// The returned buffer (string) is terminated with a null byte.
-// Returns pointer to end of string (before terminating null byte).
-// Note: the buffer p must be large enough to hold (4 * (maxl+1) + 1) bytes
-// or (4 * (maxl+1) + 3) bytes if quoted, e.g. "123..." because each UTF-8
-// character can consist of 4 bytes, "..." adds 3 bytes, quotes '""' add two
-// bytes, and the terminating null byte adds another byte.
-// This supports Unicode code points up to U+10FFFF (standard as of 10/2016).
-// Sanity checks for illegal UTF-8 sequences are included.
-
-static char *copy_trunc(char *p, const char *str, int maxl, int quote) {
-
- int size = 0; // truncated string size in characters
- int bs; // size of UTF-8 character in bytes
- const char *end = str + strlen(str); // end of input string
- if (quote) *p++ = '"'; // opening quote
- while (size < maxl) { // maximum <maxl> characters
- if (!(*str & (-32))) break; // end of string (0 or control char)
- bs = fl_utf8len(*str); // size of next character
- if (bs <= 0) break; // some error - leave
- if (str + bs > end) break; // UTF-8 sequence beyond end of string
- while (bs--) *p++ = *str++; // copy that character into the buffer
- size++; // count copied characters
- }
- if (*str) { // string was truncated
- strcpy(p,"..."); p += 3;
- }
- if (quote) *p++ = '"'; // closing quote
- *p = 0; // terminating null byte
- return p;
-}
-
-////////////////////////////////////////////////////////////////
+#include <FL/Fl.H>
+#include <FL/Fl_Browser_.H>
+#include <FL/fl_draw.H>
+#include "../src/flstring.h"
-class Widget_Browser : public Fl_Browser_ {
- friend class Fl_Type;
+#include <stdlib.h>
+#include <stdio.h>
- // required routines for Fl_Browser_ subclass:
- void *item_first() const ;
- void *item_next(void *) const ;
- void *item_prev(void *) const ;
- int item_selected(void *) const ;
- void item_select(void *,int);
- int item_width(void *) const ;
- int item_height(void *) const ;
- void item_draw(void *,int,int,int,int) const ;
- int incr_height() const ;
+// ---- global variables
-public:
+Fl_Type *Fl_Type::first = NULL;
+Fl_Type *Fl_Type::last = NULL;
- int handle(int);
- void callback();
- Widget_Browser(int,int,int,int,const char * =0);
-};
+Fl_Type *in_this_only; // set if menu popped-up in window
-static Widget_Browser *widget_browser;
-Fl_Widget *make_widget_browser(int x,int y,int w,int h) {
- return (widget_browser = new Widget_Browser(x,y,w,h));
-}
+// ---- various functions
-void redraw_widget_browser(Fl_Type *caller)
-{
- if (caller) {
- widget_browser->display(caller);
+void select_all_cb(Fl_Widget *,void *) {
+ Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
+ if (in_this_only) {
+ Fl_Type *t = p;
+ for (; t && t != in_this_only; t = t->parent) {/*empty*/}
+ if (t != in_this_only) p = in_this_only;
}
- widget_browser->redraw();
-}
-
-void select(Fl_Type *o, int v) {
- widget_browser->select(o,v,1);
- // Fl_Type::current = o;
-}
-
-void select_only(Fl_Type *o) {
- widget_browser->select_only(o,1);
-}
-
-void deselect() {
- widget_browser->deselect();
- //Fl_Type::current = 0; // this breaks the paste & merge functions
-}
-
-Fl_Type *Fl_Type::first;
-Fl_Type *Fl_Type::last;
-
-static void Widget_Browser_callback(Fl_Widget *o,void *) {
- ((Widget_Browser *)o)->callback();
-}
-
-Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l)
-: Fl_Browser_(X,Y,W,H,l) {
- type(FL_MULTI_BROWSER);
- Fl_Widget::callback(Widget_Browser_callback);
- when(FL_WHEN_RELEASE);
-}
-
-void *Widget_Browser::item_first() const {return Fl_Type::first;}
-
-void *Widget_Browser::item_next(void *l) const {return ((Fl_Type*)l)->next;}
-
-void *Widget_Browser::item_prev(void *l) const {return ((Fl_Type*)l)->prev;}
-
-int Widget_Browser::item_selected(void *l) const {return ((Fl_Type*)l)->new_selected;}
-
-void Widget_Browser::item_select(void *l,int v) {((Fl_Type*)l)->new_selected = v;}
-
-int Widget_Browser::item_height(void *l) const {
- Fl_Type *t = (Fl_Type*)l;
- if (t->visible) {
- if (show_comments && t->comment())
- return textsize()*2+4;
- else
- return textsize()+5;
+ for (;;) {
+ if (p) {
+ int foundany = 0;
+ for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
+ if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;}
+ }
+ if (foundany) break;
+ p = p->parent;
+ } else {
+ for (Fl_Type *t = Fl_Type::first; t; t = t->next)
+ widget_browser->select(t,1,0);
+ break;
+ }
}
- return 0;
-}
-
-int Widget_Browser::incr_height() const {return textsize()+2;}
-
-static Fl_Type* pushedtitle;
-
-// Generate a descriptive text for this item, to put in browser & window titles
-const char* Fl_Type::title() {
- const char* c = name(); if (c) return c;
- return type_name();
+ selection_changed(p);
}
-extern const char* subclassname(Fl_Type*);
-
-
-/**
- Draw an item in the widget browser.
-
- A browser line starts with a variable size space. This space directly
- relates to the level of the type entry.
-
- If this type has the ability to store children, a triangle follows,
- pointing right (closed) or pointing down (open, children shown).
-
- Next follows an icon that is specific to the type. This makes it easy to
- spot certain types.
-
- Now follows some text. For classes and widgets, this is the type itself,
- followed by the name of the object. Other objects show their content as
- text, possibly abbreviated with an ellipsis.
-
- \param v v is a pointer to the actual widget type and can be cast safely
- to Fl_Type
- \param X,Y these give the position in window coordinates of the top left
- corner of this line
-*/
-void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
- // cast to a more general type
- Fl_Type *l = (Fl_Type *)v;
-
- char buf[340]; // edit buffer: large enough to hold 80 UTF-8 chars + nul
-
- // calculate the horizontal start position of this item
- // 3 is the edge of the browser
- // 13 is the width of the arrow that indicates children for the item
- // 18 is the width of the icon
- // 12 is the indent per level
- X += 3 + 13 + 18 + l->level * 12;
-
- // calculate the horizontal start position and width of the separator line
- int x1 = X;
- int w1 = w() - x1;
-
- // items can contain a comment. If they do, the comment gets a second text
- // line inside this browser line
- int comment_incr = 0;
- if (show_comments && l->comment()) {
- copy_trunc(buf, l->comment(), 80, 0);
- comment_incr = textsize()-1;
- if (l->new_selected) fl_color(fl_contrast(FL_DARK_GREEN,FL_SELECTION_COLOR));
- else fl_color(fl_contrast(FL_DARK_GREEN,color()));
- fl_font(textfont()+FL_ITALIC, textsize()-2);
- fl_draw(buf, X, Y+12);
- Y += comment_incr/2;
- comment_incr -= comment_incr/2;
+void select_none_cb(Fl_Widget *,void *) {
+ Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
+ if (in_this_only) {
+ Fl_Type *t = p;
+ for (; t && t != in_this_only; t = t->parent) {/*empty*/}
+ if (t != in_this_only) p = in_this_only;
}
-
- if (l->new_selected) fl_color(fl_contrast(FL_FOREGROUND_COLOR,FL_SELECTION_COLOR));
- else fl_color(FL_FOREGROUND_COLOR);
-
- // Width=10: Draw the triangle that indicates possible children
- if (l->is_parent()) {
- X = X - 18 - 13;
- if (!l->next || l->next->level <= l->level) {
- if (l->open_!=(l==pushedtitle)) {
- // an outlined triangle to the right indicates closed item, no children
- fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7);
- } else {
- // an outlined triangle to the bottom indicates open item, no children
- fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12);
+ for (;;) {
+ if (p) {
+ int foundany = 0;
+ for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
+ if (t->new_selected) {widget_browser->select(t,0,0); foundany = 1;}
}
+ if (foundany) break;
+ p = p->parent;
} else {
- if (l->open_!=(l==pushedtitle)) {
- // a filled triangle to the right indicates closed item, with children
- fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7);
- } else {
- // a filled triangle to the bottom indicates open item, with children
- fl_polygon(X+2,Y+2,X+7,Y+7,X+2,Y+12);
- }
+ for (Fl_Type *t = Fl_Type::first; t; t = t->next)
+ widget_browser->select(t,0,0);
+ break;
}
- X = X + 13 + 18;
- }
-
- // Width=18: Draw the icon associated with the type.
- Fl_Pixmap *pm = pixmap[l->pixmapID()];
- if (pm) pm->draw(X-18, Y);
-
- // Add tags on top of the icon for locked and protected types.
- switch (l->is_public()) {
- case 0: lock_pixmap->draw(X - 17, Y); break;
- case 2: protected_pixmap->draw(X - 17, Y); break;
}
+ selection_changed(p);
+}
- if ( l->is_widget()
- && !l->is_window()
- && ((Fl_Widget_Type*)l)->o
- && !((Fl_Widget_Type*)l)->o->visible()
- && (!l->parent || ( strcmp(l->parent->type_name(),"Fl_Tabs")
- && strcmp(l->parent->type_name(),"Fl_Wizard")) )
- )
- {
- invisible_pixmap->draw(X - 17, Y);
+// move selected widgets in their parent's list:
+void earlier_cb(Fl_Widget*,void*) {
+ Fl_Type *f;
+ int mod = 0;
+ for (f = Fl_Type::first; f; ) {
+ Fl_Type* nxt = f->next;
+ if (f->selected) {
+ Fl_Type* g;
+ for (g = f->prev; g && g->level > f->level; g = g->prev) {/*empty*/}
+ if (g && g->level == f->level && !g->selected) {
+ f->move_before(g);
+ mod = 1;
+ }
+ }
+ f = nxt;
}
+ if (mod) set_modflag(1);
+}
- // Indent=12 per level: Now write the text that comes after the graphics representation
- Y += comment_incr;
- if (l->is_widget() || l->is_class()) {
- const char* c = subclassname(l);
- if (!strncmp(c,"Fl_",3)) c += 3;
- fl_font(textfont(), textsize());
- fl_draw(c, X, Y+13);
- X += int(fl_width(c)+fl_width('n'));
- c = l->name();
- if (c) {
- fl_font(textfont()|FL_BOLD, textsize());
- fl_draw(c, X, Y+13);
- } else if ((c = l->label())) {
- copy_trunc(buf, c, 20, 1); // quoted string
- fl_draw(buf, X, Y+13);
+void later_cb(Fl_Widget*,void*) {
+ Fl_Type *f;
+ int mod = 0;
+ for (f = Fl_Type::last; f; ) {
+ Fl_Type* prv = f->prev;
+ if (f->selected) {
+ Fl_Type* g;
+ for (g = f->next; g && g->level > f->level; g = g->next) {/*empty*/}
+ if (g && g->level == f->level && !g->selected) {
+ g->move_before(f);
+ mod = 1;
+ }
}
- } else {
- copy_trunc(buf, l->title(), 55, 0);
- fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
- fl_draw(buf, X, Y+13);
+ f = prv;
}
+ if (mod) set_modflag(1);
+}
- // draw a thin line below the item if this item is not selected
- // (if it is selected this additional line would look bad)
- if (!l->new_selected) {
- fl_color(fl_lighter(FL_GRAY));
- fl_line(x1,Y+16,x1+w1,Y+16);
+static void delete_children(Fl_Type *p) {
+ Fl_Type *f;
+ for (f = p; f && f->next && f->next->level > p->level; f = f->next) {/*empty*/}
+ for (; f != p; ) {
+ Fl_Type *g = f->prev;
+ delete f;
+ f = g;
}
}
-int Widget_Browser::item_width(void *v) const {
-
- char buf[340]; // edit buffer: large enough to hold 80 UTF-8 chars + nul
-
- Fl_Type *l = (Fl_Type *)v;
-
- if (!l->visible) return 0;
-
- int W = 3 + 13 + 18 + l->level * 12;
-
- if (l->is_widget() || l->is_class()) {
- const char* c = l->type_name();
- if (!strncmp(c,"Fl_",3)) c += 3;
- fl_font(textfont(), textsize());
- W += int(fl_width(c) + fl_width('n'));
- c = l->name();
- if (c) {
- fl_font(textfont()|FL_BOLD, textsize());
- W += int(fl_width(c));
- } else if (l->label()) {
- copy_trunc(buf, l->label(), 20, 1); // quoted string
- W += int(fl_width(buf));
- }
- } else {
- copy_trunc(buf, l->title(), 55, 0);
- fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
- W += int(fl_width(buf));
+// object list operations:
+void delete_all(int selected_only) {
+ for (Fl_Type *f = Fl_Type::first; f;) {
+ if (f->selected || !selected_only) {
+ delete_children(f);
+ Fl_Type *g = f->next;
+ delete f;
+ f = g;
+ } else f = f->next;
+ }
+ if(!selected_only) {
+ include_H_from_C=1;
+ use_FL_COMMAND=0;
}
- return W;
-}
-
-void redraw_browser() {
- widget_browser->redraw();
+ selection_changed(0);
}
-void Widget_Browser::callback() {
- selection_changed((Fl_Type*)selection());
+// update a string member:
+// replace a string pointer with new value, strips leading/trailing blanks:
+int storestring(const char *n, const char * & p, int nostrip) {
+ if (n == p) return 0;
+ undo_checkpoint();
+ int length = 0;
+ if (n) { // see if blank, strip leading & trailing blanks
+ if (!nostrip) while (isspace((int)(unsigned char)*n)) n++;
+ const char *e = n + strlen(n);
+ if (!nostrip) while (e > n && isspace((int)(unsigned char)*(e-1))) e--;
+ length = int(e-n);
+ if (!length) n = 0;
+ }
+ if (n == p) return 0;
+ if (n && p && !strncmp(n,p,length) && !p[length]) return 0;
+ if (p) free((void *)p);
+ if (!n || !*n) {
+ p = 0;
+ } else {
+ char *q = (char *)malloc(length+1);
+ strlcpy(q,n,length+1);
+ p = q;
+ }
+ set_modflag(1);
+ return 1;
}
-
-/**
- Override the event handling for this browser.
-
- The vertical mouse position corresponds to an entry in the type tree.
- The horizontal position has the following hot zones:
- - 0-3 is the widget frame and ignored
- - the next hot zone starts 12*indent pixels further to the right
- - the next 13 pixels refer to the arrow that indicates children for the item
- - 18 pixels follow for the icon
- - the remaining part is filled with text
-
- \param[in] e the incoming event type
- \return 0 if the event is not supported, and 1 if the event was "used up"
-*/
-int Widget_Browser::handle(int e) {
- static Fl_Type *title;
- Fl_Type *l;
- int X,Y,W,H; bbox(X,Y,W,H);
- switch (e) {
- case FL_PUSH:
- if (!Fl::event_inside(X,Y,W,H)) break;
- l = (Fl_Type*)find_item(Fl::event_y());
- if (l) {
- X += 3 + 12*l->level - hposition();
- if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) {
- title = pushedtitle = l;
- redraw_line(l);
- return 1;
- }
- }
- break;
- case FL_DRAG:
- if (!title) break;
- l = (Fl_Type*)find_item(Fl::event_y());
- if (l) {
- X += 3 + 12*l->level - hposition();
- if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) ;
- else l = 0;
- }
- if (l != pushedtitle) {
- if (pushedtitle) redraw_line(pushedtitle);
- if (l) redraw_line(l);
- pushedtitle = l;
- }
- return 1;
- case FL_RELEASE:
- if (!title) {
- l = (Fl_Type*)find_item(Fl::event_y());
- if (l && l->new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL)))
- l->open();
- break;
- }
- l = pushedtitle;
- title = pushedtitle = 0;
- if (l) {
- if (l->open_) {
- l->open_ = 0;
- for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
- k->visible = 0;
- } else {
- l->open_ = 1;
- for (Fl_Type*k=l->next; k&&k->level>l->level;) {
- k->visible = 1;
- if (k->is_parent() && !k->open_) {
- Fl_Type *j;
- for (j = k->next; j && j->level>k->level; j = j->next) {/*empty*/}
- k = j;
- } else
- k = k->next;
- }
- }
- redraw();
- }
- return 1;
+void fixvisible(Fl_Type *p) {
+ Fl_Type *t = p;
+ for (;;) {
+ if (t->parent) t->visible = t->parent->visible && t->parent->open_;
+ else t->visible = 1;
+ t = t->next;
+ if (!t || t->level <= p->level) break;
}
- return Fl_Browser_::handle(e);
}
+// ---- implemenation of Fl_Type
+
Fl_Type::Fl_Type() {
factory = 0;
parent = 0;
@@ -441,21 +227,28 @@ Fl_Type::Fl_Type() {
code_position_end = header_position_end = -1;
}
-static void fixvisible(Fl_Type *p) {
- Fl_Type *t = p;
- for (;;) {
- if (t->parent) t->visible = t->parent->visible && t->parent->open_;
- else t->visible = 1;
- t = t->next;
- if (!t || t->level <= p->level) break;
- }
+Fl_Type::~Fl_Type() {
+ // warning: destructor only works for widgets that have been add()ed.
+ if (widget_browser) widget_browser->deleting(this);
+ if (prev) prev->next = next; else first = next;
+ if (next) next->prev = prev; else last = prev;
+ if (current == this) current = 0;
+ if (parent) parent->remove_child(this);
+ if (name_) free((void*)name_);
+ if (label_) free((void*)label_);
+ if (callback_) free((void*)callback_);
+ if (user_data_) free((void*)user_data_);
+ if (user_data_type_) free((void*)user_data_type_);
+ if (comment_) free((void*)comment_);
}
-// turn a click at x,y on this into the actual picked object:
-Fl_Type* Fl_Type::click_test(int,int) {return 0;}
-void Fl_Type::add_child(Fl_Type*, Fl_Type*) {}
-void Fl_Type::move_child(Fl_Type*, Fl_Type*) {}
-void Fl_Type::remove_child(Fl_Type*) {}
+// Generate a descriptive text for this item, to put in browser & window titles
+const char* Fl_Type::title() {
+ const char* c = name();
+ if (c)
+ return c;
+ return type_name();
+}
// add a list of widgets as a new child of p:
void Fl_Type::add(Fl_Type *p) {
@@ -516,8 +309,7 @@ void Fl_Type::insert(Fl_Type *g) {
}
// Return message number for I18N...
-int
-Fl_Type::msgnum() {
+int Fl_Type::msgnum() {
int count;
Fl_Type *p;
@@ -532,53 +324,34 @@ Fl_Type::msgnum() {
return count;
}
-
-// delete from parent:
+/**
+ Remove this node and all its children from the parent node.
+ \return the node that follows this node after the operation; can be NULL
+ */
Fl_Type *Fl_Type::remove() {
+ // -- find the last child of this node
Fl_Type *end = this;
for (;;) {
if (!end->next || end->next->level <= level) break;
end = end->next;
}
+ // -- unlink this node from the previous one
if (prev) prev->next = end->next;
else first = end->next;
+ // -- unlink the last child from their next node
if (end->next) end->next->prev = prev;
else last = prev;
Fl_Type *r = end->next;
prev = end->next = 0;
+ // -- allow the parent to update changes in the UI
if (parent) parent->remove_child(this);
parent = 0;
+ widget_browser->redraw_lines();
widget_browser->redraw();
selection_changed(0);
return r;
}
-// update a string member:
-int storestring(const char *n, const char * & p, int nostrip) {
- if (n == p) return 0;
- undo_checkpoint();
- int length = 0;
- if (n) { // see if blank, strip leading & trailing blanks
- if (!nostrip) while (isspace((int)(unsigned char)*n)) n++;
- const char *e = n + strlen(n);
- if (!nostrip) while (e > n && isspace((int)(unsigned char)*(e-1))) e--;
- length = int(e-n);
- if (!length) n = 0;
- }
- if (n == p) return 0;
- if (n && p && !strncmp(n,p,length) && !p[length]) return 0;
- if (p) free((void *)p);
- if (!n || !*n) {
- p = 0;
- } else {
- char *q = (char *)malloc(length+1);
- strlcpy(q,n,length+1);
- p = q;
- }
- set_modflag(1);
- return 1;
-}
-
void Fl_Type::name(const char *n) {
int nostrip = is_comment();
if (storestring(n,name_,nostrip)) {
@@ -615,125 +388,6 @@ void Fl_Type::open() {
printf("Open of '%s' is not yet implemented\n",type_name());
}
-void Fl_Type::setlabel(const char *) {}
-
-Fl_Type::~Fl_Type() {
- // warning: destructor only works for widgets that have been add()ed.
- if (widget_browser) widget_browser->deleting(this);
- if (prev) prev->next = next; else first = next;
- if (next) next->prev = prev; else last = prev;
- if (current == this) current = 0;
- if (parent) parent->remove_child(this);
- if (name_) free((void*)name_);
- if (label_) free((void*)label_);
- if (callback_) free((void*)callback_);
- if (user_data_) free((void*)user_data_);
- if (user_data_type_) free((void*)user_data_type_);
- if (comment_) free((void*)comment_);
-}
-
-int Fl_Type::is_parent() const {return 0;}
-int Fl_Type::is_widget() const {return 0;}
-int Fl_Type::is_valuator() const {return 0;}
-int Fl_Type::is_spinner() const {return 0;}
-int Fl_Type::is_button() const {return 0;}
-int Fl_Type::is_input() const {return 0;}
-int Fl_Type::is_value_input() const {return 0;}
-int Fl_Type::is_text_display() const {return 0;}
-int Fl_Type::is_menu_item() const {return 0;}
-int Fl_Type::is_menu_button() const {return 0;}
-int Fl_Type::is_group() const {return 0;}
-int Fl_Type::is_window() const {return 0;}
-int Fl_Type::is_code() const {return 0;}
-int Fl_Type::is_code_block() const {return 0;}
-int Fl_Type::is_decl_block() const {return 0;}
-int Fl_Type::is_comment() const {return 0;}
-int Fl_Type::is_class() const {return 0;}
-int Fl_Type::is_public() const {return 1;}
-
-int Fl_Code_Type::is_public()const { return -1; }
-int Fl_CodeBlock_Type::is_public()const { return -1; }
-
-
-////////////////////////////////////////////////////////////////
-
-Fl_Type *in_this_only; // set if menu popped-up in window
-
-void select_all_cb(Fl_Widget *,void *) {
- Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
- if (in_this_only) {
- Fl_Type *t = p;
- for (; t && t != in_this_only; t = t->parent) {/*empty*/}
- if (t != in_this_only) p = in_this_only;
- }
- for (;;) {
- if (p) {
- int foundany = 0;
- for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
- if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;}
- }
- if (foundany) break;
- p = p->parent;
- } else {
- for (Fl_Type *t = Fl_Type::first; t; t = t->next)
- widget_browser->select(t,1,0);
- break;
- }
- }
- selection_changed(p);
-}
-
-void select_none_cb(Fl_Widget *,void *) {
- Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
- if (in_this_only) {
- Fl_Type *t = p;
- for (; t && t != in_this_only; t = t->parent) {/*empty*/}
- if (t != in_this_only) p = in_this_only;
- }
- for (;;) {
- if (p) {
- int foundany = 0;
- for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
- if (t->new_selected) {widget_browser->select(t,0,0); foundany = 1;}
- }
- if (foundany) break;
- p = p->parent;
- } else {
- for (Fl_Type *t = Fl_Type::first; t; t = t->next)
- widget_browser->select(t,0,0);
- break;
- }
- }
- selection_changed(p);
-}
-
-static void delete_children(Fl_Type *p) {
- Fl_Type *f;
- for (f = p; f && f->next && f->next->level > p->level; f = f->next) {/*empty*/}
- for (; f != p; ) {
- Fl_Type *g = f->prev;
- delete f;
- f = g;
- }
-}
-
-void delete_all(int selected_only) {
- for (Fl_Type *f = Fl_Type::first; f;) {
- if (f->selected || !selected_only) {
- delete_children(f);
- Fl_Type *g = f->next;
- delete f;
- f = g;
- } else f = f->next;
- }
- if(!selected_only) {
- include_H_from_C=1;
- use_FL_COMMAND=0;
- }
-
- selection_changed(0);
-}
-
// move f (and its children) into list before g:
// returns pointer to whatever is after f & children
void Fl_Type::move_before(Fl_Type* g) {
@@ -756,45 +410,6 @@ void Fl_Type::move_before(Fl_Type* g) {
}
-// move selected widgets in their parent's list:
-void earlier_cb(Fl_Widget*,void*) {
- Fl_Type *f;
- int mod = 0;
- for (f = Fl_Type::first; f; ) {
- Fl_Type* nxt = f->next;
- if (f->selected) {
- Fl_Type* g;
- for (g = f->prev; g && g->level > f->level; g = g->prev) {/*empty*/}
- if (g && g->level == f->level && !g->selected) {
- f->move_before(g);
- mod = 1;
- }
- }
- f = nxt;
- }
- if (mod) set_modflag(1);
-}
-
-void later_cb(Fl_Widget*,void*) {
- Fl_Type *f;
- int mod = 0;
- for (f = Fl_Type::last; f; ) {
- Fl_Type* prv = f->prev;
- if (f->selected) {
- Fl_Type* g;
- for (g = f->next; g && g->level > f->level; g = g->next) {/*empty*/}
- if (g && g->level == f->level && !g->selected) {
- g->move_before(f);
- mod = 1;
- }
- }
- f = prv;
- }
- if (mod) set_modflag(1);
-}
-
-////////////////////////////////////////////////////////////////
-
// write a widget and all its children:
void Fl_Type::write() {
write_indent(level);
@@ -871,21 +486,6 @@ void Fl_Type::read_property(const char *c) {
int Fl_Type::read_fdesign(const char*, const char*) {return 0;}
/**
- Return 1 if the list contains a function with the given signature at the top level.
- */
-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;
-}
-
-/**
Write a comment into the header file.
*/
void Fl_Type::write_comment_h(const char *pre)
@@ -963,25 +563,6 @@ void Fl_Type::write_comment_inline_c(const char *pre)
}
/**
- Make sure that the given item is visible in the browser by opening
- all parent groups and moving the item into the visible space.
-*/
-void reveal_in_browser(Fl_Type *t) {
- Fl_Type *p = t->parent;
- if (p) {
- for (;;) {
- if (!p->open_)
- p->open_ = 1;
- if (!p->parent) break;
- p = p->parent;
- }
- fixvisible(p);
- }
- widget_browser->display(t);
- redraw_browser();
-}
-
-/**
Build widgets and dataset needed in live mode.
\return a widget pointer that the live mode initiator can 'show()'
\see leave_live_mode()
@@ -1019,3 +600,56 @@ int Fl_Type::user_defined(const char* cbname) const {
return 1;
return 0;
}
+
+const char *Fl_Type::callback_name() {
+ if (is_name(callback())) return callback();
+ return unique_id(this, "cb", name(), label());
+}
+
+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;
+}
+
+/**
+ If this Type resides inside a class, this function returns the class type, or null.
+ */
+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;
+}
+
+void Fl_Type::write_static() {
+}
+
+void Fl_Type::write_code1() {
+ write_h("// Header for %s\n", title());
+ write_c("// Code for %s\n", title());
+}
+
+void Fl_Type::write_code2() {
+}
+
diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h
index 3f7c9bde1..9027b4fc5 100644
--- a/fluid/Fl_Type.h
+++ b/fluid/Fl_Type.h
@@ -14,39 +14,30 @@
// https://www.fltk.org/bugs.php
//
-// Each object described by Fluid is one of these objects. They
-// are all stored in a double-linked list.
-//
-// There is also a single "factory" instance of each type of this.
-// The method "make()" is called on this factory to create a new
-// instance of this object. It could also have a "copy()" function,
-// but it was easier to implement this by using the file read/write
-// that is needed to save the setup anyways.
+#ifndef _FLUID_FL_TYPE_H
+#define _FLUID_FL_TYPE_H
#include <FL/Fl_Widget.H>
-#include <FL/Fl_Menu.H>
-#include <FL/Fl_Plugin.H>
-#include "Fluid_Image.h"
#include <FL/fl_draw.H>
-#include <FL/fl_attr.h>
-#include <stdarg.h>
-#include <stdlib.h>
+class Fl_Type;
-#ifdef _WIN32
- #include "ExternalCodeEditor_WIN32.h"
-#else
- #include "ExternalCodeEditor_UNIX.h"
-#endif
+void fixvisible(Fl_Type *p);
+void delete_all(int selected_only=0);
+int storestring(const char *n, const char * & p, int nostrip=0);
-void set_modflag(int mf);
+void select_all_cb(Fl_Widget *,void *);
+void select_none_cb(Fl_Widget *,void *);
+void earlier_cb(Fl_Widget*,void*);
+void later_cb(Fl_Widget*,void*);
class Fl_Type {
friend class Widget_Browser;
friend Fl_Widget *make_type_browser(int,int,int,int,const char *);
friend class Fl_Window_Type;
- virtual void setlabel(const char *); // virtual part of label(char*)
+
+ virtual void setlabel(const char *) { } // virtual part of label(char*)
protected:
@@ -107,10 +98,10 @@ public:
const char *comment() { return comment_; }
void comment(const char *);
- virtual Fl_Type* click_test(int,int);
- virtual void add_child(Fl_Type*, Fl_Type* beforethis);
- virtual void move_child(Fl_Type*, Fl_Type* beforethis);
- virtual void remove_child(Fl_Type*);
+ virtual Fl_Type* click_test(int,int) { return NULL; }
+ virtual void add_child(Fl_Type*, Fl_Type* beforethis) { }
+ virtual void move_child(Fl_Type*, Fl_Type* beforethis) { }
+ virtual void remove_child(Fl_Type*) { }
static Fl_Type *current; // most recently picked object
virtual void open(); // what happens when you double-click
@@ -138,24 +129,24 @@ public:
int msgnum();
// fake rtti:
- virtual int is_parent() const;
- virtual int is_widget() const;
- virtual int is_button() const;
- virtual int is_input() const;
- virtual int is_value_input() const;
- virtual int is_text_display() const;
- virtual int is_valuator() const;
- virtual int is_spinner() const;
- virtual int is_menu_item() const;
- virtual int is_menu_button() const;
- virtual int is_group() const;
- virtual int is_window() const;
- virtual int is_code() const;
- virtual int is_code_block() const;
- virtual int is_decl_block() const;
- virtual int is_comment() const;
- virtual int is_class() const;
- virtual int is_public() const;
+ virtual int is_parent() const {return 0;}
+ virtual int is_widget() const {return 0;}
+ virtual int is_button() const {return 0;}
+ virtual int is_input() const {return 0;}
+ virtual int is_value_input() const {return 0;}
+ virtual int is_text_display() const {return 0;}
+ virtual int is_valuator() const {return 0;}
+ virtual int is_spinner() const {return 0;}
+ virtual int is_menu_item() const {return 0;}
+ virtual int is_menu_button() const {return 0;}
+ virtual int is_group() const {return 0;}
+ virtual int is_window() const {return 0;}
+ virtual int is_code() const {return 0;}
+ virtual int is_code_block() const {return 0;}
+ virtual int is_decl_block() const {return 0;}
+ virtual int is_comment() const {return 0;}
+ virtual int is_class() const {return 0;}
+ virtual int is_public() const {return 1;}
virtual int pixmapID() { return 0; }
@@ -163,767 +154,4 @@ public:
const class Fl_Class_Type* is_in_class() const;
};
-class Fl_Function_Type : public Fl_Type {
- const char* return_type;
- char public_, cdecl_, constructor, havewidgets;
-public:
- Fl_Function_Type() :
- Fl_Type(),
- return_type(0L), public_(0), cdecl_(0), constructor(0), havewidgets(0)
- { }
- ~Fl_Function_Type() {
- if (return_type) free((void*)return_type);
- }
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void open();
- int ismain() {return name_ == 0;}
- virtual const char *type_name() {return "Function";}
- virtual const char *title() {
- return name() ? name() : "main()";
- }
- int is_parent() const {return 1;}
- int is_code_block() const {return 1;}
- virtual int is_public() const;
- int pixmapID() { return 7; }
- void write_properties();
- void read_property(const char *);
- int has_signature(const char *, const char*) const;
-};
-
-class Fl_Code_Type : public Fl_Type {
- ExternalCodeEditor editor_;
- int cursor_position_;
-public:
- Fl_Code_Type() { cursor_position_ = 0; }
- Fl_Type *make();
- void write();
- void write_code1();
- void write_code2();
- void open();
- virtual const char *type_name() {return "code";}
- int is_code_block() const {return 0;}
- int is_code() const {return 1;}
- int pixmapID() { return 8; }
- virtual int is_public() const;
- // See if external editor is open
- int is_editing() {
- return editor_.is_editing();
- }
- // Reap the editor's pid
- // Returns:
- // -2 -- editor not open
- // -1 -- wait failed
- // 0 -- process still running
- // >0 -- process finished + reaped (returns pid)
- //
- int 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
- //
- // Returns:
- // 0 -- file unchanged or not editing
- // 1 -- file changed, internal records updated, 'code' has new content
- // -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 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;
- }
-};
-
-class Fl_CodeBlock_Type : public Fl_Type {
- const char* after;
-public:
- Fl_CodeBlock_Type() : Fl_Type(), after(0L) { }
- ~Fl_CodeBlock_Type() {
- if (after) free((void*)after);
- }
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void open();
- virtual const char *type_name() {return "codeblock";}
- int is_code_block() const {return 1;}
- int is_parent() const {return 1;}
- virtual int is_public() const;
- int pixmapID() { return 9; }
- void write_properties();
- void read_property(const char *);
-};
-
-class Fl_Decl_Type : public Fl_Type {
-protected:
- char public_;
- char static_;
-public:
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void open();
- virtual const char *type_name() {return "decl";}
- void write_properties();
- void read_property(const char *);
- virtual int is_public() const;
- int pixmapID() { return 10; }
-};
-
-class Fl_Data_Type : public Fl_Decl_Type {
- const char *filename_;
- int text_mode_;
-public:
- Fl_Data_Type() : Fl_Decl_Type(), filename_(0L), text_mode_(0) { }
- ~Fl_Data_Type() {
- if (filename_) free((void*)filename_);
- }
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void open();
- virtual const char *type_name() {return "data";}
- void write_properties();
- void read_property(const char *);
- int pixmapID() { return 49; }
-};
-
-class Fl_DeclBlock_Type : public Fl_Type {
- const char* after;
- char public_;
-public:
- Fl_DeclBlock_Type() : Fl_Type(), after(0L) { }
- ~Fl_DeclBlock_Type() {
- if (after) free((void*)after);
- }
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void open();
- virtual const char *type_name() {return "declblock";}
- void write_properties();
- void read_property(const char *);
- int is_parent() const {return 1;}
- int is_decl_block() const {return 1;}
- virtual int is_public() const;
- int pixmapID() { return 11; }
-};
-
-class Fl_Comment_Type : public Fl_Type {
- char in_c_, in_h_, style_;
- char title_buf[64];
-public:
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void open();
- virtual const char *type_name() {return "comment";}
- virtual const char *title(); // string for browser
- void write_properties();
- void read_property(const char *);
- virtual int is_public() const { return 1; }
- virtual int is_comment() const { return 1; }
- int pixmapID() { return 46; }
-};
-
-class Fl_Class_Type : public Fl_Type {
- const char* subclass_of;
- char public_;
-public:
- Fl_Class_Type() : Fl_Type(), subclass_of(0L) { }
- ~Fl_Class_Type() {
- if (subclass_of) free((void*)subclass_of);
- }
-
- // state variables for output:
- char write_public_state; // true when public: has been printed
- Fl_Class_Type* parent_class; // save class if nested
-//
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void open();
- virtual const char *type_name() {return "class";}
- int is_parent() const {return 1;}
- int is_decl_block() const {return 1;}
- int is_class() const {return 1;}
- virtual int is_public() const;
- int pixmapID() { return 12; }
- void write_properties();
- void read_property(const char *);
-
- // class prefix attribute access
- void prefix(const char* p);
- const char* prefix() const {return class_prefix;}
- int has_function(const char*, const char*) const;
-private:
- const char* class_prefix;
-};
-
-#define NUM_EXTRA_CODE 4
-
-class Fl_Widget_Type : public Fl_Type {
- virtual Fl_Widget *widget(int,int,int,int) = 0;
- virtual Fl_Widget_Type *_make() = 0; // virtual constructor
- virtual void setlabel(const char *);
-
- const char *extra_code_[NUM_EXTRA_CODE];
- const char *subclass_;
- const char *tooltip_;
- const char *image_name_;
- const char *inactive_name_;
- uchar hotspot_;
-
-protected:
-
- void write_static();
- void write_code1();
- void write_widget_code();
- void write_extra_code();
- void write_block_close();
- void write_code2();
- void write_color(const char*, Fl_Color);
- Fl_Widget *live_widget;
-
-public:
- static int default_size;
-
- const char *xclass; // junk string, used for shortcut
- Fl_Widget *o;
- int public_;
-
- Fluid_Image *image;
- void setimage(Fluid_Image *);
- Fluid_Image *inactive;
- void setinactive(Fluid_Image *);
-
- Fl_Widget_Type();
- Fl_Type *make();
- void open();
-
- const char *extra_code(int n) const {return extra_code_[n];}
- void extra_code(int n,const char *);
- const char *subclass() const {return subclass_;}
- void subclass(const char *);
- const char *tooltip() const {return tooltip_;}
- void tooltip(const char *);
- const char *image_name() const {return image_name_;}
- void image_name(const char *);
- const char *inactive_name() const {return inactive_name_;}
- void inactive_name(const char *);
- uchar hotspot() const {return hotspot_;}
- void hotspot(uchar v) {hotspot_ = v;}
- uchar resizable() const;
- void resizable(uchar v);
-
- virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &);
- virtual Fl_Menu_Item *subtypes();
-
- virtual int is_widget() const;
- virtual int is_public() const;
-
- virtual void write_properties();
- virtual void read_property(const char *);
- virtual int read_fdesign(const char*, const char*);
-
- virtual Fl_Widget *enter_live_mode(int top=0);
- virtual void leave_live_mode();
- virtual void copy_properties();
-
- virtual void ideal_size(int &w, int &h);
- virtual void ideal_spacing(int &x, int &y);
-
- ~Fl_Widget_Type();
- void redraw();
-};
-
-#include <FL/Fl_Tabs.H>
-#include <FL/Fl_Pack.H>
-#include <FL/Fl_Wizard.H>
-
-class igroup : public Fl_Group {
-public:
- void resize(int,int,int,int);
- void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); }
- igroup(int X,int Y,int W,int H) : Fl_Group(X,Y,W,H) {Fl_Group::current(0);}
-};
-
-class itabs : public Fl_Tabs {
-public:
- void resize(int,int,int,int);
- void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); }
- itabs(int X,int Y,int W,int H) : Fl_Tabs(X,Y,W,H) {}
-};
-
-class iwizard : public Fl_Wizard {
-public:
- void resize(int,int,int,int);
- void full_resize(int X, int Y, int W, int H) { Fl_Group::resize(X, Y, W, H); }
- iwizard(int X,int Y,int W,int H) : Fl_Wizard(X,Y,W,H) {}
-};
-
-class Fl_Group_Type : public Fl_Widget_Type {
-public:
- virtual const char *type_name() {return "Fl_Group";}
- virtual const char *alt_type_name() {return "fltk::Group";}
- Fl_Widget *widget(int X,int Y,int W,int H) {
- igroup *g = new igroup(X,Y,W,H); Fl_Group::current(0); return g;}
- Fl_Widget_Type *_make() {return new Fl_Group_Type();}
- Fl_Type *make();
- void write_code1();
- void write_code2();
- void add_child(Fl_Type*, Fl_Type*);
- void move_child(Fl_Type*, Fl_Type*);
- void remove_child(Fl_Type*);
- int is_parent() const {return 1;}
- int is_group() const {return 1;}
- int pixmapID() { return 6; }
-
- virtual Fl_Widget *enter_live_mode(int top=0);
- virtual void leave_live_mode();
- virtual void copy_properties();
-};
-
-extern const char pack_type_name[];
-extern Fl_Menu_Item pack_type_menu[];
-
-class Fl_Pack_Type : public Fl_Group_Type {
- Fl_Menu_Item *subtypes() {return pack_type_menu;}
-public:
- virtual const char *type_name() {return pack_type_name;}
- virtual const char *alt_type_name() {return "fltk::PackedGroup";}
- Fl_Widget_Type *_make() {return new Fl_Pack_Type();}
- int pixmapID() { return 22; }
- void copy_properties();
-};
-
-extern const char table_type_name[];
-
-class Fl_Table_Type : public Fl_Group_Type {
-public:
- virtual const char *type_name() {return table_type_name;}
- virtual const char *alt_type_name() {return "fltk::TableGroup";}
- Fl_Widget_Type *_make() {return new Fl_Table_Type();}
- Fl_Widget *widget(int X,int Y,int W,int H);
- int pixmapID() { return 51; }
- virtual Fl_Widget *enter_live_mode(int top=0);
- void add_child(Fl_Type*, Fl_Type*);
- void move_child(Fl_Type*, Fl_Type*);
- void remove_child(Fl_Type*);
-};
-
-extern const char tabs_type_name[];
-
-class Fl_Tabs_Type : public Fl_Group_Type {
-public:
- virtual void ideal_spacing(int &x, int &y) {
- x = 10;
- fl_font(o->labelfont(), o->labelsize());
- y = fl_height() + o->labelsize() - 6;
- }
- virtual const char *type_name() {return tabs_type_name;}
- virtual const char *alt_type_name() {return "fltk::TabGroup";}
- Fl_Widget *widget(int X,int Y,int W,int H) {
- itabs *g = new itabs(X,Y,W,H); Fl_Group::current(0); return g;}
- Fl_Widget_Type *_make() {return new Fl_Tabs_Type();}
- Fl_Type* click_test(int,int);
- void add_child(Fl_Type*, Fl_Type*);
- void remove_child(Fl_Type*);
- int pixmapID() { return 13; }
- Fl_Widget *enter_live_mode(int top=0);
-};
-
-extern const char scroll_type_name[];
-extern Fl_Menu_Item scroll_type_menu[];
-
-class Fl_Scroll_Type : public Fl_Group_Type {
- Fl_Menu_Item *subtypes() {return scroll_type_menu;}
-public:
- virtual const char *type_name() {return scroll_type_name;}
- virtual const char *alt_type_name() {return "fltk::ScrollGroup";}
- Fl_Widget_Type *_make() {return new Fl_Scroll_Type();}
- int pixmapID() { return 19; }
- Fl_Widget *enter_live_mode(int top=0);
- void copy_properties();
-};
-
-extern const char tile_type_name[];
-
-class Fl_Tile_Type : public Fl_Group_Type {
-public:
- virtual const char *type_name() {return tile_type_name;}
- virtual const char *alt_type_name() {return "fltk::TileGroup";}
- Fl_Widget_Type *_make() {return new Fl_Tile_Type();}
- int pixmapID() { return 20; }
- void copy_properties();
-};
-
-extern const char wizard_type_name[];
-
-class Fl_Wizard_Type : public Fl_Group_Type {
-public:
- virtual const char *type_name() {return wizard_type_name;}
- virtual const char *alt_type_name() {return "fltk::WizardGroup";}
- Fl_Widget *widget(int X,int Y,int W,int H) {
- iwizard *g = new iwizard(X,Y,W,H); Fl_Group::current(0); return g;}
- Fl_Widget_Type *_make() {return new Fl_Wizard_Type();}
- int pixmapID() { return 21; }
-};
-
-extern Fl_Menu_Item window_type_menu[];
-
-class Fl_Window_Type : public Fl_Widget_Type {
-protected:
-
- Fl_Menu_Item* subtypes() {return window_type_menu;}
-
- friend class Overlay_Window;
- int mx,my; // mouse position during dragging
- int x1,y1; // initial position of selection box
- int bx,by,br,bt; // bounding box of selection before snapping
- int sx,sy,sr,st; // bounding box of selection after snapping to guides
- int dx,dy;
- int drag; // which parts of bbox are being moved
- int numselected; // number of children selected
- enum {LEFT=1,RIGHT=2,BOTTOM=4,TOP=8,DRAG=16,BOX=32};
- void draw_overlay();
- void newdx();
- void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h);
- int handle(int);
- virtual void setlabel(const char *);
- void write_code1();
- void write_code2();
- Fl_Widget_Type *_make() {return 0;} // we don't call this
- Fl_Widget *widget(int,int,int,int) {return 0;}
- int recalc; // set by fix_overlay()
- void moveallchildren();
- int pixmapID() { return 1; }
-
-public:
-
- Fl_Window_Type() { drag = dx = dy = 0; sr_min_w = sr_min_h = sr_max_w = sr_max_h = 0; }
- uchar modal, non_modal;
-
- Fl_Type *make();
- virtual const char *type_name() {return "Fl_Window";}
- virtual const char *alt_type_name() {return "fltk::Window";}
-
- void open();
-
- void fix_overlay(); // Update the bounding box, etc
- uchar *read_image(int &ww, int &hh); // Read an image of the window
-
- virtual void write_properties();
- virtual void read_property(const char *);
- virtual int read_fdesign(const char*, const char*);
-
- void add_child(Fl_Type*, Fl_Type*);
- void move_child(Fl_Type*, Fl_Type*);
- void remove_child(Fl_Type*);
-
- int is_parent() const {return 1;}
- int is_group() const {return 1;}
- int is_window() const {return 1;}
-
- Fl_Widget *enter_live_mode(int top=0);
- void leave_live_mode();
- void copy_properties();
-
- int sr_min_w, sr_min_h, sr_max_w, sr_max_h;
-
- static int popupx, popupy;
-};
-
-class Fl_Widget_Class_Type : private Fl_Window_Type {
-public:
- Fl_Widget_Class_Type() {
- write_public_state = 0;
- wc_relative = 0;
- }
- // state variables for output:
- char write_public_state; // true when public: has been printed
- char wc_relative; // if true, reposition all child widgets in an Fl_Group
-
- virtual void write_properties();
- virtual void read_property(const char *);
-
- void write_code1();
- void write_code2();
- Fl_Type *make();
- virtual const char *type_name() {return "widget_class";}
- int pixmapID() { return 48; }
- int is_parent() const {return 1;}
- int is_code_block() const {return 1;}
- int is_decl_block() const {return 1;}
- int is_class() const {return 1;}
-};
-
-
-extern Fl_Menu_Item menu_item_type_menu[];
-
-class Fl_Menu_Item_Type : public Fl_Widget_Type {
-public:
- Fl_Menu_Item* subtypes() {return menu_item_type_menu;}
- const char* type_name() {return "MenuItem";}
- const char* alt_type_name() {return "fltk::Item";}
- Fl_Type* make();
- int is_menu_item() const {return 1;}
- int is_button() const {return 1;} // this gets shortcut to work
- Fl_Widget* widget(int,int,int,int) {return 0;}
- Fl_Widget_Type* _make() {return 0;}
- const char* menu_name(int& i);
- int flags();
- void write_static();
- void write_item();
- void write_code1();
- void write_code2();
- int pixmapID() { return 16; }
-};
-
-class Fl_Radio_Menu_Item_Type : public Fl_Menu_Item_Type {
-public:
- const char* type_name() {return "RadioMenuItem";}
- Fl_Type* make();
- int pixmapID() { return 55; }
-};
-
-class Fl_Checkbox_Menu_Item_Type : public Fl_Menu_Item_Type {
-public:
- const char* type_name() {return "CheckMenuItem";}
- Fl_Type* make();
- int pixmapID() { return 54; }
-};
-
-class Fl_Submenu_Type : public Fl_Menu_Item_Type {
-public:
- Fl_Menu_Item* subtypes() {return 0;}
- const char* type_name() {return "Submenu";}
- const char* alt_type_name() {return "fltk::ItemGroup";}
- int is_parent() const {return 1;}
- int is_button() const {return 0;} // disable shortcut
- Fl_Type* make();
- // changes to submenu must propagate up so build_menu is called
- // on the parent Fl_Menu_Type:
- void add_child(Fl_Type*a, Fl_Type*b) {parent->add_child(a,b);}
- void move_child(Fl_Type*a, Fl_Type*b) {parent->move_child(a,b);}
- void remove_child(Fl_Type*a) {parent->remove_child(a);}
- int pixmapID() { return 18; }
-};
-
-
-
-#include <FL/Fl_Menu_.H>
-class Fl_Menu_Type : public Fl_Widget_Type {
- int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
- Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
- switch (w) {
- case 4:
- case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break;
- case 1: myo->textfont(f); break;
- case 2: myo->textsize(s); break;
- case 3: myo->textcolor(c); break;
- }
- return 1;
- }
-public:
- int is_menu_button() const {return 1;}
- int is_parent() const {return 1;}
- int menusize;
- virtual void build_menu();
- Fl_Menu_Type() : Fl_Widget_Type() {menusize = 0;}
- ~Fl_Menu_Type() {
- if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu());
- }
- void add_child(Fl_Type*, Fl_Type*) {build_menu();}
- void move_child(Fl_Type*, Fl_Type*) {build_menu();}
- void remove_child(Fl_Type*) {build_menu();}
- Fl_Type* click_test(int x, int y);
- void write_code2();
- void copy_properties();
-};
-
-extern Fl_Menu_Item button_type_menu[];
-
-#include <FL/Fl_Menu_Button.H>
-class Fl_Menu_Button_Type : public Fl_Menu_Type {
- Fl_Menu_Item *subtypes() {return button_type_menu;}
-public:
- virtual void ideal_size(int &w, int &h) {
- Fl_Widget_Type::ideal_size(w, h);
- w += 2 * ((o->labelsize() - 3) & ~1) + o->labelsize() - 4;
- h = (h / 5) * 5;
- if (h < 15) h = 15;
- if (w < (15 + h)) w = 15 + h;
- }
- virtual const char *type_name() {return "Fl_Menu_Button";}
- virtual const char *alt_type_name() {return "fltk::MenuButton";}
- Fl_Widget *widget(int X,int Y,int W,int H) {
- return new Fl_Menu_Button(X,Y,W,H,"menu");}
- Fl_Widget_Type *_make() {return new Fl_Menu_Button_Type();}
- int pixmapID() { return 26; }
-};
-
-extern Fl_Menu_Item dummymenu[];
-
-#include <FL/Fl_Choice.H>
-class Fl_Choice_Type : public Fl_Menu_Type {
-public:
- virtual void ideal_size(int &w, int &h) {
- Fl_Widget_Type::ideal_size(w, h);
- int w1 = o->h() - Fl::box_dh(o->box());
- if (w1 > 20) w1 = 20;
- w1 = (w1 - 4) / 3;
- if (w1 < 1) w1 = 1;
- w += 2 * w1 + o->labelsize() - 4;
- h = (h / 5) * 5;
- if (h < 15) h = 15;
- if (w < (15 + h)) w = 15 + h;
- }
- virtual const char *type_name() {return "Fl_Choice";}
- virtual const char *alt_type_name() {return "fltk::Choice";}
- Fl_Widget *widget(int X,int Y,int W,int H) {
- Fl_Choice *myo = new Fl_Choice(X,Y,W,H,"choice:");
- myo->menu(dummymenu);
- return myo;
- }
- Fl_Widget_Type *_make() {return new Fl_Choice_Type();}
- int pixmapID() { return 15; }
-};
-
-#include <FL/Fl_Input_Choice.H>
-class Fl_Input_Choice_Type : public Fl_Menu_Type {
- int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
- Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
- switch (w) {
- case 4:
- case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break;
- case 1: myo->textfont(f); break;
- case 2: myo->textsize(s); break;
- case 3: myo->textcolor(c); break;
- }
- return 1;
- }
-public:
- virtual void ideal_size(int &w, int &h) {
- Fl_Input_Choice *myo = (Fl_Input_Choice *)o;
- fl_font(myo->textfont(), myo->textsize());
- h = fl_height() + myo->textsize() - 6;
- w = o->w() - 20 - Fl::box_dw(o->box());
- int ww = (int)fl_width('m');
- w = ((w + ww - 1) / ww) * ww + 20 + Fl::box_dw(o->box());
- if (h < 15) h = 15;
- if (w < (15 + h)) w = 15 + h;
- }
- virtual const char *type_name() {return "Fl_Input_Choice";}
- virtual const char *alt_type_name() {return "fltk::ComboBox";}
- virtual Fl_Type* click_test(int,int);
- Fl_Widget *widget(int X,int Y,int W,int H) {
- Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:");
- myo->menu(dummymenu);
- myo->value("input");
- return myo;
- }
- Fl_Widget_Type *_make() {return new Fl_Input_Choice_Type();}
- virtual void build_menu();
- int pixmapID() { return 53; }
- void copy_properties();
-};
-
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Menu_Bar.H>
-class Fl_Menu_Bar_Type : public Fl_Menu_Type {
-public:
- virtual void ideal_size(int &w, int &h) {
- w = o->window()->w();
- h = ((o->labelsize() + Fl::box_dh(o->box()) + 4) / 5) * 5;
- if (h < 15) h = 15;
- }
- virtual const char *type_name() {return "Fl_Menu_Bar";}
- virtual const char *alt_type_name() {return "fltk::MenuBar";}
- Fl_Widget *widget(int X,int Y,int W,int H) {return new Fl_Menu_Bar(X,Y,W,H);}
- Fl_Widget_Type *_make() {return new Fl_Menu_Bar_Type();}
- int pixmapID() { return 17; }
-};
-// object list operations:
-Fl_Widget *make_widget_browser(int X,int Y,int W,int H);
-void redraw_widget_browser(Fl_Type*);
-extern int modflag;
-void delete_all(int selected_only=0);
-void selection_changed(Fl_Type* new_current);
-void reveal_in_browser(Fl_Type*);
-int has_toplevel_function(const char *rtype, const char *sig);
-
-// file operations:
-void write_word(const char *);
-void write_string(const char *,...) __fl_attr((__format__ (__printf__, 1, 2)));
-int write_file(const char *, int selected_only = 0);
-int write_code(const char *cfile, const char *hfile);
-int write_strings(const char *sfile);
-
-int write_declare(const char *, ...) __fl_attr((__format__ (__printf__, 1, 2)));
-int is_id(char);
-const char* unique_id(void* o, const char*, const char*, const char*);
-void write_c(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2)));
-void write_cc(const char *, int, const char*, const char*);
-void vwrite_c(const char* format, va_list args);
-void write_h(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2)));
-void write_hc(const char *, int, const char*, const char*);
-void write_cstring(const char *);
-void write_cstring(const char *,int length);
-void write_cdata(const char *,int length);
-void write_indent(int n);
-void write_open(int);
-void write_close(int n);
-extern int write_number;
-extern int write_sourceview;
-void write_public(int state); // writes pubic:/private: as needed
-extern int indentation;
-extern const char* indent();
-
-int read_file(const char *, int merge);
-const char *read_word(int wantbrace = 0);
-void read_error(const char *format, ...);
-
-// check legality of c code (sort of) and return error:
-const char *c_check(const char *c, int type = 0);
-
-// replace a string pointer with new value, strips leading/trailing blanks:
-int storestring(const char *n, const char * & p, int nostrip=0);
-
-extern int include_H_from_C;
-extern int use_FL_COMMAND;
-
-/*
- This class is needed for additional command line plugins.
- */
-class Fl_Commandline_Plugin : public Fl_Plugin {
-public:
- Fl_Commandline_Plugin(const char *name)
- : Fl_Plugin(klass(), name) { }
- virtual const char *klass() { return "commandline"; }
- // return a unique name for this plugin
- virtual const char *name() = 0;
- // return a help text for all supported commands
- virtual const char *help() = 0;
- // handle a command and return the number of args used, or 0
- virtual int arg(int argc, char **argv, int &i) = 0;
- // optional test the plugin
- virtual int test(const char *a1=0L, const char *a2=0L, const char *a3=0L) {
- return 0;
- }
- // show a GUI panel to edit some data
- virtual void show_panel() { }
-};
+#endif // _FLUID_FL_TYPE_H
diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx
index 17765dc06..53d0ec06a 100644
--- a/fluid/Fl_Widget_Type.cxx
+++ b/fluid/Fl_Widget_Type.cxx
@@ -14,17 +14,30 @@
// https://www.fltk.org/bugs.php
//
+#include "Fl_Widget_Type.h"
+
+#include "fluid.h"
+#include "Fl_Window_Type.h"
+#include "Fl_Group_Type.h"
+#include "Fl_Menu_Type.h"
+#include "Fl_Function_Type.h"
+#include "file.h"
+#include "code.h"
+#include "Fluid_Image.h"
+#include "alignment_panel.h"
+#include "widget_panel.h"
+
#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Table.H>
#include <FL/Fl_Input.H>
-#include "Fl_Widget_Type.h"
-#include "alignment_panel.h"
#include <FL/fl_message.H>
#include <FL/Fl_Slider.H>
#include <FL/Fl_Spinner.H>
#include <FL/Fl_Window.H>
+#include <FL/fl_show_colormap.H>
#include "../src/flstring.h"
+
#include <stdio.h>
#include <stdlib.h>
@@ -35,16 +48,6 @@
// instance, sets the widget pointers, and makes all the display
// update correctly...
-extern int reading_file;
-int force_parent;
-extern int gridx;
-extern int gridy;
-extern int i18n_type;
-extern const char* i18n_include;
-extern const char* i18n_function;
-extern const char* i18n_file;
-extern const char* i18n_set;
-
int Fl_Widget_Type::default_size = FL_NORMAL_SIZE;
int Fl_Widget_Type::is_widget() const {return 1;}
@@ -164,8 +167,6 @@ Fl_Type *Fl_Widget_Type::make() {
return t;
}
-#include "Fluid_Image.h"
-
void Fl_Widget_Type::setimage(Fluid_Image *i) {
if (i == image || is_window()) return;
if (image) image->decrement();
@@ -287,9 +288,6 @@ Fl_Type *sort(Fl_Type *parent) {
////////////////////////////////////////////////////////////////
// The control panels!
-#include "widget_panel.h"
-#include <FL/fl_show_colormap.H>
-
static Fl_Window *the_panel;
// All the callbacks use the argument to indicate whether to load or store.
@@ -2089,11 +2087,6 @@ void Fl_Widget_Type::write_static() {
}
}
-const char *Fl_Type::callback_name() {
- if (is_name(callback())) return callback();
- return unique_id(this, "cb", name(), label());
-}
-
extern int varused_test, varused;
void Fl_Widget_Type::write_code1() {
@@ -2532,8 +2525,6 @@ void Fl_Widget_Type::write_properties() {
}
}
-int pasteoffset;
-extern double read_version;
void Fl_Widget_Type::read_property(const char *c) {
int x,y,w,h; Fl_Font f; int s; Fl_Color cc;
if (!strcmp(c,"private")) {
@@ -2698,7 +2689,6 @@ Fl_Menu_Item boxmenu1[] = {
{"11", 0,0,(void *)FL_DOWN_FRAME},
{0}};
-extern int fdesign_flip;
int lookup_symbol(const char *, int &, int numberok = 0);
int Fl_Widget_Type::read_fdesign(const char* propname, const char* value) {
diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h
index ab33f4e10..6d39fb9f4 100644
--- a/fluid/Fl_Widget_Type.h
+++ b/fluid/Fl_Widget_Type.h
@@ -18,10 +18,99 @@
// https://www.fltk.org/bugs.php
//
+#ifndef _FLUID_FL_WIDGET_TYPE_H
+#define _FLUID_FL_WIDGET_TYPE_H
+
#include "Fl_Type.h"
-struct Fl_Menu_Item;
+#define NUM_EXTRA_CODE 4
+
+class Fl_Widget_Type;
class Fluid_Image;
extern void* const LOAD;
extern Fl_Widget_Type *current_widget; // one of the selected ones
+
+extern const char* subclassname(Fl_Type* l);
+extern int is_name(const char *c);
+void selection_changed(Fl_Type* new_current);
+Fl_Type *sort(Fl_Type *parent);
+void comment_cb(class Fl_Text_Editor* i, void *v);
+
+class Fl_Widget_Type : public Fl_Type {
+ virtual Fl_Widget *widget(int,int,int,int) = 0;
+ virtual Fl_Widget_Type *_make() = 0; // virtual constructor
+ virtual void setlabel(const char *);
+
+ const char *extra_code_[NUM_EXTRA_CODE];
+ const char *subclass_;
+ const char *tooltip_;
+ const char *image_name_;
+ const char *inactive_name_;
+ uchar hotspot_;
+
+protected:
+
+ void write_static();
+ void write_code1();
+ void write_widget_code();
+ void write_extra_code();
+ void write_block_close();
+ void write_code2();
+ void write_color(const char*, Fl_Color);
+ Fl_Widget *live_widget;
+
+public:
+ static int default_size;
+
+ const char *xclass; // junk string, used for shortcut
+ Fl_Widget *o;
+ int public_;
+
+ Fluid_Image *image;
+ void setimage(Fluid_Image *);
+ Fluid_Image *inactive;
+ void setinactive(Fluid_Image *);
+
+ Fl_Widget_Type();
+ Fl_Type *make();
+ void open();
+
+ const char *extra_code(int n) const {return extra_code_[n];}
+ void extra_code(int n,const char *);
+ const char *subclass() const {return subclass_;}
+ void subclass(const char *);
+ const char *tooltip() const {return tooltip_;}
+ void tooltip(const char *);
+ const char *image_name() const {return image_name_;}
+ void image_name(const char *);
+ const char *inactive_name() const {return inactive_name_;}
+ void inactive_name(const char *);
+ uchar hotspot() const {return hotspot_;}
+ void hotspot(uchar v) {hotspot_ = v;}
+ uchar resizable() const;
+ void resizable(uchar v);
+
+ virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &);
+ virtual Fl_Menu_Item *subtypes();
+
+ virtual int is_widget() const;
+ virtual int is_public() const;
+
+ virtual void write_properties();
+ virtual void read_property(const char *);
+ virtual int read_fdesign(const char*, const char*);
+
+ virtual Fl_Widget *enter_live_mode(int top=0);
+ virtual void leave_live_mode();
+ virtual void copy_properties();
+
+ virtual void ideal_size(int &w, int &h);
+ virtual void ideal_spacing(int &x, int &y);
+
+ ~Fl_Widget_Type();
+ void redraw();
+};
+
+
+#endif // _FLUID_FL_WIDGET_TYPE_H
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
index ff196d2e1..c42d62af7 100644
--- a/fluid/Fl_Window_Type.cxx
+++ b/fluid/Fl_Window_Type.cxx
@@ -18,6 +18,16 @@
// https://www.fltk.org/bugs.php
//
+#include "Fl_Window_Type.h"
+
+#include "fluid.h"
+#include "widget_browser.h"
+#include "undo.h"
+#include "alignment_panel.h"
+#include "file.h"
+#include "code.h"
+#include "widget_panel.h"
+
#include <FL/Fl.H>
#include <FL/Fl_Overlay_Window.H>
#include <FL/fl_message.H>
@@ -25,18 +35,12 @@
#include <FL/platform.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Round_Button.H>
-#include "Fl_Widget_Type.h"
-#include "undo.h"
+#include "../src/flstring.h"
+
#include <math.h>
#include <stdlib.h>
-#include "alignment_panel.h"
#include <stdio.h>
-extern int gridx;
-extern int gridy;
-extern int snap;
-extern int show_guides;
-
int include_H_from_C = 1;
int use_FL_COMMAND = 0;
extern int i18n_type;
@@ -49,8 +53,6 @@ extern Fl_Preferences fluid_prefs;
inline int fl_min(int a, int b) { return (a < b ? a : b); }
-#include "widget_panel.h"
-
// Update the XYWH values in the widget panel...
static void update_xywh() {
if (current_widget && current_widget->is_widget()) {
@@ -174,9 +176,6 @@ void i18n_int_cb(Fl_Int_Input *i, void *) {
set_modflag(1);
}
-extern const char* header_file_name;
-extern const char* code_file_name;
-
void show_project_cb(Fl_Widget *, void *) {
if(project_window==0) make_project_window();
include_H_from_C_button->value(include_H_from_C);
@@ -1350,9 +1349,6 @@ int Fl_Window_Type::handle(int event) {
////////////////////////////////////////////////////////////////
-#include <stdio.h>
-#include "../src/flstring.h"
-
void Fl_Window_Type::write_code1() {
Fl_Widget_Type::write_code1();
}
@@ -1393,7 +1389,6 @@ void Fl_Window_Type::write_properties() {
if (o->visible()) write_string("visible");
}
-extern int pasteoffset;
void Fl_Window_Type::read_property(const char *c) {
if (!strcmp(c,"modal")) {
modal = 1;
diff --git a/fluid/Fl_Window_Type.h b/fluid/Fl_Window_Type.h
new file mode 100644
index 000000000..4067d03f9
--- /dev/null
+++ b/fluid/Fl_Window_Type.h
@@ -0,0 +1,125 @@
+//
+// Widget type header file for the Fast Light Tool Kit (FLTK).
+//
+// Type for creating all subclasses of Fl_Widget
+// This should have the widget pointer in it, but it is still in the
+// Fl_Type base class.
+//
+// Copyright 1998-2010 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_FL_WINDOW_TYPE_H
+#define _FLUID_FL_WINDOW_TYPE_H
+
+#include "Fl_Widget_Type.h"
+
+class Fl_Widget_Class_Type;
+
+extern int include_H_from_C;
+extern int use_FL_COMMAND;
+
+extern Fl_Menu_Item window_type_menu[];
+extern Fl_Widget_Class_Type *current_widget_class;
+void toggle_overlays(Fl_Widget *,void *);
+void show_project_cb(Fl_Widget *, void *);
+void show_grid_cb(Fl_Widget *, void *);
+void show_settings_cb(Fl_Widget *, void *);
+void show_global_settings_cb(Fl_Widget *, void *);
+
+class Fl_Window_Type : public Fl_Widget_Type {
+protected:
+
+ Fl_Menu_Item* subtypes() {return window_type_menu;}
+
+ friend class Overlay_Window;
+ int mx,my; // mouse position during dragging
+ int x1,y1; // initial position of selection box
+ int bx,by,br,bt; // bounding box of selection before snapping
+ int sx,sy,sr,st; // bounding box of selection after snapping to guides
+ int dx,dy;
+ int drag; // which parts of bbox are being moved
+ int numselected; // number of children selected
+ enum {LEFT=1,RIGHT=2,BOTTOM=4,TOP=8,DRAG=16,BOX=32};
+ void draw_overlay();
+ void newdx();
+ void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h);
+ int handle(int);
+ virtual void setlabel(const char *);
+ void write_code1();
+ void write_code2();
+ Fl_Widget_Type *_make() {return 0;} // we don't call this
+ Fl_Widget *widget(int,int,int,int) {return 0;}
+ int recalc; // set by fix_overlay()
+ void moveallchildren();
+ int pixmapID() { return 1; }
+
+public:
+
+ Fl_Window_Type() { drag = dx = dy = 0; sr_min_w = sr_min_h = sr_max_w = sr_max_h = 0; }
+ uchar modal, non_modal;
+
+ Fl_Type *make();
+ virtual const char *type_name() {return "Fl_Window";}
+ virtual const char *alt_type_name() {return "fltk::Window";}
+
+ void open();
+
+ void fix_overlay(); // Update the bounding box, etc
+ uchar *read_image(int &ww, int &hh); // Read an image of the window
+
+ virtual void write_properties();
+ virtual void read_property(const char *);
+ virtual int read_fdesign(const char*, const char*);
+
+ void add_child(Fl_Type*, Fl_Type*);
+ void move_child(Fl_Type*, Fl_Type*);
+ void remove_child(Fl_Type*);
+
+ int is_parent() const {return 1;}
+ int is_group() const {return 1;}
+ int is_window() const {return 1;}
+
+ Fl_Widget *enter_live_mode(int top=0);
+ void leave_live_mode();
+ void copy_properties();
+
+ int sr_min_w, sr_min_h, sr_max_w, sr_max_h;
+
+ static int popupx, popupy;
+};
+
+class Fl_Widget_Class_Type : private Fl_Window_Type {
+public:
+ Fl_Widget_Class_Type() {
+ write_public_state = 0;
+ wc_relative = 0;
+ }
+ // state variables for output:
+ char write_public_state; // true when public: has been printed
+ char wc_relative; // if true, reposition all child widgets in an Fl_Group
+
+ virtual void write_properties();
+ virtual void read_property(const char *);
+
+ void write_code1();
+ void write_code2();
+ Fl_Type *make();
+ virtual const char *type_name() {return "widget_class";}
+ int pixmapID() { return 48; }
+ int is_parent() const {return 1;}
+ int is_code_block() const {return 1;}
+ int is_decl_block() const {return 1;}
+ int is_class() const {return 1;}
+};
+
+#endif // _FLUID_FL_WINDOW_TYPE_H
diff --git a/fluid/Fluid_Image.cxx b/fluid/Fluid_Image.cxx
index 1057f171d..f1f5832b1 100644
--- a/fluid/Fluid_Image.cxx
+++ b/fluid/Fluid_Image.cxx
@@ -14,22 +14,28 @@
// https://www.fltk.org/bugs.php
//
+#include "Fluid_Image.h"
+
+#include "fluid.h"
+#include "Fl_Group_Type.h"
+#include "Fl_Window_Type.h"
+#include "file.h"
+#include "code.h"
+
#include <FL/Fl.H>
#include <FL/Fl_Widget.H>
+#include <FL/Fl_Window.H>
#include <FL/filename.H>
#include <FL/fl_string.h>
#include <FL/fl_utf8.h> // fl_fopen()
-#include "Fl_Type.h"
-#include "Fluid_Image.h"
+#include <FL/Fl_File_Chooser.H>
#include "../src/flstring.h"
+
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
-extern void goto_source_dir(); // in fluid.cxx
-extern void leave_source_dir(); // in fluid.cxx
-
void Fluid_Image::image(Fl_Widget *o) {
if (o->window() != o) o->image(img);
}
@@ -236,8 +242,6 @@ Fluid_Image::~Fluid_Image() {
////////////////////////////////////////////////////////////////
-#include <FL/Fl_File_Chooser.H>
-
const char *ui_find_image_name;
Fluid_Image *ui_find_image(const char *oldname) {
goto_source_dir();
diff --git a/fluid/Fluid_Image.h b/fluid/Fluid_Image.h
index 7020c14f6..99b06d218 100644
--- a/fluid/Fluid_Image.h
+++ b/fluid/Fluid_Image.h
@@ -19,10 +19,9 @@
//
#ifndef FLUID_IMAGE_H
-# define FLUID_IMAGE_H
-
-# include <FL/Fl_Shared_Image.H>
+#define FLUID_IMAGE_H
+#include <FL/Fl_Shared_Image.H>
class Fluid_Image {
const char *name_;
diff --git a/fluid/Makefile b/fluid/Makefile
index 3a9e0f888..c87c05719 100644
--- a/fluid/Makefile
+++ b/fluid/Makefile
@@ -35,8 +35,10 @@ CPPFILES = \
fluid.cxx \
function_panel.cxx \
pixmaps.cxx \
+ shell_command.cxx \
template_panel.cxx \
undo.cxx \
+ widget_browser.cxx \
widget_panel.cxx
# ExternalCodeEditor: platform specific files
diff --git a/fluid/Shortcut_Button.h b/fluid/Shortcut_Button.h
index 8726fa654..790415158 100644
--- a/fluid/Shortcut_Button.h
+++ b/fluid/Shortcut_Button.h
@@ -14,6 +14,9 @@
// https://www.fltk.org/bugs.php
//
+#ifndef _FLUID_SHORTCUT_BUTTON_H
+#define _FLUID_SHORTCUT_BUTTON_H
+
#include <FL/Fl_Button.H>
class Shortcut_Button : public Fl_Button {
@@ -24,3 +27,6 @@ public:
Shortcut_Button(int X,int Y,int W,int H, const char* l = 0) :
Fl_Button(X,Y,W,H,l) {svalue = 0;}
};
+
+#endif
+
diff --git a/fluid/StyleParse.cxx b/fluid/StyleParse.cxx
index 5d0dd5e5d..b8b8ff4f0 100644
--- a/fluid/StyleParse.cxx
+++ b/fluid/StyleParse.cxx
@@ -15,11 +15,12 @@
// https://www.fltk.org/bugs.php
//
+#include "StyleParse.h"
+
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h> // bsearch()
-#include "StyleParse.h"
// Sorted list of C/C++ keywords...
static const char * const code_keywords[] = {
diff --git a/fluid/about_panel.cxx b/fluid/about_panel.cxx
index 7dc5fadde..5a6e40e5b 100644
--- a/fluid/about_panel.cxx
+++ b/fluid/about_panel.cxx
@@ -1,7 +1,7 @@
//
// About dialog for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2021 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
diff --git a/fluid/about_panel.fl b/fluid/about_panel.fl
index a0a302349..74cedb06f 100644
--- a/fluid/about_panel.fl
+++ b/fluid/about_panel.fl
@@ -5,7 +5,7 @@ code_name {.cxx}
comment {//
// About dialog for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2021 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
@@ -36,8 +36,8 @@ Function {make_about_panel()} {open
}} {}
Fl_Window about_panel {
label {About FLUID} open
- xywh {340 190 345 180} type Double color 50 selection_color 47 hide hotspot
- code0 {\#include "../src/flstring.h"} non_modal
+ xywh {449 217 345 180} type Double color 50 selection_color 47 hotspot
+ code0 {\#include "../src/flstring.h"} non_modal visible
} {
Fl_Box {} {
image {icons/fluid-96.xpm} xywh {10 10 115 120}
@@ -53,7 +53,7 @@ Version x.x.x}
}
Fl_Box {} {
label {(Copyright)}
- comment {Label edited dynamically:} selected
+ comment {Label edited dynamically:}
xywh {135 90 200 45} align 148
code0 {o->label(cbuf);}
}
@@ -71,5 +71,5 @@ Version x.x.x}
}
data fluid_org_png {
- comment {Embedded image for internal fluid.html web page.} public local filename {../documentation/src/fluid-org.png}
+ comment {Embedded image for internal fluid.html web page.} selected public local filename {../documentation/src/fluid-org.png}
}
diff --git a/fluid/about_panel.h b/fluid/about_panel.h
index effa7ccb4..d7006c08b 100644
--- a/fluid/about_panel.h
+++ b/fluid/about_panel.h
@@ -1,7 +1,7 @@
//
// About dialog for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2021 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
diff --git a/fluid/align_widget.cxx b/fluid/align_widget.cxx
index 7a05b6129..f9bf2c02f 100644
--- a/fluid/align_widget.cxx
+++ b/fluid/align_widget.cxx
@@ -14,10 +14,14 @@
// https://www.fltk.org/bugs.php
//
+#include "align_widget.h"
+
+#include "fluid.h"
+#include "Fl_Group_Type.h"
+#include "undo.h"
+
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
-#include "Fl_Widget_Type.h"
-#include "undo.h"
/**
the first behaviour always uses the first selected widget as a reference
diff --git a/fluid/align_widget.h b/fluid/align_widget.h
new file mode 100644
index 000000000..541894e94
--- /dev/null
+++ b/fluid/align_widget.h
@@ -0,0 +1,25 @@
+//
+// FLUID main entry for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_ALIGN_WIDGET_H
+#define _FLUID_ALIGN_WIDGET_H
+
+class Fl_Widget;
+
+void align_widget_cb(Fl_Widget *, long);
+void widget_size_cb(Fl_Widget *, long);
+
+#endif // _FLUID_ALIGN_WIDGET_H
diff --git a/fluid/alignment_panel.fl b/fluid/alignment_panel.fl
index 20b09b575..9d0ed50a3 100644
--- a/fluid/alignment_panel.fl
+++ b/fluid/alignment_panel.fl
@@ -20,6 +20,12 @@ comment {//
} {in_source in_header
}
+decl {\#include "fluid.h"} {public global
+}
+
+decl {\#include "widget_browser.h"} {public global
+}
+
decl {\#include <FL/Fl_Text_Buffer.H>} {public local
}
@@ -38,37 +44,16 @@ decl {\#include <FL/fl_ask.H>} {private global
decl {\#include <string.h>} {private global
}
-decl {extern void load_history();} {public local
-}
-
-decl {extern void redraw_browser();} {public local
-}
-
-decl {extern int show_comments;} {public local
-}
-
-decl {extern int G_use_external_editor;} {public local
-}
-
-decl {extern char G_external_editor_command[512];} {public local
-}
-
-decl {extern int show_coredevmenus;} {public local
-}
-
decl {extern struct Fl_Menu_Item *dbmanager_item;} {public local
}
-decl {extern Fl_Preferences fluid_prefs;} {public local
-}
-
Function {make_project_window()} {open
} {
Fl_Window project_window {
- label {Project Settings} open
- xywh {396 475 399 252} type Double hide
+ label {Project Settings}
+ xywh {473 246 399 252} type Double
code0 {\#include <FL/Fl_Preferences.H>}
- code1 {\#include <FL/Fl_Tooltip.H>} modal
+ code1 {\#include <FL/Fl_Tooltip.H>} modal visible
} {
Fl_Button {} {
label Close
@@ -162,11 +147,12 @@ decl {extern void i18n_cb(Fl_Choice *,void *);} {public local
decl {void scheme_cb(Fl_Choice *, void *);} {public local
}
-Function {make_settings_window()} {} {
+Function {make_settings_window()} {open
+} {
Fl_Window settings_window {
- label {GUI Settings} open
- xywh {355 85 360 355} type Double hide resizable
- code0 {o->size_range(o->w(), o->h());} non_modal
+ label {GUI Settings}
+ xywh {442 538 360 355} type Double resizable
+ code0 {o->size_range(o->w(), o->h());} non_modal visible
} {
Fl_Choice scheme_choice {
label {Scheme: }
@@ -295,11 +281,11 @@ Examples:
}
}
-Function {make_shell_window()} {open
+Function {make_shell_window()} {open selected
} {
Fl_Window shell_window {
- label {Shell Command} open
- xywh {761 190 365 125} type Double hide
+ label {Shell Command}
+ xywh {873 248 365 125} type Double visible
} {
Fl_Input shell_command_input {
label {Command:}
@@ -345,8 +331,8 @@ Function {make_shell_window()} {open
}
}
Fl_Window shell_run_window {
- label {Shell Command Output} open
- xywh {454 363 555 430} type Double hide resizable
+ label {Shell Command Output}
+ xywh {887 409 555 430} type Double resizable visible
} {
Fl_Simple_Terminal shell_run_terminal {
xywh {10 10 535 375} resizable
@@ -364,10 +350,11 @@ shell_run_window->hide();}
}
}
-Function {make_layout_window()} {} {
+Function {make_layout_window()} {open
+} {
Fl_Window grid_window {
- label {Layout Settings} open
- xywh {812 369 310 245} type Double hide non_modal
+ label {Layout Settings}
+ xywh {545 376 310 245} type Double non_modal visible
} {
Fl_Input horizontal_input {
label x
@@ -558,7 +545,7 @@ Function {writePrefs()} {
}} {}
}
-Function {show_global_settings_window()} {open return_type void
+Function {show_global_settings_window()} {return_type void
} {
code {if (!global_settings_window)
make_global_settings_window();
@@ -749,7 +736,7 @@ Default is on.} xywh {245 366 100 25} down_box BORDER_BOX
} {
MenuItem {} {
label off
- user_data 0 user_data_type long selected
+ user_data 0 user_data_type long
xywh {30 30 31 20}
}
MenuItem {} {
@@ -781,7 +768,7 @@ Default is on.} xywh {245 442 100 25} down_box BORDER_BOX
} {
MenuItem {} {
label off
- user_data 0 user_data_type long selected
+ user_data 0 user_data_type long
xywh {30 30 31 20}
}
MenuItem {} {
diff --git a/fluid/alignment_panel.h b/fluid/alignment_panel.h
index e2a9bdc03..0457f4560 100644
--- a/fluid/alignment_panel.h
+++ b/fluid/alignment_panel.h
@@ -19,17 +19,12 @@
#ifndef alignment_panel_h
#define alignment_panel_h
#include <FL/Fl.H>
+#include "fluid.h"
+#include "widget_browser.h"
#include <FL/Fl_Text_Buffer.H>
#include <FL/Fl_Text_Display.H>
#include <FL/filename.H>
-extern void load_history();
-extern void redraw_browser();
-extern int show_comments;
-extern int G_use_external_editor;
-extern char G_external_editor_command[512];
-extern int show_coredevmenus;
extern struct Fl_Menu_Item *dbmanager_item;
-extern Fl_Preferences fluid_prefs;
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Preferences.H>
#include <FL/Fl_Tooltip.H>
diff --git a/fluid/code.cxx b/fluid/code.cxx
index 671cbb1a1..005a07d1c 100644
--- a/fluid/code.cxx
+++ b/fluid/code.cxx
@@ -14,28 +14,37 @@
// https://www.fltk.org/bugs.php
//
-#include <stdio.h>
-#include <stdlib.h>
-#include "../src/flstring.h"
-#include <stdarg.h>
+#include "code.h"
+
+#include "Fl_Group_Type.h"
+#include "Fl_Window_Type.h"
+#include "Fl_Function_Type.h"
+#include "alignment_panel.h"
+#include "file.h"
#include <FL/Fl.H>
#include <FL/fl_string.h>
-#include "Fl_Type.h"
-#include "alignment_panel.h"
+#include <FL/filename.H>
+#include "../src/flstring.h"
-static FILE *code_file;
-static FILE *header_file;
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/// \defgroup cfile C Code File Operations
+/// \{
-extern char i18n_program[];
-extern int i18n_type;
-extern const char* i18n_include;
-extern const char* i18n_function;
-extern const char* i18n_file;
-extern const char* i18n_set;
+static FILE *code_file = NULL;
+static FILE *header_file = NULL;
-// return true if c can be in a C identifier. I needed this so
-// it is not messed up by locale settings:
+int indentation = 0;
+int write_number = 0;
+int write_sourceview = 0;
+
+/**
+ Return true if c can be in a C identifier.
+ I needed this so it is not messed up by locale settings.
+ */
int is_id(char c) {
return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
}
@@ -59,6 +68,7 @@ id::~id() {
static id* id_root;
+// TODO: document me
const char* unique_id(void* o, const char* type, const char* name, const char* label) {
char buffer[128];
char* q = buffer;
@@ -93,9 +103,13 @@ const char* unique_id(void* o, const char* type, const char* name, const char* l
////////////////////////////////////////////////////////////////
// return current indentation:
-static const char* spaces = " ";
-int indentation;
+
+/**
+ Return a C string that indents code to the current depth.
+ */
const char* indent() {
+ static const char* spaces = " ";
+
int i = indentation; if (i>16) i = 16;
return spaces+16-i;
}
@@ -149,7 +163,9 @@ int write_declare(const char *format, ...) {
int varused_test;
int varused;
-// write an array of C characters (adds a null):
+/**
+ Write an array of C characters (adds a null).
+ */
void write_cstring(const char *s, int length) {
if (varused_test) {
varused = 1;
@@ -232,10 +248,14 @@ void write_cstring(const char *s, int length) {
putc('\"', code_file);
}
-// write a C string, quoting characters if necessary:
+/**
+ Write a C string, quoting characters if necessary.
+ */
void write_cstring(const char *s) {write_cstring(s, (int)strlen(s));}
-// write an array of C binary data (does not add a null):
+/**
+ Write an array of C binary data (does not add a null).
+ */
void write_cdata(const char *s, int length) {
if (varused_test) {
varused = 1;
@@ -269,6 +289,7 @@ void write_cdata(const char *s, int length) {
putc('}', code_file);
}
+// TODO: document me
void vwrite_c(const char* format, va_list args) {
if (varused_test) {
varused = 1;
@@ -277,6 +298,7 @@ void vwrite_c(const char* format, va_list args) {
vfprintf(code_file, format, args);
}
+// TODO: document me
void write_c(const char* format,...) {
va_list args;
va_start(args, format);
@@ -284,7 +306,9 @@ void write_c(const char* format,...) {
va_end(args);
}
-// write code (c) of size (n) to C file, with optional comment (com) w/o trailing space
+/**
+ Write code (c) of size (n) to C file, with optional comment (com) w/o trailing space.
+ */
void write_cc(const char *indent, int n, const char *c, const char *com) {
if (*com)
write_c("%s%.*s; %s\n", indent, n, c, com);
@@ -292,6 +316,7 @@ void write_cc(const char *indent, int n, const char *c, const char *com) {
write_c("%s%.*s;\n", indent, n, c);
}
+// TODO: document me
void write_h(const char* format,...) {
if (varused_test) return;
va_list args;
@@ -300,7 +325,9 @@ void write_h(const char* format,...) {
va_end(args);
}
-// write code (c) of size (n) to H file, with optional comment (com) w/o trailing space
+/**
+ Write code (c) of size (n) to H file, with optional comment (com) w/o trailing space.
+ */
void write_hc(const char *indent, int n, const char* c, const char *com) {
if (*com)
write_h("%s%.*s; %s\n", indent, n, c, com);
@@ -308,13 +335,10 @@ void write_hc(const char *indent, int n, const char* c, const char *com) {
write_h("%s%.*s;\n", indent, n, c);
}
-#include <FL/filename.H>
-int write_number;
-int write_sourceview;
-extern Fl_Widget_Class_Type *current_widget_class;
-// recursively dump code, putting children between the two parts
-// of the parent code:
+/**
+ Recursively dump code, putting children between the two parts of the parent code.
+ */
static Fl_Type* write_code(Fl_Type* p) {
if (write_sourceview) {
p->code_position = (int)ftell(code_file);
@@ -367,11 +391,8 @@ static Fl_Type* write_code(Fl_Type* p) {
return q;
}
-extern const char* header_file_name;
-extern Fl_Class_Type *current_class;
-
-
-/** \brief Write the source and header files for the current design.
+/**
+ Write the source and header files for the current design.
If the files already exist, they will be overwritten.
@@ -625,11 +646,22 @@ int write_strings(const char *sfile) {
return fclose(fp);
}
-////////////////////////////////////////////////////////////////
-
-void Fl_Type::write_static() {}
-void Fl_Type::write_code1() {
- write_h("// Header for %s\n", title());
- write_c("// Code for %s\n", title());
+/**
+ Write the public/private/protected keywords inside the class.
+ This avoids repeating these words if the mode is already set.
+ */
+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;
+ }
}
-void Fl_Type::write_code2() {}
+
+/// \}
+
diff --git a/fluid/code.h b/fluid/code.h
new file mode 100644
index 000000000..00c6c8855
--- /dev/null
+++ b/fluid/code.h
@@ -0,0 +1,44 @@
+//
+// Code output routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_CODE_H
+#define _FLUID_CODE_H
+
+#include <FL/fl_attr.h>
+
+#include <stdarg.h>
+
+extern int indentation;
+extern int write_number;
+extern int write_sourceview;
+
+int is_id(char c);
+const char* unique_id(void* o, const char*, const char*, const char*);
+extern const char* indent();
+int write_declare(const char *, ...) __fl_attr((__format__ (__printf__, 1, 2)));
+void write_cstring(const char *,int length);
+void write_cstring(const char *);
+void write_cdata(const char *,int length);
+void vwrite_c(const char* format, va_list args);
+void write_c(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2)));
+void write_cc(const char *, int, const char*, const char*);
+void write_h(const char*, ...) __fl_attr((__format__ (__printf__, 1, 2)));
+void write_hc(const char *, int, const char*, const char*);
+int write_code(const char *cfile, const char *hfile);
+int write_strings(const char *sfile);
+void write_public(int state); // writes pubic:/private: as needed
+
+#endif // _FLUID_CODE_H
diff --git a/fluid/factory.cxx b/fluid/factory.cxx
index 803411d3a..d1b1b664d 100644
--- a/fluid/factory.cxx
+++ b/fluid/factory.cxx
@@ -22,16 +22,20 @@
// https://www.fltk.org/bugs.php
//
+#include "factory.h"
+
+#include "fluid.h"
+#include "Fl_Window_Type.h"
+#include "undo.h"
+
#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl_Tree.H>
-#include <stdio.h>
#include "../src/flstring.h"
-#include "undo.h"
-#include "Fl_Widget_Type.h"
+#include <stdio.h>
extern Fl_Pixmap *pixmap[];
@@ -1116,7 +1120,6 @@ void fill_in_New_Menu() {
}
// use keyword to pick the type, this is used to parse files:
-int reading_file;
Fl_Type *Fl_Type_make(const char *tn) {
reading_file = 1; // makes labels be null
Fl_Type *r = 0;
diff --git a/fluid/factory.h b/fluid/factory.h
new file mode 100644
index 000000000..aaed57b20
--- /dev/null
+++ b/fluid/factory.h
@@ -0,0 +1,29 @@
+//
+// Widget type header file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_FACTORY_H
+#define _FLUID_FACTORY_H
+
+struct Fl_Menu_Item;
+class Fl_Type;
+
+extern Fl_Menu_Item New_Menu[];
+
+void fill_in_New_Menu();
+Fl_Type *Fl_Type_make(const char *tn);
+
+
+#endif // _FLUID_FACTORY_H
diff --git a/fluid/file.cxx b/fluid/file.cxx
index 30335a232..1e67ce4c8 100644
--- a/fluid/file.cxx
+++ b/fluid/file.cxx
@@ -19,21 +19,55 @@
// https://www.fltk.org/bugs.php
//
-#include <stdio.h>
-#include <stdlib.h>
-#include "../src/flstring.h"
-#include <stdarg.h>
+#include "file.h"
+
+#include "fluid.h"
+#include "factory.h"
+#include "Fl_Function_Type.h"
+#include "Fl_Widget_Type.h"
+#include "Fl_Window_Type.h"
#include "alignment_panel.h"
+#include "widget_browser.h"
+#include "code.h"
+
#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
#include <FL/fl_string.h>
-#include "Fl_Widget_Type.h"
+#include <FL/fl_message.H>
+#include "../src/flstring.h"
-////////////////////////////////////////////////////////////////
-// BASIC FILE WRITING:
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+/// \defgroup flfile .fl Design File Operations
+/// \{
+
+// This file contains code to read and write .fl file.
+// TODO: there is a name confusion with routines that write to the C and Header files which must be fixed.
static FILE *fout;
+static FILE *fin;
+
+static int needspace;
+static int lineno;
+static const char *fname;
+
+int fdesign_flip;
+int fdesign_magic;
+
+double read_version;
+
+////////////////////////////////////////////////////////////////
+// BASIC FILE WRITING:
-int open_write(const char *s) {
+/**
+ Open teh .fl design file for writing.
+ If the filename is NULL, associate stdout instead.
+ \param[in] s the filename or NULL for stdout
+ \return 1 if successful. 0 if the operation failed
+ */
+static int open_write(const char *s) {
if (!s) {fout = stdout; return 1;}
FILE *f = fl_fopen(s,"w");
if (!f) return 0;
@@ -41,7 +75,11 @@ int open_write(const char *s) {
return 1;
}
-int close_write() {
+/**
+ Close the .fl desing file.
+ Don't close, if data was sent to stdout.
+ */
+static int close_write() {
if (fout != stdout) {
int x = fclose(fout);
fout = stdout;
@@ -50,10 +88,9 @@ int close_write() {
return 1;
}
-static int needspace;
-int is_id(char); // in code.C
-
-// write a string, quoting characters if necessary:
+/**
+ Write a string to the .fl file, quoting characters if necessary.
+ */
void write_word(const char *w) {
if (needspace) putc(' ', fout);
needspace = 1;
@@ -86,9 +123,11 @@ void write_word(const char *w) {
putc('}', fout);
}
-// write an arbitrary formatted word, or a comment, etc.
-// if needspace is set, then one space is written before the string
-// unless the format starts with a newline character ('\n'):
+/**
+ Write an arbitrary formatted word to the .fl file, or a comment, etc. .
+ If needspace is set, then one space is written before the string
+ unless the format starts with a newline character '\\n'.
+ */
void write_string(const char *format, ...) {
va_list args;
va_start(args, format);
@@ -98,35 +137,43 @@ void write_string(const char *format, ...) {
needspace = !isspace(format[strlen(format)-1] & 255);
}
-// start a new line and indent it for a given nesting level:
+/**
+ Start a new line in the .fl file and indent it for a given nesting level.
+ */
void write_indent(int n) {
fputc('\n',fout);
while (n--) {fputc(' ',fout); fputc(' ',fout);}
needspace = 0;
}
-// write a '{' at the given indenting level:
+/**
+ Write a '{' to the .fl file at the given indenting level.
+ */
void write_open(int) {
if (needspace) fputc(' ',fout);
fputc('{',fout);
needspace = 0;
}
-// write a '}' at the given indenting level:
+/**
+ Write a '}' to the .fl file at the given indenting level.
+ */
void write_close(int n) {
if (needspace) write_indent(n);
fputc('}',fout);
needspace = 1;
}
+
////////////////////////////////////////////////////////////////
// BASIC FILE READING:
-static FILE *fin;
-static int lineno;
-static const char *fname;
-
-int open_read(const char *s) {
+/**
+ Open an .fl file for reading.
+ \param[in] s filename, if NULL, read from stdin instead
+ \return 0 if the operation failed, 1 if it succeeded
+ */
+static int open_read(const char *s) {
lineno = 1;
if (!s) {fin = stdin; fname = "stdin"; return 1;}
FILE *f = fl_fopen(s,"r");
@@ -136,7 +183,11 @@ int open_read(const char *s) {
return 1;
}
-int close_read() {
+/**
+ Close the .fl file.
+ \return 0 if the operation failed, 1 if it succeeded
+ */
+static int close_read() {
if (fin != stdin) {
int x = fclose(fin);
fin = 0;
@@ -145,8 +196,12 @@ int close_read() {
return 1;
}
-#include <FL/fl_message.H>
-
+/**
+ Display an error while reading the file.
+ If the .fl file isn't opened for reading, pop up an FLTK dialog, otherwise
+ print to stdout.
+ \note Matt: I am not sure why it is done this way. Shouldn;t this depend on \c batch_mode?
+ */
void read_error(const char *format, ...) {
va_list args;
va_start(args, format);
@@ -162,6 +217,9 @@ void read_error(const char *format, ...) {
va_end(args);
}
+/**
+ Convert a single ASCII char, assumed to be a hex digit, into its decimal value.
+ */
static int hexdigit(int x) {
if (isdigit(x)) return x-'0';
if (isupper(x)) return x-'A'+10;
@@ -169,7 +227,11 @@ static int hexdigit(int x) {
return 20;
}
-
+/**
+ Convert an ASCII sequence form the .fl file that starts with a \\ into a single character.
+ Conversion includes the common C style \\ characters like \\n, \x## hex
+ values, and \o### octal values.
+ */
static int read_quoted() { // read whatever character is after a \ .
int c,d,x;
switch(c = fgetc(fin)) {
@@ -203,16 +265,13 @@ static int read_quoted() { // read whatever character is after a \ .
return(c);
}
-// return a word read from the file, or NULL at the EOF:
-// This will skip all comments (# to end of line), and evaluate
-// all \xxx sequences and use \ at the end of line to remove the newline.
-// A word is any one of:
-// a continuous string of non-space chars except { and } and #
-// everything between matching {...} (unless wantbrace != 0)
-// the characters '{' and '}'
-
static char *buffer;
static int buflen;
+
+/**
+ A simple growing buffer.
+ Oh how I wish sometimes we would upgrade to moder C++.
+ */
static void expand_buffer(int length) {
if (length >= buflen) {
if (!buflen) {
@@ -226,6 +285,17 @@ static void expand_buffer(int length) {
}
}
+/**
+ Return a word read from the .fl file, or NULL at the EOF.
+
+ This will skip all comments (# to end of line), and evaluate
+ all \\xxx sequences and use \\ at the end of line to remove the newline.
+
+ A word is any one of:
+ - a continuous string of non-space chars except { and } and #
+ - everything between matching {...} (unless wantbrace != 0)
+ - the characters '{' and '}'
+ */
const char *read_word(int wantbrace) {
int x;
@@ -295,19 +365,12 @@ const char *read_word(int wantbrace) {
////////////////////////////////////////////////////////////////
-// global int variables:
-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 int header_file_set;
-extern int code_file_set;
-extern const char* header_file_name;
-extern const char* code_file_name;
-
+/**
+ Write an .fl design description file.
+ \param[in] filename create this file, and if it exists, overwrite it
+ \param[in] selected_only write only the selected nodes in the widget_tree. This
+ is used to implement copy and paste.
+ */
int write_file(const char *filename, int selected_only) {
if (!open_write(filename)) return 0;
write_string("# data file for the Fltk User Interface Designer (fluid)\n"
@@ -349,12 +412,9 @@ int write_file(const char *filename, int selected_only) {
////////////////////////////////////////////////////////////////
// read all the objects out of the input file:
-void read_fdesign();
-
-double read_version;
-
-extern Fl_Type *Fl_Type_make(const char *tn);
-
+/**
+ Read child node in the .fl design file.
+ */
static void read_children(Fl_Type *p, int paste) {
Fl_Type::current = p;
for (;;) {
@@ -491,8 +551,12 @@ static void read_children(Fl_Type *p, int paste) {
}
}
-extern void deselect();
-
+/**
+ Read a .fl design file.
+ \param[in] filename read this file
+ \param[in] merge if this is set, merge the file into an existing design
+ \return 0 if the operation failed, 1 if it succeeded
+ */
int read_file(const char *filename, int merge) {
Fl_Type *o;
read_version = 0.0;
@@ -512,8 +576,7 @@ int read_file(const char *filename, int merge) {
////////////////////////////////////////////////////////////////
// Read Forms and XForms fdesign files:
-int read_fdesign_line(const char*& name, const char*& value) {
-
+static int read_fdesign_line(const char*& name, const char*& value) {
int length = 0;
int x;
// find a colon:
@@ -550,10 +613,6 @@ int read_fdesign_line(const char*& name, const char*& value) {
return 1;
}
-int fdesign_flip;
-int fdesign_magic;
-#include <FL/Fl_Group.H>
-
static const char *class_matcher[] = {
"FL_CHECKBUTTON", "Fl_Check_Button",
"FL_ROUNDBUTTON", "Fl_Round_Button",
@@ -585,6 +644,13 @@ static const char *class_matcher[] = {
"24","Fl_Value_Slider",
0};
+/**
+ Read a XForms design file.
+ .fl and .fd file start with the same header. Fluid can recognize .fd XForms
+ Design files by a magic number. It will read them and map XForms widgets onto
+ FLTK widgets.
+ \see http://xforms-toolkit.org
+ */
void read_fdesign() {
fdesign_magic = atoi(read_word());
fdesign_flip = (fdesign_magic < 13000);
@@ -639,3 +705,6 @@ void read_fdesign() {
}
}
}
+
+/// \}
+
diff --git a/fluid/file.h b/fluid/file.h
new file mode 100644
index 000000000..18b96492e
--- /dev/null
+++ b/fluid/file.h
@@ -0,0 +1,40 @@
+//
+// Fluid file routines for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_FILE_H
+#define _FLUID_FILE_H
+
+#include <FL/fl_attr.h>
+
+extern double read_version;
+extern int fdesign_flip;
+extern int fdesign_magic;
+
+void write_word(const char *);
+void write_string(const char *,...) __fl_attr((__format__ (__printf__, 1, 2)));
+void write_indent(int n);
+void write_open(int);
+void write_close(int n);
+
+void read_error(const char *format, ...);
+const char *read_word(int wantbrace = 0);
+
+int write_file(const char *, int selected_only = 0);
+
+int read_file(const char *, int merge);
+void read_fdesign();
+
+#endif // _FLUID_FILE_H
diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx
index 700c81d63..0779e600d 100644
--- a/fluid/fluid.cxx
+++ b/fluid/fluid.cxx
@@ -14,56 +14,37 @@
// https://www.fltk.org/bugs.php
//
+#include "fluid.h"
+
+#include "Fl_Type.h"
+#include "Fl_Function_Type.h"
+#include "Fl_Group_Type.h"
+#include "Fl_Window_Type.h"
+#include "widget_browser.h"
+#include "shell_command.h"
+#include "factory.h"
+#include "pixmaps.h"
+#include "undo.h"
+#include "file.h"
+#include "code.h"
+
+#include "alignment_panel.h"
+#include "function_panel.h"
+#include "template_panel.h"
+#include "about_panel.h"
+
#include <FL/Fl.H>
#ifdef __APPLE__
#include <FL/platform.H> // for fl_open_callback
#endif
-#include <FL/Fl_Double_Window.H>
-#include <FL/Fl_Box.H>
-#include <FL/Fl_Button.H>
-#include <FL/Fl_File_Icon.H>
#include <FL/Fl_Help_Dialog.H>
-#include <FL/Fl_Hold_Browser.H>
#include <FL/Fl_Menu_Bar.H>
-#include <FL/Fl_Input.H>
-#include <FL/Fl_Plugin.H>
-#include <FL/fl_ask.H>
-#include <FL/fl_draw.H>
-#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_PNG_Image.H>
-#include <FL/fl_message.H>
-#include <FL/filename.H>
#include <FL/Fl_Native_File_Chooser.H>
#include <FL/Fl_Printer.H>
-#include <FL/fl_utf8.h>
#include <FL/fl_string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
#include <locale.h> // setlocale()..
-#include <time.h> // time(), localtime(), etc.
-
#include "../src/flstring.h"
-#include "alignment_panel.h"
-#include "function_panel.h"
-#include "template_panel.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-# include <direct.h>
-# include <windows.h>
-# include <io.h>
-# include <fcntl.h>
-# include <commdlg.h>
-# include <FL/platform.H>
-#else
-# include <unistd.h>
-#endif
-
-#include "pixmaps.h"
-#include "about_panel.h"
-#include "undo.h"
-
-#include "Fl_Type.h"
extern "C"
{
@@ -77,46 +58,160 @@ extern "C"
#endif // HAVE_LIBPNG && HAVE_LIBZ
}
+/// \defgroup globals Fluid Global Variables, Functions and Calbacks
+/// \{
+
//
// Globals..
//
+
+/// Fluid-wide help dialog.
static Fl_Help_Dialog *help_dialog = 0;
+Fl_Menu_Bar *main_menubar = NULL;
+Fl_Window *main_window;
+
+/// Fluid application preferences, allways accessible, will be flushed when app closes.
Fl_Preferences fluid_prefs(Fl_Preferences::USER, "fltk.org", "fluid");
+
+/// Align widget position and size when designing, saved in app preferences and project file.
int gridx = 5;
+
+/// Align widget position and size when designing, saved in app preferences and project file.
int gridy = 5;
+
+/// Activate snapping to grid, saved in app preferences and project file.
int snap = 1;
+
+/// Show guides in the design window when positioning widgets, saved in app preferences.
int show_guides = 1;
+
+/// Show widget comments in the browser, saved in app preferences.
int show_comments = 1;
+
+/// Use external editor for editing Fl_Code_Type, saved in app preferences.
int G_use_external_editor = 0;
+
+/// Debugging help for external Fl_Code_Type editor.
int G_debug = 0;
+
+/// Run this command to load an Fl_Code_Type into an external editor, save in app preferences.
char G_external_editor_command[512];
-int show_coredevmenus = 1;
+
+
+/// \todo Functionality unclear.
+int force_parent = 0;
+
+/// This is set to create different labels when creating new widgets.
+/// \todo Details unclear.
+int reading_file = 0;
+
// File history info...
+
+/// Stores the absolute filename of the last 10 design files, saved in app preferences.
char absolute_history[10][FL_PATH_MAX];
+
+/// This list of filenames is computed from \c absolute_history and displayed in the main menu.
char relative_history[10][FL_PATH_MAX];
-void load_history();
-void update_history(const char *);
+/// Menuitem to save a .fl design file, will be deactivated if the design is unchanged.
+Fl_Menu_Item *save_item = NULL;
-// Shell command support...
-void show_shell_window();
+/// First Menuitem that shows the .fl design file hisory.
+Fl_Menu_Item *history_item = NULL;
-Fl_Menu_Item *save_item = 0L;
-Fl_Menu_Item *history_item = 0L;
-Fl_Menu_Item *widgetbin_item = 0L;
-Fl_Menu_Item *sourceview_item = 0L;
+/// Menuitem to show or hide the widget bin, label will change if bin is visible.
+Fl_Menu_Item *widgetbin_item = NULL;
+
+/// Menuitem to show or hide the source view, label will change if view is visible.
+Fl_Menu_Item *sourceview_item = NULL;
////////////////////////////////////////////////////////////////
-static const char *filename;
-void set_filename(const char *c);
-void set_modflag(int mf);
-int modflag;
+/// Filename of the current .fl design file
+static const char *filename = NULL;
+
+/// Set if the current design has been modified compared to the associated .fl design file.
+int modflag = 0;
+
+/// Application work directory, stored here when temporarily changing to the source code directory.
+/// \see goto_source_dir()
+static char* pwd = NULL;
+
+/// Set, if the current working directory is in the source code folder vs. the app working space.
+/// \see goto_source_dir()
+static char in_source_dir = 0;
+
+/// Set, if Fluid was started with the command line argument -u
+int update_file = 0; // fluid -u
+
+/// Set, if Fluid was started with the command line argument -c
+int compile_file = 0; // fluid -c
+
+/// Set, if Fluid was started with the command line argument -cs
+int compile_strings = 0; // fluic -cs
+
+/// Set, if Fluid runs in batch mode, and no user interface is activated.
+int batch_mode = 0; // if set (-c, -u) don't open display
+
+/// If set, commandline overrides header file name in .fl file.
+int header_file_set = 0;
+
+/// If set, commandline overrides source code file name in .fl file.
+int code_file_set = 0;
+
+/// Hold the default extension for header files, or the entire filename if set via command line.
+const char* header_file_name = ".h";
+
+/// Hold the default extension for source code files, or the entire filename if set via command line.
+const char* code_file_name = ".cxx";
+
+
+/// Saved in the .fl design file.
+/// \todo document me
+int i18n_type = 0;
+
+/// Saved in the .fl design file.
+/// \todo document me
+const char* i18n_include = "";
+
+/// Saved in the .fl design file.
+/// \todo document me
+const char* i18n_function = "";
+
+/// Saved in the .fl design file.
+/// \todo document me
+const char* i18n_file = "";
+
+/// Saved in the .fl design file.
+/// \todo document me
+const char* i18n_set = "";
+
+/// \todo document me
+char i18n_program[FL_PATH_MAX] = "";
+
+/// \todo document me
+int pasteoffset = 0;
+
+/// \todo document me
+static int ipasteoffset = 0;
-static char* pwd;
-static char in_source_dir;
+
+// ---- Sourceview definition
+
+void update_sourceview_position();
+void update_sourceview_position_cb(Fl_Tabs*, void*);
+void update_sourceview_cb(Fl_Button*, void*);
+void update_sourceview_timer(void*);
+
+// ----
+
+/**
+ Change the current working directory to the source code folder.
+ Remember the the previous directory, so \c leave_source_dir() can return there.
+ \see leave_source_dir(), pwd, in_source_dir
+ */
void goto_source_dir() {
if (in_source_dir) return;
if (!filename || !*filename) return;
@@ -136,6 +231,10 @@ void goto_source_dir() {
in_source_dir = 1;
}
+/**
+ Change the current working directory to its previous directory.
+ \see goto_source_dir(), pwd, in_source_dir
+ */
void leave_source_dir() {
if (!in_source_dir) return;
if (fl_chdir(pwd) < 0) {
@@ -144,6 +243,17 @@ void leave_source_dir() {
in_source_dir = 0;
}
+/**
+ Position the given window window based on entries in the app preferences.
+ Customizable by user; feature can be switched off.
+ The window is not shown or hidden by this function, but a value is returned
+ to indicate the state to the caller.
+ \param[in] w position this window
+ \param[in] prefsName name of the preferences item that stores the window settings
+ \param[in] Visible default value if window is hidden or shown
+ \param[in] X, Y, W, H default size and position if nothing is specified in the preferences
+ \return 1 if the caller should make the window visible, 0 if hidden.
+ */
char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0 ) {
Fl_Preferences pos(fluid_prefs, prefsName);
if (prevpos_button->value()) {
@@ -161,6 +271,11 @@ char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, in
return Visible;
}
+/**
+ Save the position and visibility state of a window to the app preferences.
+ \param[in] w save this window data
+ \param[in] prefsName name of the preferences item that stores the window settings
+ */
void save_position(Fl_Window *w, const char *prefsName) {
Fl_Preferences pos(fluid_prefs, prefsName);
pos.set("x", w->x());
@@ -170,9 +285,11 @@ void save_position(Fl_Window *w, const char *prefsName) {
pos.set("visible", (int)(w->shown() && w->visible()));
}
-Fl_Window *main_window;
-Fl_Menu_Bar *main_menubar;
-
+/**
+ Return the path and filename of a temporary file for cut or duplicated data.
+ \param[in] which 0 gets the cut/copy/paste buffer, 1 gets the duplication buffer
+ \return a pointer to a string in a static buffer
+ */
static char* cutfname(int which = 0) {
static char name[2][FL_PATH_MAX];
static char beenhere = 0;
@@ -188,10 +305,13 @@ static char* cutfname(int which = 0) {
return name[which];
}
-// Timer to watch for external editor modifications
-// If one or more external editors open, check if their files were modified.
-// If so: reload to ram, update size/mtime records, and change fluid's 'modified' state.
-//
+/**
+ Timer to watch for external editor modifications.
+
+ If one or more external editors open, check if their files were modified.
+ If so: reload to ram, update size/mtime records, and change fluid's
+ 'modified' state.
+ */
static void external_editor_timer(void*) {
int editors_open = ExternalCodeEditor::editors_open();
if ( G_debug ) printf("--- TIMER --- External editors open=%d\n", editors_open);
@@ -223,6 +343,12 @@ static void external_editor_timer(void*) {
}
}
+/**
+ Save the current design to the file given by \c filename.
+ If automatic, this overwrites an existing file. If iinteractive, if will
+ verify with the user.
+ \param[in] v if v is not NULL, or no filename is set, open a filechooser.
+ */
void save_cb(Fl_Widget *, void *v) {
Fl_Native_File_Chooser fnfc;
const char *c = filename;
@@ -261,6 +387,10 @@ void save_cb(Fl_Widget *, void *v) {
}
}
+/**
+ Save a design template.
+ \todo We should document the concept of templates.
+ */
void save_template_cb(Fl_Widget *, void *) {
// Setup the template panel...
if (!template_panel) make_template_panel();
@@ -367,6 +497,10 @@ void save_template_cb(Fl_Widget *, void *) {
#endif // HAVE_LIBPNG && HAVE_LIBZ
}
+/**
+ Reload the file set by \c filename, replacing the current design.
+ If the design was modified, a dialog will ask for confirmation.
+ */
void revert_cb(Fl_Widget *,void *) {
if (modflag) {
if (!fl_choice("This user interface has been changed. Really revert?",
@@ -383,6 +517,10 @@ void revert_cb(Fl_Widget *,void *) {
undo_clear();
}
+/**
+ Exit Fluid; we hope you had a nice experience.
+ If the design was modified, a dialog will ask for confirmation.
+ */
void exit_cb(Fl_Widget *,void *) {
// Stop any external editor update timers
@@ -433,8 +571,12 @@ void exit_cb(Fl_Widget *,void *) {
#ifdef __APPLE__
-void
-apple_open_cb(const char *c) {
+/**
+ Handle app launch with an associated filename (macOS only).
+ Should there be a modified design already, Fluid asks for user confirmation.
+ \param[in] c the filename of the new design
+ */
+void apple_open_cb(const char *c) {
if (modflag) {
switch (fl_choice("Do you want to save changes to this user\n"
"interface before opening another one?", "Don't Save",
@@ -469,6 +611,11 @@ apple_open_cb(const char *c) {
}
#endif // __APPLE__
+/**
+ Open a file chooser and load a new file.
+ If the current design was modified, Fluid will ask for user confirmation.
+ \param[in] v if v is set, Fluid will not ask for confirmation.
+ */
void open_cb(Fl_Widget *, void *v) {
if (!v && modflag) {
switch (fl_choice("Do you want to save changes to this user\n"
@@ -517,6 +664,11 @@ void open_cb(Fl_Widget *, void *v) {
}
}
+/**
+ Open a file from history.
+ If the current design was modified, Fluid will ask for user confirmation.
+ \param[in] v points to the absolute path and filename.
+ */
void open_history_cb(Fl_Widget *, void *v) {
if (modflag) {
switch (fl_choice("Do you want to save changes to this user\n"
@@ -552,6 +704,11 @@ void open_history_cb(Fl_Widget *, void *v) {
}
}
+/**
+ Close the current design and create a new, empty one.
+ If the current design was modified, Fluid will ask for user confirmation.
+ \param[in] v if v is set, don't ask for confirmation
+ */
void new_cb(Fl_Widget *, void *v) {
// Check if the current file has been modified...
if (!v && modflag) {
@@ -573,6 +730,12 @@ void new_cb(Fl_Widget *, void *v) {
set_filename(NULL);
}
+/**
+ Open the template browser and load a new file from templates.
+ If the current design was modified, Fluid will ask for user confirmation.
+ \param[in] w widget that caused this request, unused
+ \param[in] v if v is set, don't ask for confirmation
+ */
void new_from_template_cb(Fl_Widget *w, void *v) {
new_cb(w, v);
@@ -668,26 +831,11 @@ void new_from_template_cb(Fl_Widget *w, void *v) {
undo_clear();
}
-int exit_early = 0;
-int update_file = 0; // fluid -u
-int compile_file = 0; // fluid -c
-int compile_strings = 0; // fluic -cs
-int batch_mode = 0; // if set (-c, -u) don't open display
-int header_file_set = 0;
-int code_file_set = 0;
-const char* header_file_name = ".h";
-const char* code_file_name = ".cxx";
-int i18n_type = 0;
-const char* i18n_include = "";
-const char* i18n_function = "";
-const char* i18n_file = "";
-const char* i18n_set = "";
-char i18n_program[FL_PATH_MAX] = "";
-
-/** \brief Generate the C++ source and header filenames and write those files.
+/**
+ Generate the C++ source and header filenames and write those files.
This function creates the source filename by setting the file
- extension to \c code_file_name and a header filename
+ extension to \c code_file_name and a header filename
with the extension \c code_file_name which are both
settable by the user.
@@ -737,10 +885,16 @@ int write_code_files() {
return 0;
}
+/**
+ Callback to write C++ code and header files.
+ */
void write_cb(Fl_Widget *, void *) {
write_code_files();
}
+/**
+ Write the strings that are used in i18n.
+ */
void write_strings_cb(Fl_Widget *, void *) {
static const char *exts[] = { ".txt", ".po", ".msg" };
if (!filename) {
@@ -764,6 +918,9 @@ void write_strings_cb(Fl_Widget *, void *) {
}
}
+/**
+ Show the editor for the \c current Fl_Type.
+ */
void openwidget_cb(Fl_Widget *, void *) {
if (!Fl_Type::current) {
fl_message("Please select a widget");
@@ -772,18 +929,9 @@ void openwidget_cb(Fl_Widget *, void *) {
Fl_Type::current->open();
}
-void toggle_overlays(Fl_Widget *,void *);
-
-void select_all_cb(Fl_Widget *,void *);
-void select_none_cb(Fl_Widget *,void *);
-
-void group_cb(Fl_Widget *, void *);
-
-void ungroup_cb(Fl_Widget *, void *);
-
-extern int pasteoffset;
-static int ipasteoffset;
-
+/**
+ User chose to copy the currently selected widgets.
+ */
void copy_cb(Fl_Widget*, void*) {
if (!Fl_Type::current) {
fl_beep();
@@ -796,7 +944,9 @@ void copy_cb(Fl_Widget*, void*) {
}
}
-extern void select_only(Fl_Type *);
+/**
+ User chose to cut the currently selected widgets.
+ */
void cut_cb(Fl_Widget *, void *) {
if (!Fl_Type::current) {
fl_beep();
@@ -813,8 +963,12 @@ void cut_cb(Fl_Widget *, void *) {
while (p && p->selected) p = p->parent;
delete_all(1);
if (p) select_only(p);
+ //widget_browser->redraw_lines();
}
+/**
+ User chose to delete the currently selected widgets.
+ */
void delete_cb(Fl_Widget *, void *) {
if (!Fl_Type::current) {
fl_beep();
@@ -829,8 +983,9 @@ void delete_cb(Fl_Widget *, void *) {
if (p) select_only(p);
}
-extern int force_parent;
-
+/**
+ User chose to paste the widgets from the cut buffer.
+ */
void paste_cb(Fl_Widget*, void*) {
//if (ipasteoffset) force_parent = 1;
pasteoffset = ipasteoffset;
@@ -847,7 +1002,9 @@ void paste_cb(Fl_Widget*, void*) {
force_parent = 0;
}
-// Duplicate the selected widgets...
+/**
+ Duplicate the selected widgets.
+ */
void duplicate_cb(Fl_Widget*, void*) {
if (!Fl_Type::current) {
fl_beep();
@@ -873,29 +1030,25 @@ void duplicate_cb(Fl_Widget*, void*) {
force_parent = 0;
}
-void earlier_cb(Fl_Widget*,void*);
-
-void later_cb(Fl_Widget*,void*);
-
-Fl_Type *sort(Fl_Type *parent);
-
+/**
+ User wants to sort selected widgets by y coordinate.
+ */
static void sort_cb(Fl_Widget *,void *) {
- sort((Fl_Type*)0);
+ sort((Fl_Type*)NULL);
}
-void show_project_cb(Fl_Widget *, void *);
-void show_grid_cb(Fl_Widget *, void *);
-void show_settings_cb(Fl_Widget *, void *);
-void show_global_settings_cb(Fl_Widget *, void *);
-
-void align_widget_cb(Fl_Widget *, long);
-void widget_size_cb(Fl_Widget *, long);
-
+/**
+ Open the "About" dialog.
+ */
void about_cb(Fl_Widget *, void *) {
if (!about_panel) make_about_panel();
about_panel->show();
}
+/**
+ Open a dialog to show the HTML help page form the FLTK documentation folder.
+ \param[in] name name of the HTML help file.
+ */
void show_help(const char *name) {
const char *docdir;
char helpname[FL_PATH_MAX];
@@ -960,16 +1113,25 @@ void show_help(const char *name) {
help_dialog->show();
}
+/**
+ User wants help on Fluid.
+ */
void help_cb(Fl_Widget *, void *) {
show_help("fluid.html");
}
+/**
+ User wants to see the Fluid manual.
+ */
void manual_cb(Fl_Widget *, void *) {
show_help("index.html");
}
+// ---- Printing
-////////////////////////////////////////////////////////////////
+/**
+ Open the dialog to allow the user to print the current window.
+ */
void print_menu_cb(Fl_Widget *, void *) {
int w, h, ww, hh;
int frompage, topage;
@@ -1036,13 +1198,23 @@ void print_menu_cb(Fl_Widget *, void *) {
printjob.end_job();
}
-////////////////////////////////////////////////////////////////
+// ---- Main menu bar
+
+/**
+ This is the main Fluid menu.
-extern Fl_Menu_Item New_Menu[];
+ Design history is manipulated right inside this menu structure.
+ Some menuitem change or deactivate correctly, but most items just trigger
+ various callbacks.
-void toggle_widgetbin_cb(Fl_Widget *, void *);
-void toggle_sourceview_cb(Fl_Double_Window *, void *);
+ \c New_Menu creates new widgets and is explained in detail in another location.
+ \see New_Menu
+ \todo This menu need some major modernisation. Menus are too long and their
+ sorting is not always obvious.
+ \todo Shortcuts are all over the palce (Alt, Ctrl, Command, Shift-Ctrl,
+ function keys), and there should be a help page listing all shortcuts.
+ */
Fl_Menu_Item Main_Menu[] = {
{"&File",0,0,0,FL_SUBMENU},
{"&New", FL_COMMAND+'n', new_cb, 0},
@@ -1136,14 +1308,10 @@ Fl_Menu_Item Main_Menu[] = {
{0},
{0}};
-#define BROWSERWIDTH 300
-#define BROWSERHEIGHT 500
-#define WINWIDTH 300
-#define MENUHEIGHT 25
-#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT)
-
-extern void fill_in_New_Menu();
-
+/**
+ Change the app's and hence preview the design's scheme.
+ The scheme setting is stored inthe app preferences.
+ */
void scheme_cb(Fl_Choice *, void *) {
if (batch_mode)
return;
@@ -1169,6 +1337,10 @@ void scheme_cb(Fl_Choice *, void *) {
fluid_prefs.set("scheme", scheme_choice->value());
}
+/**
+ Show or hide the widget bin.
+ The state is stored in the app preferences.
+ */
void toggle_widgetbin_cb(Fl_Widget *, void *) {
if (!widgetbin_panel) {
make_widgetbin();
@@ -1184,7 +1356,10 @@ void toggle_widgetbin_cb(Fl_Widget *, void *) {
}
}
-
+/**
+ Show or hide the source code preview.
+ The state is stored in the app preferences.
+ */
void toggle_sourceview_cb(Fl_Double_Window *, void *) {
if (!sourceview_panel) {
make_sourceview();
@@ -1212,10 +1387,17 @@ void toggle_sourceview_cb(Fl_Double_Window *, void *) {
}
}
+/**
+ Show or hide the source code preview, called from a button.
+ The state is stored in the app preferences.
+ */
void toggle_sourceview_b_cb(Fl_Button*, void *) {
toggle_sourceview_cb(0,0);
}
+/**
+ Build the main app window and create a few other dialogs.
+ */
void make_main_window() {
if (!batch_mode) {
fluid_prefs.get("snap", snap, 1);
@@ -1256,7 +1438,13 @@ void make_main_window() {
}
}
-// Load file history from preferences...
+/**
+ Load file history from preferences.
+
+ This loads the absolute filepaths of the last 10 used design files.
+ It also computes and stores the relative filepaths for display in
+ the main menu.
+ */
void load_history() {
int i; // Looping var
int max_files;
@@ -1283,7 +1471,15 @@ void load_history() {
}
}
-// Update file history from preferences...
+/**
+ Update file history from preferences.
+
+ Add this new filepath to the history and update the main menu.
+ Writes the new file history to the app preferences.
+
+ \param[in] flname path or filename of .fl file, will be converted into an
+ absolute file path based on the current working directory.
+ */
void update_history(const char *flname) {
int i; // Looping var
char absolute[FL_PATH_MAX];
@@ -1335,243 +1531,72 @@ void update_history(const char *flname) {
fluid_prefs.flush();
}
-// ********** portable process class definition **********
-
-class Fl_Process {
-public:
- // construction / destruction
- Fl_Process() {_fpt= NULL;}
- ~Fl_Process() {if (_fpt) close();}
-
- // FIXME: popen needs the UTF-8 equivalent fl_popen
- FILE * popen (const char *cmd, const char *mode="r");
- //not necessary here: FILE * fl_fopen (const char *file, const char *mode="r");
- int close();
-
- FILE * desc() const { return _fpt;} // non-null if file is open
- char * get_line(char * line, size_t s) const {return _fpt ? fgets(line, (int)s, _fpt) : NULL;}
-
- // returns fileno(FILE*):
- // (file must be open, i.e. _fpt must be non-null)
- // *FIXME* we should find a better solution for the 'fileno' issue
- int get_fileno() const {
-#ifdef _MSC_VER
- return _fileno(_fpt); // suppress MSVC warning
-#else
- return fileno(_fpt);
-#endif
- } // non null if file is open
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-protected:
- HANDLE pin[2], pout[2], perr[2];
- char ptmode;
- PROCESS_INFORMATION pi;
- STARTUPINFO si;
-
- static bool createPipe(HANDLE * h, BOOL bInheritHnd=TRUE);
-
-private:
- FILE * freeHandles() {
- clean_close(pin[0]); clean_close(pin[1]);
- clean_close(pout[0]); clean_close(pout[1]);
- clean_close(perr[0]); clean_close(perr[1]);
- return NULL; // convenient for error management
- }
- static void clean_close(HANDLE& h);
-#endif
-
-protected:
- FILE * _fpt;
-};
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-bool Fl_Process::createPipe(HANDLE * h, BOOL bInheritHnd) {
- SECURITY_ATTRIBUTES sa;
- sa.nLength = sizeof(sa);
- sa.lpSecurityDescriptor = NULL;
- sa.bInheritHandle = bInheritHnd;
- return CreatePipe (&h[0],&h[1],&sa,0) ? true : false;
-}
-#endif
-// portable open process:
-FILE * Fl_Process::popen(const char *cmd, const char *mode) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
- // PRECONDITIONS
- if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return NULL;
- if (_fpt) close(); // close first before reuse
-
- ptmode = *mode;
- pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE;
- // stderr to stdout wanted ?
- int fusion = (strstr(cmd,"2>&1") !=NULL);
-
- // Create windows pipes
- if (!createPipe(pin) || !createPipe(pout) || (!fusion && !createPipe(perr) ) )
- return freeHandles(); // error
-
- // Initialize Startup Info
- ZeroMemory(&si, sizeof(STARTUPINFO));
- si.cb = sizeof(STARTUPINFO);
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = pin[0];
- si.hStdOutput = pout[1];
- si.hStdError = fusion ? pout[1] : perr [1];
-
- if ( CreateProcess(NULL, (LPTSTR) cmd,NULL,NULL,TRUE,
- DETACHED_PROCESS,NULL,NULL, &si, &pi)) {
- // don't need theses handles inherited by child process:
- clean_close(pin[0]); clean_close(pout[1]); clean_close(perr[1]);
- HANDLE & h = *mode == 'r' ? pout[0] : pin[1];
- _fpt = _fdopen(_open_osfhandle((fl_intptr_t) h,_O_BINARY),mode);
- h= INVALID_HANDLE_VALUE; // reset the handle pointer that is shared
- // with _fpt so we don't free it twice
- }
-
- if (!_fpt) freeHandles();
- return _fpt;
-#else
- _fpt=::popen(cmd,mode);
- return _fpt;
-#endif
-}
-
-int Fl_Process::close() {
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (_fpt) {
- fclose(_fpt);
- clean_close(perr[0]);
- clean_close(pin[1]);
- clean_close(pout[0]);
- _fpt = NULL;
- return 0;
- }
- return -1;
-#else
- int ret = ::pclose(_fpt);
- _fpt=NULL;
- return ret;
-#endif
-}
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-void Fl_Process::clean_close(HANDLE& h) {
- if (h!= INVALID_HANDLE_VALUE) CloseHandle(h);
- h = INVALID_HANDLE_VALUE;
-}
-#endif
-// ********** Fl_Process class end **********
-
-static Fl_Process s_proc;
-
-// Shell command support...
-
-static bool prepare_shell_command(const char * &command) { // common pre-shell command code all platforms
- shell_window->hide();
- if (s_proc.desc()) {
- fl_alert("Previous shell command still running!");
- return false;
- }
- if ((command = shell_command_input->value()) == NULL || !*command) {
- fl_alert("No shell command entered!");
- return false;
- }
- if (shell_savefl_button->value()) {
- save_cb(0, 0);
- }
- if (shell_writecode_button->value()) {
- write_code_files();
- }
- if (shell_writemsgs_button->value()) {
- write_strings_cb(0, 0);
- }
- return true;
-}
+/**
+ Set the filename of the current .fl design.
+ \param[in] c the new absolute filename and path
+ */
+void set_filename(const char *c) {
+ if (filename) free((void *)filename);
+ filename = c ? fl_strdup(c) : NULL;
-// Support the full piped shell command...
-void
-shell_pipe_cb(FL_SOCKET, void*) {
- char line[1024]=""; // Line from command output...
+ if (filename && !batch_mode)
+ update_history(filename);
- if (s_proc.get_line(line, sizeof(line)) != NULL) {
- // Add the line to the output list...
- shell_run_terminal->append(line);
- } else {
- // End of file; tell the parent...
- Fl::remove_fd(s_proc.get_fileno());
- s_proc.close();
- shell_run_terminal->append("... END SHELL COMMAND ...\n");
- }
+ set_modflag(modflag);
}
-void
-do_shell_command(Fl_Return_Button*, void*) {
- const char *command=NULL; // Command to run
+/**
+ Set the "modified" flag and update the title of the main window.
+ \param[in] mf 0 to clear the modflag, 1 to mark the design "modified"
+ */
+void set_modflag(int mf) {
+ const char *basename;
+ static char title[FL_PATH_MAX];
- if (!prepare_shell_command(command)) return;
+ modflag = mf;
- // Show the output window and clear things...
- shell_run_terminal->text("");
- shell_run_terminal->append(command);
- shell_run_terminal->append("\n");
- shell_run_window->label("Shell Command Running...");
+ if (main_window) {
+ if (!filename) basename = "Untitled.fl";
+ else if ((basename = strrchr(filename, '/')) != NULL) basename ++;
+#if defined(_WIN32)
+ else if ((basename = strrchr(filename, '\\')) != NULL) basename ++;
+#endif // _WIN32
+ else basename = filename;
- if (s_proc.popen((char *)command) == NULL) {
- fl_alert("Unable to run shell command: %s", strerror(errno));
- return;
+ if (modflag) {
+ snprintf(title, sizeof(title), "%s (modified)", basename);
+ main_window->label(title);
+ } else main_window->label(basename);
}
-
- shell_run_button->deactivate();
-
- Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos");
- int x, y, w, h;
- pos.get("x", x, -1);
- pos.get("y", y, 0);
- pos.get("w", w, 640);
- pos.get("h", h, 480);
- if (x!=-1) {
- shell_run_window->resize(x, y, w, h);
+ // if the UI was modified in any way, update the Source View panel
+ if (sourceview_panel && sourceview_panel->visible() && sv_autorefresh->value())
+ {
+ // we will only update earliest 0.5 seconds after the last change, and only
+ // if no other change was made, so dragging a widget will not generate any
+ // CPU load
+ Fl::remove_timeout(update_sourceview_timer, 0);
+ Fl::add_timeout(0.5, update_sourceview_timer, 0);
}
- shell_run_window->show();
- Fl::add_fd(s_proc.get_fileno(), shell_pipe_cb);
-
- while (s_proc.desc()) Fl::wait();
-
- shell_run_button->activate();
- shell_run_window->label("Shell Command Complete");
- fl_beep();
-
- while (shell_run_window->shown()) Fl::wait();
+ // Enable/disable the Save menu item...
+ if (modflag) save_item->activate();
+ else save_item->deactivate();
}
-void
-show_shell_window() {
- shell_window->hotspot(shell_command_input);
- shell_window->show();
-}
+// ---- Sourceview implementation
-void set_filename(const char *c) {
- if (filename) free((void *)filename);
- filename = c ? fl_strdup(c) : NULL;
+static char *sv_source_filename = NULL;
+static char *sv_header_filename = NULL;
- if (filename && !batch_mode)
- update_history(filename);
-
- set_modflag(modflag);
-}
+/**
+ Update the header and source code highlighting depending on the
+ currently selected object
-//
-// The Source View system offers an immediate preview of the code
-// files that will be generated by FLUID. It also marks the code
-// generated for the last selected item in the header and the source
-// file.
-//
-
-//
-// Update the header and source code highlighting depending on the
-// currently selected object
-//
+ The Source View system offers an immediate preview of the code
+ files that will be generated by FLUID. It also marks the code
+ generated for the last selected item in the header and the source
+ file.
+ */
void update_sourceview_position()
{
if (!sourceview_panel || !sourceview_panel->visible())
@@ -1605,18 +1630,18 @@ void update_sourceview_position()
}
}
+/**
+ Callback to update the sourceview position.
+ */
void update_sourceview_position_cb(Fl_Tabs*, void*)
{
update_sourceview_position();
}
-static char *sv_source_filename = 0;
-static char *sv_header_filename = 0;
-
-//
-// Generate a header and source file in a temporary directory and
-// load those into the Code Viewer widgets.
-//
+/**
+ Generate a header and source file in a temporary directory and
+ load those into the Code Viewer widgets.
+ */
void update_sourceview_cb(Fl_Button*, void*)
{
if (!sourceview_panel || !sourceview_panel->visible())
@@ -1662,48 +1687,23 @@ void update_sourceview_cb(Fl_Button*, void*)
header_file_name = header_file_name_bak;
}
+/**
+ This is called by the timer itself
+ */
void update_sourceview_timer(void*)
{
update_sourceview_cb(0,0);
}
-// Set the "modified" flag and update the title of the main window...
-void set_modflag(int mf) {
- const char *basename;
- static char title[FL_PATH_MAX];
-
- modflag = mf;
-
- if (main_window) {
- if (!filename) basename = "Untitled.fl";
- else if ((basename = strrchr(filename, '/')) != NULL) basename ++;
-#if defined(_WIN32)
- else if ((basename = strrchr(filename, '\\')) != NULL) basename ++;
-#endif // _WIN32
- else basename = filename;
-
- if (modflag) {
- snprintf(title, sizeof(title), "%s (modified)", basename);
- main_window->label(title);
- } else main_window->label(basename);
- }
- // if the UI was modified in any way, update the Source View panel
- if (sourceview_panel && sourceview_panel->visible() && sv_autorefresh->value())
- {
- // we will only update earliest 0.5 seconds after the last change, and only
- // if no other change was made, so dragging a widget will not generate any
- // CPU load
- Fl::remove_timeout(update_sourceview_timer, 0);
- Fl::add_timeout(0.5, update_sourceview_timer, 0);
- }
-
- // Enable/disable the Save menu item...
- if (modflag) save_item->activate();
- else save_item->deactivate();
-}
-
-////////////////////////////////////////////////////////////////
+// ---- Main program entry point
+/**
+ Handle command line arguments.
+ \param[in] argc number of arguments in the list
+ \param[in] argv pointer to an array of arguments
+ \param[inout] i current argument index
+ \return number of arguments used; if 0, the argument is not supported
+ */
static int arg(int argc, char** argv, int& i) {
if (argv[i][1] == 'd' && !argv[i][2]) {G_debug=1; i++; return 1;}
if (argv[i][1] == 'u' && !argv[i][2]) {update_file++; batch_mode++; i++; return 1;}
@@ -1721,13 +1721,6 @@ static int arg(int argc, char** argv, int& i) {
i += 2;
return 2;
}
- Fl_Plugin_Manager pm("commandline");
- int j, n = pm.plugins();
- for (j=0; j<n; j++) {
- Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(j);
- int r = pi->arg(argc, argv, i);
- if (r) return r;
- }
return 0;
}
@@ -1751,8 +1744,27 @@ static void sigint(SIGARG) {
quit_flag = 1;
}
}
+
#endif
+/**
+ Start Fluid.
+
+ Fluid can run in interactive mode with a full user interface to design new
+ user interfaces and write the C++ files to manage them,
+
+ Fluid can run form the command line in batch mode to convert .fl design files
+ into C++ source and header files. In batch mode, no diplay is needed,
+ particularly no X11 connection will be attempted on Linux/Unix.
+
+ \param[in] argc number of arguments in the list
+ \param[in] argv pointer to an array of arguments
+ \return in batch mode, an error code will be returned via \c exit() . This
+ function return 1, if there was an error in the parameters list.
+ \todo On MSWindows, Fluid can under certain conditions open a dialog box, even
+ in batch mode. Is that intentional? Does it circumvent issues with Windows'
+ stderr and stdout?
+ */
int main(int argc,char **argv) {
int i = 1;
@@ -1768,30 +1780,13 @@ int main(int argc,char **argv) {
" -o <name> : .cxx output filename, or extension if <name> starts with '.'\n"
" -h <name> : .h output filename, or extension if <name> starts with '.'\n"
" -d : enable internal debugging\n";
- int len = (int)(strlen(msg) + strlen(argv[0]?argv[0]:"fluid") + strlen(Fl::help));
- Fl_Plugin_Manager pm("commandline");
- int i, n = pm.plugins();
- for (i=0; i<n; i++) {
- Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(i);
- if (pi) len += (int)strlen(pi->help());
- }
- char *buf = (char*)malloc(len+1);
- sprintf(buf, msg, argv[0]);
- for (i=0; i<n; i++) {
- Fl_Commandline_Plugin *pi = (Fl_Commandline_Plugin*)pm.plugin(i);
- if (pi) strcat(buf, pi->help());
- }
- strcat(buf, Fl::help);
#ifdef _MSC_VER
- fl_message("%s\n", buf);
+ fl_message("%s\n", msg);
#else
- fprintf(stderr, "%s\n", buf);
+ fprintf(stderr, "%s\n", msg);
#endif
- free(buf);
return 1;
}
- if (exit_early)
- exit(0);
const char *c = argv[i];
@@ -1799,7 +1794,6 @@ int main(int argc,char **argv) {
make_main_window();
-
if (c) set_filename(c);
if (!batch_mode) {
#ifdef __APPLE__
@@ -1862,3 +1856,6 @@ int main(int argc,char **argv) {
return (0);
}
+
+/// \}
+
diff --git a/fluid/fluid.h b/fluid/fluid.h
new file mode 100644
index 000000000..e2370359f
--- /dev/null
+++ b/fluid/fluid.h
@@ -0,0 +1,118 @@
+//
+// FLUID main entry for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_FLUID_H
+#define _FLUID_FLUID_H
+
+#include <FL/filename.H>
+#include <FL/Fl_Preferences.H>
+#include <FL/Fl_Menu_Item.H>
+
+#define BROWSERWIDTH 300
+#define BROWSERHEIGHT 500
+#define WINWIDTH 300
+#define MENUHEIGHT 25
+#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT)
+
+class Fl_Double_Window;
+class Fl_Window;
+class Fl_Menu_Bar;
+class Fl_Type;
+class Fl_Choice;
+class Fl_Button;
+
+extern int force_parent;
+
+extern Fl_Preferences fluid_prefs;
+extern Fl_Menu_Item Main_Menu[];
+extern Fl_Menu_Bar *main_menubar;
+extern Fl_Window *main_window;
+
+extern int gridx;
+extern int gridy;
+extern int snap;
+extern int show_guides;
+extern int show_comments;
+
+extern int G_use_external_editor;
+extern int G_debug;
+extern char G_external_editor_command[512];
+
+extern int reading_file;
+
+// File history info...
+extern char absolute_history[10][FL_PATH_MAX];
+extern char relative_history[10][FL_PATH_MAX];
+extern void load_history();
+extern void update_history(const char *);
+
+extern Fl_Menu_Item *save_item;
+extern Fl_Menu_Item *history_item;
+extern Fl_Menu_Item *widgetbin_item;
+extern Fl_Menu_Item *sourceview_item;
+
+extern int modflag;
+
+extern void goto_source_dir();
+extern void leave_source_dir();
+
+extern int update_file; // fluid -u
+extern int compile_file; // fluid -c
+extern int compile_strings; // fluic -cs
+extern int batch_mode;
+
+extern int header_file_set;
+extern int code_file_set;
+extern const char* header_file_name;
+extern const char* code_file_name;
+
+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[FL_PATH_MAX];
+
+extern int pasteoffset;
+
+// ---- public functions
+
+extern void set_filename(const char *c);
+extern void set_modflag(int mf);
+
+// ---- public callback functions
+
+extern void save_cb(Fl_Widget *, void *v);
+extern void save_template_cb(Fl_Widget *, void *);
+extern void revert_cb(Fl_Widget *,void *);
+extern void exit_cb(Fl_Widget *,void *);
+
+#ifdef __APPLE__
+extern void apple_open_cb(const char *c);
+#endif // __APPLE__
+
+extern void open_cb(Fl_Widget *, void *v);
+extern void open_history_cb(Fl_Widget *, void *v);
+extern void new_cb(Fl_Widget *, void *v);
+extern void new_from_template_cb(Fl_Widget *w, void *v);
+
+extern int write_code_files();
+extern void write_strings_cb(Fl_Widget *, void *);
+extern void align_widget_cb(Fl_Widget *, long);
+extern void widget_size_cb(Fl_Widget *, long);
+extern void toggle_widgetbin_cb(Fl_Widget *, void *);
+
+#endif // _FLUID_FLUID_H
diff --git a/fluid/function_panel.cxx b/fluid/function_panel.cxx
index e6821be2d..6cb60bcd0 100644
--- a/fluid/function_panel.cxx
+++ b/fluid/function_panel.cxx
@@ -17,14 +17,12 @@
// generated by Fast Light User Interface Designer (fluid) version 1.0400
#include "function_panel.h"
-#include <FL/Fl_Pixmap.H>
+#include "fluid.h"
+#include "pixmaps.h"
+#include "factory.h"
#include "Fl_Type.h"
+#include "widget_browser.h"
#include "undo.h"
-extern class Fl_Pixmap *pixmap[];
-extern class Fl_Type *Fl_Type_make(const char*);
-extern void select_only(Fl_Type*);
-extern void exit_cb(Fl_Widget*, void*);
-extern void toggle_widgetbin_cb(Fl_Widget*, void*);
/**
Allow widget navigation on text fields with Tab.
diff --git a/fluid/function_panel.fl b/fluid/function_panel.fl
index 6ef30500a..d0750b87d 100644
--- a/fluid/function_panel.fl
+++ b/fluid/function_panel.fl
@@ -20,28 +20,22 @@ comment {//
} {in_source in_header
}
-decl {\#include <FL/Fl_Pixmap.H>} {private local
+decl {\#include "fluid.h"} {private local
}
-decl {\#include "Fl_Type.h"} {private local
-}
-
-decl {\#include "undo.h"} {private local
+decl {\#include "pixmaps.h"} {private local
}
-decl {extern class Fl_Pixmap *pixmap[];} {private local
+decl {\#include "factory.h"} {private local
}
-decl {extern class Fl_Type *Fl_Type_make(const char*);} {private local
-}
-
-decl {extern void select_only(Fl_Type*);} {private local
+decl {\#include "Fl_Type.h"} {private local
}
-decl {extern void exit_cb(Fl_Widget*, void*);} {private global
+decl {\#include "widget_browser.h"} {selected private local
}
-decl {extern void toggle_widgetbin_cb(Fl_Widget*, void*);} {private global
+decl {\#include "undo.h"} {private local
}
Function {use_tab_navigation(int, Fl_Text_Editor*)} {
@@ -50,10 +44,11 @@ Function {use_tab_navigation(int, Fl_Text_Editor*)} {
code {return 0;} {}
}
-Function {make_function_panel()} {} {
+Function {make_function_panel()} {open
+} {
Fl_Window function_panel {
- label {Function/Method Properties} open
- xywh {557 523 343 232} type Double hide resizable modal
+ label {Function/Method Properties}
+ xywh {101 713 343 232} type Double resizable modal visible
} {
Fl_Group {} {open
xywh {10 10 270 20}
@@ -131,14 +126,15 @@ Function {make_function_panel()} {} {
}
}
-Function {make_code_panel()} {} {
+Function {make_code_panel()} {open
+} {
Fl_Window code_panel {
label {Code Properties}
callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape)
return; // ignore Escape
-code_panel->hide(); // otherwise hide..} open
- xywh {503 450 540 180} type Double labelsize 11 hide resizable
- code0 {o->size_range(200, 150);} modal
+code_panel->hide(); // otherwise hide..}
+ xywh {425 882 540 180} type Double labelsize 11 resizable
+ code0 {o->size_range(200, 150);} modal visible
} {
Fl_Text_Editor code_input {
xywh {10 10 520 130} box DOWN_BOX labelsize 11 textfont 4 textsize 11 resizable
@@ -167,11 +163,12 @@ code_input->linenumber_width(60);
code_input->linenumber_size(code_input->Fl_Text_Display::textsize());} {}
}
-Function {make_codeblock_panel()} {} {
+Function {make_codeblock_panel()} {open
+} {
Fl_Window codeblock_panel {
- label {Code Block Properties} open
- xywh {468 221 300 115} type Double labelsize 11 hide resizable
- code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal
+ label {Code Block Properties}
+ xywh {806 735 300 115} type Double labelsize 11 resizable
+ code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal visible
} {
Fl_Input code_before_input {
label {Conditional code block}
@@ -199,11 +196,12 @@ Function {make_codeblock_panel()} {} {
}
}
-Function {make_declblock_panel()} {} {
+Function {make_declblock_panel()} {open
+} {
Fl_Window declblock_panel {
- label {Declaration Block Properties} open
- xywh {428 215 300 135} type Double labelsize 11 hide resizable
- code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal
+ label {Declaration Block Properties}
+ xywh {806 564 300 135} type Double labelsize 11 resizable
+ code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal visible
} {
Fl_Group {} {open
xywh {10 10 280 20}
@@ -255,10 +253,11 @@ Function {make_declblock_panel()} {} {
}
}
-Function {make_decl_panel()} {} {
+Function {make_decl_panel()} {open
+} {
Fl_Window decl_panel {
- label {Declaration Properties} open
- xywh {480 333 343 237} type Double align 80 hide resizable size_range {343 237 0 0}
+ label {Declaration Properties}
+ xywh {445 609 343 237} type Double align 80 resizable size_range {343 237 0 0} visible
} {
Fl_Group {} {open
xywh {10 10 270 20}
@@ -331,10 +330,11 @@ Function {make_decl_panel()} {} {
}
}
-Function {make_data_panel()} {} {
+Function {make_data_panel()} {open
+} {
Fl_Window data_panel {
- label {Inline Data Properties} open
- xywh {472 191 343 237} type Double align 80 hide resizable size_range {343 237 0 0}
+ label {Inline Data Properties}
+ xywh {449 337 343 237} type Double align 80 resizable size_range {343 237 0 0} visible
} {
Fl_Group {} {open
xywh {10 10 320 20}
@@ -419,10 +419,11 @@ Function {make_data_panel()} {} {
}
}
-Function {make_class_panel()} {} {
+Function {make_class_panel()} {open
+} {
Fl_Window class_panel {
- label {Class Properties} open
- xywh {497 585 342 196} type Double labelsize 11 hide resizable modal size_range {343 188 0 0}
+ label {Class Properties}
+ xywh {795 337 342 196} type Double labelsize 11 resizable modal size_range {343 188 0 0} visible
} {
Fl_Group {} {open
xywh {10 10 280 20} hide
@@ -540,8 +541,8 @@ Function {make_widgetbin()} {open
callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape)
exit_cb((Fl_Widget*)o, v);
else
- toggle_widgetbin_cb((Fl_Widget*)o, v);} open
- xywh {445 273 600 102} type Single align 80 non_modal visible
+ toggle_widgetbin_cb((Fl_Widget*)o, v);}
+ xywh {449 206 600 102} type Single align 80 non_modal visible
} {
Fl_Group {} {
label Code open
@@ -844,7 +845,7 @@ else
}
Fl_Button {} {
user_data {"radiomenuitem"}
- callback type_make_cb selected
+ callback type_make_cb
tooltip {Radio Menu Item} xywh {425 71 24 24} box THIN_UP_BOX
code0 {o->image(pixmap[55]);}
}
diff --git a/fluid/print_panel.cxx b/fluid/print_panel.cxx
index 6b8c8248f..eae17fee5 100644
--- a/fluid/print_panel.cxx
+++ b/fluid/print_panel.cxx
@@ -17,12 +17,11 @@
// generated by Fast Light User Interface Designer (fluid) version 1.0400
#include "print_panel.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include "../src/flstring.h"
+#include "fluid.h"
#include <FL/fl_string.h>
-#include <FL/Fl_Preferences.H>
-extern Fl_Preferences fluid_prefs;
+#include "../src/flstring.h"
+#include <stdlib.h>
+#include <stdio.h>
Fl_Double_Window *print_panel=(Fl_Double_Window *)0;
diff --git a/fluid/print_panel.fl b/fluid/print_panel.fl
index e2042f531..9119d35a9 100644
--- a/fluid/print_panel.fl
+++ b/fluid/print_panel.fl
@@ -20,29 +20,26 @@ comment {//
} {in_source in_header
}
-decl {\#include <stdio.h>} {private local
+decl {\#include "fluid.h"} {selected private local
}
-decl {\#include <stdlib.h>} {private local
+decl {\#include <FL/fl_string.h>} {private local
}
decl {\#include "../src/flstring.h"} {private local
}
-decl {\#include <FL/fl_string.h>} {private local
-}
-
-decl {\#include <FL/Fl_Preferences.H>} {private local
+decl {\#include <stdlib.h>} {private local
}
-decl {extern Fl_Preferences fluid_prefs;} {private local
+decl {\#include <stdio.h>} {private local
}
Function {make_print_panel()} {open
} {
Fl_Window print_panel {
- label Print open
- xywh {394 209 465 235} type Double hide modal
+ label Print
+ xywh {465 222 465 235} type Double modal visible
} {
Fl_Group print_panel_controls {open
xywh {10 10 447 216}
@@ -215,8 +212,8 @@ print_collate_group[1 - i]->hide();}
Fl_Window print_properties_panel {
label {Printer Properties}
callback {print_properties_panel->hide();
-print_update_status();} open
- xywh {400 537 290 130} type Double hide modal
+print_update_status();}
+ xywh {462 486 290 130} type Double modal visible
} {
Fl_Choice print_page_size {
label {Page Size:}
diff --git a/fluid/shell_command.cxx b/fluid/shell_command.cxx
new file mode 100644
index 000000000..7e77d1883
--- /dev/null
+++ b/fluid/shell_command.cxx
@@ -0,0 +1,234 @@
+//
+// FLUID main entry for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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 "shell_command.h"
+
+#include "fluid.h"
+#include "alignment_panel.h"
+
+#include <FL/Fl_Double_Window.H>
+#include <FL/fl_message.H>
+
+#include <errno.h>
+
+static Fl_Process s_proc;
+
+/** \class Fl_Process
+ \todo Explain.
+ */
+
+Fl_Process::Fl_Process() {
+ _fpt= NULL;
+}
+
+Fl_Process::~Fl_Process() {
+ if (_fpt) close();
+}
+
+// FIXME: popen needs the UTF-8 equivalent fl_popen
+// portable open process:
+FILE * Fl_Process::popen(const char *cmd, const char *mode) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // PRECONDITIONS
+ if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return NULL;
+ if (_fpt) close(); // close first before reuse
+
+ ptmode = *mode;
+ pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE;
+ // stderr to stdout wanted ?
+ int fusion = (strstr(cmd,"2>&1") !=NULL);
+
+ // Create windows pipes
+ if (!createPipe(pin) || !createPipe(pout) || (!fusion && !createPipe(perr) ) )
+ return freeHandles(); // error
+
+ // Initialize Startup Info
+ ZeroMemory(&si, sizeof(STARTUPINFO));
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = pin[0];
+ si.hStdOutput = pout[1];
+ si.hStdError = fusion ? pout[1] : perr [1];
+
+ if ( CreateProcess(NULL, (LPTSTR) cmd,NULL,NULL,TRUE,
+ DETACHED_PROCESS,NULL,NULL, &si, &pi)) {
+ // don't need theses handles inherited by child process:
+ clean_close(pin[0]); clean_close(pout[1]); clean_close(perr[1]);
+ HANDLE & h = *mode == 'r' ? pout[0] : pin[1];
+ _fpt = _fdopen(_open_osfhandle((fl_intptr_t) h,_O_BINARY),mode);
+ h= INVALID_HANDLE_VALUE; // reset the handle pointer that is shared
+ // with _fpt so we don't free it twice
+ }
+
+ if (!_fpt) freeHandles();
+ return _fpt;
+#else
+ _fpt=::popen(cmd,mode);
+ return _fpt;
+#endif
+}
+
+int Fl_Process::close() {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (_fpt) {
+ fclose(_fpt);
+ clean_close(perr[0]);
+ clean_close(pin[1]);
+ clean_close(pout[0]);
+ _fpt = NULL;
+ return 0;
+ }
+ return -1;
+#else
+ int ret = ::pclose(_fpt);
+ _fpt=NULL;
+ return ret;
+#endif
+}
+
+// non-null if file is open
+FILE *Fl_Process::desc() const {
+ return _fpt;
+}
+
+char *Fl_Process::get_line(char * line, size_t s) const {
+ return _fpt ? fgets(line, (int)s, _fpt) : NULL;
+}
+
+// returns fileno(FILE*):
+// (file must be open, i.e. _fpt must be non-null)
+// *FIXME* we should find a better solution for the 'fileno' issue
+// non null if file is open
+int Fl_Process::get_fileno() const {
+#ifdef _MSC_VER
+ return _fileno(_fpt); // suppress MSVC warning
+#else
+ return fileno(_fpt);
+#endif
+}
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
+bool Fl_Process::createPipe(HANDLE * h, BOOL bInheritHnd) {
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = bInheritHnd;
+ return CreatePipe (&h[0],&h[1],&sa,0) ? true : false;
+}
+
+FILE *Fl_Process::freeHandles() {
+ clean_close(pin[0]); clean_close(pin[1]);
+ clean_close(pout[0]); clean_close(pout[1]);
+ clean_close(perr[0]); clean_close(perr[1]);
+ return NULL; // convenient for error management
+}
+
+void Fl_Process::clean_close(HANDLE& h) {
+ if (h!= INVALID_HANDLE_VALUE) CloseHandle(h);
+ h = INVALID_HANDLE_VALUE;
+}
+
+#endif
+
+
+// Shell command support...
+
+static bool prepare_shell_command(const char * &command) { // common pre-shell command code all platforms
+ shell_window->hide();
+ if (s_proc.desc()) {
+ fl_alert("Previous shell command still running!");
+ return false;
+ }
+ if ((command = shell_command_input->value()) == NULL || !*command) {
+ fl_alert("No shell command entered!");
+ return false;
+ }
+ if (shell_savefl_button->value()) {
+ save_cb(0, 0);
+ }
+ if (shell_writecode_button->value()) {
+ write_code_files();
+ }
+ if (shell_writemsgs_button->value()) {
+ write_strings_cb(0, 0);
+ }
+ return true;
+}
+
+// Support the full piped shell command...
+void shell_pipe_cb(FL_SOCKET, void*) {
+ char line[1024]=""; // Line from command output...
+
+ if (s_proc.get_line(line, sizeof(line)) != NULL) {
+ // Add the line to the output list...
+ shell_run_terminal->append(line);
+ } else {
+ // End of file; tell the parent...
+ Fl::remove_fd(s_proc.get_fileno());
+ s_proc.close();
+ shell_run_terminal->append("... END SHELL COMMAND ...\n");
+ }
+}
+
+void do_shell_command(Fl_Return_Button*, void*) {
+ const char *command=NULL; // Command to run
+
+ if (!prepare_shell_command(command)) return;
+
+ // Show the output window and clear things...
+ shell_run_terminal->text("");
+ shell_run_terminal->append(command);
+ shell_run_terminal->append("\n");
+ shell_run_window->label("Shell Command Running...");
+
+ if (s_proc.popen((char *)command) == NULL) {
+ fl_alert("Unable to run shell command: %s", strerror(errno));
+ return;
+ }
+
+ shell_run_button->deactivate();
+
+ Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos");
+ int x, y, w, h;
+ pos.get("x", x, -1);
+ pos.get("y", y, 0);
+ pos.get("w", w, 640);
+ pos.get("h", h, 480);
+ if (x!=-1) {
+ shell_run_window->resize(x, y, w, h);
+ }
+ shell_run_window->show();
+
+ Fl::add_fd(s_proc.get_fileno(), shell_pipe_cb);
+
+ while (s_proc.desc()) Fl::wait();
+
+ shell_run_button->activate();
+ shell_run_window->label("Shell Command Complete");
+ fl_beep();
+
+ while (shell_run_window->shown()) Fl::wait();
+}
+
+/**
+ Show a dialog box to run an external shell command.
+ */
+void show_shell_window() {
+ shell_window->hotspot(shell_command_input);
+ shell_window->show();
+}
+
diff --git a/fluid/shell_command.h b/fluid/shell_command.h
new file mode 100644
index 000000000..cc86e0662
--- /dev/null
+++ b/fluid/shell_command.h
@@ -0,0 +1,67 @@
+//
+// FLUID main entry for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_SHELL_COMMAND_H
+#define _FLUID_SHELL_COMMAND_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# include <direct.h>
+# include <windows.h>
+# include <io.h>
+# include <fcntl.h>
+# include <commdlg.h>
+# include <FL/platform.H>
+#else
+# include <unistd.h>
+#endif
+
+void show_shell_window();
+
+class Fl_Process {
+public:
+ Fl_Process();
+ ~Fl_Process();
+
+ FILE *popen(const char *cmd, const char *mode="r");
+ int close();
+
+ FILE * desc() const;
+ char * get_line(char * line, size_t s) const;
+
+ int get_fileno() const;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+protected:
+ HANDLE pin[2], pout[2], perr[2];
+ char ptmode;
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+
+ static bool createPipe(HANDLE * h, BOOL bInheritHnd=TRUE);
+
+private:
+ FILE * freeHandles();
+ static void clean_close(HANDLE& h);
+#endif
+
+protected:
+ FILE * _fpt;
+};
+
+#endif // _FLUID_SHELL_COMMAND_H
diff --git a/fluid/template_panel.cxx b/fluid/template_panel.cxx
index 18b363f4d..04117ba6c 100644
--- a/fluid/template_panel.cxx
+++ b/fluid/template_panel.cxx
@@ -17,21 +17,20 @@
// generated by Fast Light User Interface Designer (fluid) version 1.0400
#include "template_panel.h"
+#include "fluid.h"
+#include <FL/Fl_Shared_Image.H>
+#include <FL/fl_ask.H>
+#include <FL/fl_string.h>
+#include <FL/filename.H>
+#include "../src/flstring.h"
#include <stdio.h>
#include <stdlib.h>
-#include "../src/flstring.h"
-#include <FL/fl_string.h>
#include <errno.h>
-#include <FL/filename.H>
-#include <FL/fl_ask.H>
-#include <FL/Fl_Shared_Image.H>
-#include <FL/Fl_Preferences.H>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <io.h>
#else
#include <unistd.h>
#endif // _WIN32 && !__CYGWIN__
-extern Fl_Preferences fluid_prefs;
Fl_Double_Window *template_panel=(Fl_Double_Window *)0;
diff --git a/fluid/template_panel.fl b/fluid/template_panel.fl
index b0d5b9ff9..9407a7564 100644
--- a/fluid/template_panel.fl
+++ b/fluid/template_panel.fl
@@ -20,31 +20,31 @@ comment {//
} {in_source in_header
}
-decl {\#include <stdio.h>} {private local
+decl {\#include "fluid.h"} {private local
}
-decl {\#include <stdlib.h>} {private local
+decl {\#include <FL/Fl_Shared_Image.H>} {private local
}
-decl {\#include "../src/flstring.h"} {private local
+decl {\#include <FL/fl_ask.H>} {private local
}
decl {\#include <FL/fl_string.h>} {private local
}
-decl {\#include <errno.h>} {private local
+decl {\#include <FL/filename.H>} {selected private local
}
-decl {\#include <FL/filename.H>} {private local
+decl {\#include "../src/flstring.h"} {private local
}
-decl {\#include <FL/fl_ask.H>} {private local
+decl {\#include <stdio.h>} {private local
}
-decl {\#include <FL/Fl_Shared_Image.H>} {private local
+decl {\#include <stdlib.h>} {private local
}
-decl {\#include <FL/Fl_Preferences.H>} {private local
+decl {\#include <errno.h>} {private local
}
declblock {\#if defined(_WIN32) && !defined(__CYGWIN__)} {after {\#endif // _WIN32 && !__CYGWIN__}
@@ -57,9 +57,6 @@ declblock {\#if defined(_WIN32) && !defined(__CYGWIN__)} {after {\#endif // _WIN
}
}
-decl {extern Fl_Preferences fluid_prefs;} {private local
-}
-
Function {make_template_panel()} {open
} {
Fl_Window template_panel {
@@ -71,8 +68,8 @@ template_preview->image(0);
template_browser->deselect();
template_name->value("");
template_instance->value("");
-template_panel->hide();} open
- xywh {398 200 460 355} type Double hide resizable modal
+template_panel->hide();}
+ xywh {455 202 460 355} type Double resizable modal visible
} {
Fl_Browser template_browser {
label {Available Templates:}
@@ -207,7 +204,7 @@ template_browser->remove(item);
template_browser->do_callback();} {}
}
-Function {template_load()} {open return_type void
+Function {template_load()} {return_type void
} {
code {int i;
char name[1024], filename[1400], path[1024], *ptr;
@@ -262,6 +259,5 @@ for (i = 0; i < num_files; i ++) {
free(files[i]);
}
-if (num_files > 0) free(files);} {selected
- }
+if (num_files > 0) free(files);} {}
}
diff --git a/fluid/undo.cxx b/fluid/undo.cxx
index 1afbb09f0..38d70c2e1 100644
--- a/fluid/undo.cxx
+++ b/fluid/undo.cxx
@@ -14,10 +14,15 @@
// https://www.fltk.org/bugs.php
//
-#include <FL/Fl.H>
-#include "Fl_Type.h"
#include "undo.h"
+
+#include "fluid.h"
+#include "file.h"
+#include "Fl_Type.h"
+
+#include <FL/Fl.H>
#include <FL/Fl_Preferences.H>
+#include <FL/Fl_Menu_Bar.H>
#include <FL/filename.H>
#include "../src/flstring.h"
@@ -30,12 +35,6 @@
#endif // _WIN32 && !__CYGWIN__
-extern Fl_Preferences fluid_prefs; // FLUID preferences
-extern Fl_Menu_Item Main_Menu[]; // Main menu
-extern Fl_Menu_Bar *main_menubar; // Main menubar
-
-
-
//
// This file implements an undo system using temporary files; ideally
// we'd like to do this in memory, however the current data structures
diff --git a/fluid/undo.h b/fluid/undo.h
index c1d1aef44..171fe062f 100644
--- a/fluid/undo.h
+++ b/fluid/undo.h
@@ -15,7 +15,9 @@
//
#ifndef undo_h
-# define undo_h
+#define undo_h
+
+class Fl_Widget;
extern int undo_current; // Current undo level in buffer
extern int undo_last; // Last undo level in buffer
diff --git a/fluid/widget_browser.cxx b/fluid/widget_browser.cxx
new file mode 100644
index 000000000..6d4d1028a
--- /dev/null
+++ b/fluid/widget_browser.cxx
@@ -0,0 +1,507 @@
+//
+// Widget Browser code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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 "widget_browser.h"
+
+#include "fluid.h"
+#include "Fl_Widget_Type.h"
+#include "pixmaps.h"
+
+#include <FL/Fl.H>
+#include <FL/Fl_Browser_.H>
+#include <FL/fl_draw.H>
+
+/**
+ \class Widget_Browser
+
+ A widget that displays the nodes in the widget tree.
+
+ The Widget Browser is derived from the FLTK basic browser, extending
+ tree browsing functionality by using the \c depth component of the double
+ linked list of \c Fl_Type items.
+
+ \see Fl_Type
+ */
+
+// ---- global variables
+
+/// Global access to the widget browser.
+Widget_Browser *widget_browser = NULL;
+
+// ---- global functions
+
+/**
+ Shortcut to have the widget browser graphics refreshed soon.
+ */
+void redraw_browser() {
+ widget_browser->redraw();
+}
+
+/**
+ Shortcut to create the widget browser.
+ */
+Fl_Widget *make_widget_browser(int x,int y,int w,int h) {
+ return (widget_browser = new Widget_Browser(x,y,w,h));
+}
+
+/**
+ Make sure thet the caller is visible in the widget browser.
+ \param[in] caller scroll the browser in y so that caller
+ is visible (may be NULL)
+ */
+void redraw_widget_browser(Fl_Type *caller)
+{
+ if (caller)
+ widget_browser->display(caller);
+ widget_browser->redraw();
+}
+
+/**
+ Select or deselect a node in the widget browser.
+ \param[in] o (de)select this node
+ \oaram[in] v the new selection state (1=select, 0=de-select)
+ */
+void select(Fl_Type *o, int v) {
+ widget_browser->select(o,v,1);
+}
+
+/**
+ Select a single node in the widget browser, deselect all others.
+ \param[in] o select this node
+ */
+void select_only(Fl_Type *o) {
+ widget_browser->select_only(o,1);
+}
+
+/**
+ Deselect all nodes in the widget browser.
+ */
+void deselect() {
+ widget_browser->deselect();
+}
+
+/**
+ Show the selected item in the browser window.
+
+ Make sure that the given item is visible in the browser by opening
+ all parent groups and moving the item into the visible space.
+
+ \param[in] t show this ite
+ */
+void reveal_in_browser(Fl_Type *t) {
+ Fl_Type *p = t->parent;
+ if (p) {
+ for (;;) {
+ if (!p->open_)
+ p->open_ = 1;
+ if (!p->parent) break;
+ p = p->parent;
+ }
+ fixvisible(p);
+ }
+ widget_browser->display(t);
+ widget_browser->redraw();
+}
+
+// ---- local functions
+
+/**
+ Copy the given string str to buffer p with no more than maxl characters.
+
+ Add "..." if string was truncated.
+
+ Quote characters are NOT counted.
+
+ \param[out] p return the resulting string in this buffer, terminated with
+ a NUL byte
+ \param[in] str copy this string; utf8 aware
+ \param[in] maxl maximum number of letter to copy until we print
+ the elipsis (...)
+ \param[in] auote if set, the resulting string is embedded in double quotes
+ \returns pointer to end of string (before terminating null byte).
+ \note the buffer p must be large enough to hold (4 * (maxl+1) + 1) bytes
+ or (4 * (maxl+1) + 3) bytes if quoted, e.g. "123..." because each UTF-8
+ character can consist of 4 bytes, "..." adds 3 bytes, quotes '""' add two
+ bytes, and the terminating null byte adds another byte.
+ This supports Unicode code points up to U+10FFFF (standard as of 10/2016).
+ Sanity checks for illegal UTF-8 sequences are included.
+ */
+static char *copy_trunc(char *p, const char *str, int maxl, int quote)
+{
+ int size = 0; // truncated string size in characters
+ int bs; // size of UTF-8 character in bytes
+ const char *end = str + strlen(str); // end of input string
+ if (quote) *p++ = '"'; // opening quote
+ while (size < maxl) { // maximum <maxl> characters
+ if (!(*str & (-32))) break; // end of string (0 or control char)
+ bs = fl_utf8len(*str); // size of next character
+ if (bs <= 0) break; // some error - leave
+ if (str + bs > end) break; // UTF-8 sequence beyond end of string
+ while (bs--) *p++ = *str++; // copy that character into the buffer
+ size++; // count copied characters
+ }
+ if (*str) { // string was truncated
+ strcpy(p,"..."); p += 3;
+ }
+ if (quote) *p++ = '"'; // closing quote
+ *p = 0; // terminating null byte
+ return p;
+}
+
+// ---- Widget_Browser implementation
+
+/**
+ Create a new instance of the Widget_Browser widget.
+
+ Fluid currently generates only one instance of this browser. If we want
+ to use multiple browser at some point, we need to refactor a few global
+ variables, i.e. Fl_Type::first and Fl_Type::last .
+
+ \param[in] X, Y, W, H position and size of widget
+ \param[in] l optional label
+ \todo It would be nice to be able to grab one or more nodes and mmove them
+ within the hierarchy.
+ */
+Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l)
+: Fl_Browser_(X,Y,W,H,l),
+ pushedtitle(NULL)
+{
+ type(FL_MULTI_BROWSER);
+ Fl_Widget::callback(callback_stub);
+ when(FL_WHEN_RELEASE);
+}
+
+/**
+ Override the method to find the first item in the list of elements.
+ \return the first item
+ */
+void *Widget_Browser::item_first() const {
+ return Fl_Type::first;
+}
+
+/**
+ Override the method to find the next item in the list of elements.
+ \param l this item
+ \return the next item, irregardless of tree depth, or NULL at the end
+ */
+void *Widget_Browser::item_next(void *l) const {
+ return ((Fl_Type*)l)->next;
+}
+
+/**
+ Override the method to find the previous item in the list of elements.
+ \param l this item
+ \return the previous item, irregardless of tree depth, or NULL at the start
+ */
+void *Widget_Browser::item_prev(void *l) const {
+ return ((Fl_Type*)l)->prev;
+}
+
+/**
+ Override the method to check if an item was selected.
+ \param l this item
+ \return 1 if selected, 0 if not
+ \todo what is the difference between selected and new_selected, and why do we do this?
+ */
+int Widget_Browser::item_selected(void *l) const {
+ return ((Fl_Type*)l)->new_selected;
+}
+
+/**
+ Override the method to mark an item selected.
+ \param l this item
+ \param[in] v 1 if selecting, 0 if not
+ */
+void Widget_Browser::item_select(void *l,int v) {
+ ((Fl_Type*)l)->new_selected = v;
+}
+
+/**
+ Override the method to return the height of an item representation in Flixels.
+ \param l this item
+ \return height in FLTK units (used to be pixels before high res screens)
+ */
+int Widget_Browser::item_height(void *l) const {
+ Fl_Type *t = (Fl_Type*)l;
+ if (t->visible) {
+ if (show_comments && t->comment())
+ return textsize()*2+4;
+ else
+ return textsize()+5;
+ }
+ return 0;
+}
+
+/**
+ Override the method to return the estimated height of all items.
+ \return height in FLTK units
+ */
+int Widget_Browser::incr_height() const {
+ return textsize()+2;
+}
+
+/**
+ Draw an item in the widget browser.
+
+ A browser line starts with a variable size space. This space directly
+ relates to the level of the type entry.
+
+ If this type has the ability to store children, a triangle follows,
+ pointing right (closed) or pointing down (open, children shown).
+
+ Next follows an icon that is specific to the type. This makes it easy to
+ spot certain types.
+
+ Now follows some text. For classes and widgets, this is the type itself,
+ followed by the name of the object. Other objects show their content as
+ text, possibly abbreviated with an ellipsis.
+
+ \param v v is a pointer to the actual widget type and can be cast safely
+ to Fl_Type
+ \param X,Y these give the position in window coordinates of the top left
+ corner of this line
+*/
+void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
+ // cast to a more general type
+ Fl_Type *l = (Fl_Type *)v;
+
+ char buf[340]; // edit buffer: large enough to hold 80 UTF-8 chars + nul
+
+ // calculate the horizontal start position of this item
+ // 3 is the edge of the browser
+ // 13 is the width of the arrow that indicates children for the item
+ // 18 is the width of the icon
+ // 12 is the indent per level
+ X += 3 + 13 + 18 + l->level * 12;
+
+ // calculate the horizontal start position and width of the separator line
+ int x1 = X;
+ int w1 = w() - x1;
+
+ // items can contain a comment. If they do, the comment gets a second text
+ // line inside this browser line
+ int comment_incr = 0;
+ if (show_comments && l->comment()) {
+ copy_trunc(buf, l->comment(), 80, 0);
+ comment_incr = textsize()-1;
+ if (l->new_selected) fl_color(fl_contrast(FL_DARK_GREEN,FL_SELECTION_COLOR));
+ else fl_color(fl_contrast(FL_DARK_GREEN,color()));
+ fl_font(textfont()+FL_ITALIC, textsize()-2);
+ fl_draw(buf, X, Y+12);
+ Y += comment_incr/2;
+ comment_incr -= comment_incr/2;
+ }
+
+ if (l->new_selected) fl_color(fl_contrast(FL_FOREGROUND_COLOR,FL_SELECTION_COLOR));
+ else fl_color(FL_FOREGROUND_COLOR);
+
+ // Width=10: Draw the triangle that indicates possible children
+ if (l->is_parent()) {
+ X = X - 18 - 13;
+ if (!l->next || l->next->level <= l->level) {
+ if (l->open_!=(l==pushedtitle)) {
+ // an outlined triangle to the right indicates closed item, no children
+ fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7);
+ } else {
+ // an outlined triangle to the bottom indicates open item, no children
+ fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12);
+ }
+ } else {
+ if (l->open_!=(l==pushedtitle)) {
+ // a filled triangle to the right indicates closed item, with children
+ fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7);
+ } else {
+ // a filled triangle to the bottom indicates open item, with children
+ fl_polygon(X+2,Y+2,X+7,Y+7,X+2,Y+12);
+ }
+ }
+ X = X + 13 + 18;
+ }
+
+ // Width=18: Draw the icon associated with the type.
+ Fl_Pixmap *pm = pixmap[l->pixmapID()];
+ if (pm) pm->draw(X-18, Y);
+
+ // Add tags on top of the icon for locked and protected types.
+ switch (l->is_public()) {
+ case 0: lock_pixmap->draw(X - 17, Y); break;
+ case 2: protected_pixmap->draw(X - 17, Y); break;
+ }
+
+ if ( l->is_widget()
+ && !l->is_window()
+ && ((Fl_Widget_Type*)l)->o
+ && !((Fl_Widget_Type*)l)->o->visible()
+ && (!l->parent || ( strcmp(l->parent->type_name(),"Fl_Tabs")
+ && strcmp(l->parent->type_name(),"Fl_Wizard")) )
+ )
+ {
+ invisible_pixmap->draw(X - 17, Y);
+ }
+
+ // Indent=12 per level: Now write the text that comes after the graphics representation
+ Y += comment_incr;
+ if (l->is_widget() || l->is_class()) {
+ const char* c = subclassname(l);
+ if (!strncmp(c,"Fl_",3)) c += 3;
+ fl_font(textfont(), textsize());
+ fl_draw(c, X, Y+13);
+ X += int(fl_width(c)+fl_width('n'));
+ c = l->name();
+ if (c) {
+ fl_font(textfont()|FL_BOLD, textsize());
+ fl_draw(c, X, Y+13);
+ } else if ((c = l->label())) {
+ copy_trunc(buf, c, 20, 1); // quoted string
+ fl_draw(buf, X, Y+13);
+ }
+ } else {
+ copy_trunc(buf, l->title(), 55, 0);
+ fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
+ fl_draw(buf, X, Y+13);
+ }
+
+ // draw a thin line below the item if this item is not selected
+ // (if it is selected this additional line would look bad)
+ if (!l->new_selected) {
+ fl_color(fl_lighter(FL_GRAY));
+ fl_line(x1,Y+16,x1+w1,Y+16);
+ }
+}
+
+/**
+ Override the method to return the width of an item representation in Flixels.
+ \param l this item
+ \return width in FLTK units
+ */
+int Widget_Browser::item_width(void *v) const {
+
+ char buf[340]; // edit buffer: large enough to hold 80 UTF-8 chars + nul
+
+ Fl_Type *l = (Fl_Type *)v;
+
+ if (!l->visible) return 0;
+
+ int W = 3 + 13 + 18 + l->level * 12;
+
+ if (l->is_widget() || l->is_class()) {
+ const char* c = l->type_name();
+ if (!strncmp(c,"Fl_",3)) c += 3;
+ fl_font(textfont(), textsize());
+ W += int(fl_width(c) + fl_width('n'));
+ c = l->name();
+ if (c) {
+ fl_font(textfont()|FL_BOLD, textsize());
+ W += int(fl_width(c));
+ } else if (l->label()) {
+ copy_trunc(buf, l->label(), 20, 1); // quoted string
+ W += int(fl_width(buf));
+ }
+ } else {
+ copy_trunc(buf, l->title(), 55, 0);
+ fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
+ W += int(fl_width(buf));
+ }
+
+ return W;
+}
+
+/**
+ Callback to tell the FLuid UI when the list of selected items changed.
+ */
+void Widget_Browser::callback() {
+ selection_changed((Fl_Type*)selection());
+}
+
+/**
+ Override the event handling for this browser.
+
+ The vertical mouse position corresponds to an entry in the type tree.
+ The horizontal position has the following hot zones:
+ - 0-3 is the widget frame and ignored
+ - the next hot zone starts 12*indent pixels further to the right
+ - the next 13 pixels refer to the arrow that indicates children for the item
+ - 18 pixels follow for the icon
+ - the remaining part is filled with text
+
+ \param[in] e the incoming event type
+ \return 0 if the event is not supported, and 1 if the event was "used up"
+*/
+int Widget_Browser::handle(int e) {
+ static Fl_Type *title;
+ Fl_Type *l;
+ int X,Y,W,H; bbox(X,Y,W,H);
+ switch (e) {
+ case FL_PUSH:
+ if (!Fl::event_inside(X,Y,W,H)) break;
+ l = (Fl_Type*)find_item(Fl::event_y());
+ if (l) {
+ X += 3 + 12*l->level - hposition();
+ if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) {
+ title = pushedtitle = l;
+ redraw_line(l);
+ return 1;
+ }
+ }
+ break;
+ case FL_DRAG:
+ if (!title) break;
+ l = (Fl_Type*)find_item(Fl::event_y());
+ if (l) {
+ X += 3 + 12*l->level - hposition();
+ if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) ;
+ else l = 0;
+ }
+ if (l != pushedtitle) {
+ if (pushedtitle) redraw_line(pushedtitle);
+ if (l) redraw_line(l);
+ pushedtitle = l;
+ }
+ return 1;
+ case FL_RELEASE:
+ if (!title) {
+ l = (Fl_Type*)find_item(Fl::event_y());
+ if (l && l->new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL)))
+ l->open();
+ break;
+ }
+ l = pushedtitle;
+ title = pushedtitle = 0;
+ if (l) {
+ if (l->open_) {
+ l->open_ = 0;
+ for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
+ k->visible = 0;
+ } else {
+ l->open_ = 1;
+ for (Fl_Type*k=l->next; k&&k->level>l->level;) {
+ k->visible = 1;
+ if (k->is_parent() && !k->open_) {
+ Fl_Type *j;
+ for (j = k->next; j && j->level>k->level; j = j->next) {/*empty*/}
+ k = j;
+ } else
+ k = k->next;
+ }
+ }
+ redraw();
+ }
+ return 1;
+ }
+ return Fl_Browser_::handle(e);
+}
+
+
diff --git a/fluid/widget_browser.h b/fluid/widget_browser.h
new file mode 100644
index 000000000..c00d45052
--- /dev/null
+++ b/fluid/widget_browser.h
@@ -0,0 +1,62 @@
+//
+// Widget Browser code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2021 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_WIDGET_BROWSER_H
+#define _FLUID_WIDGET_BROWSER_H
+
+#include <FL/Fl_Browser_.H>
+
+class Fl_Type;
+class Widget_Browser;
+
+extern Widget_Browser *widget_browser;
+
+extern void redraw_browser();
+extern Fl_Widget *make_widget_browser(int x,int y,int w,int h);
+extern void redraw_widget_browser(Fl_Type *caller);
+extern void select(Fl_Type *o, int v);
+extern void select_only(Fl_Type *o);
+extern void deselect();
+extern void reveal_in_browser(Fl_Type *t);
+
+class Widget_Browser : public Fl_Browser_
+{
+ friend class Fl_Type;
+
+ static void callback_stub(Fl_Widget *o, void *) {
+ ((Widget_Browser *)o)->callback();
+ }
+
+ Fl_Type* pushedtitle;
+
+ // required routines for Fl_Browser_ subclass:
+ void *item_first() const ;
+ void *item_next(void *) const ;
+ void *item_prev(void *) const ;
+ int item_selected(void *) const ;
+ void item_select(void *,int);
+ int item_width(void *) const ;
+ int item_height(void *) const ;
+ void item_draw(void *,int,int,int,int) const ;
+ int incr_height() const ;
+
+public:
+ int handle(int);
+ void callback();
+ Widget_Browser(int,int,int,int,const char * =0);
+};
+
+#endif // _FLUID_WIDGET_BROWSER_H
diff --git a/fluid/widget_panel.cxx b/fluid/widget_panel.cxx
index 30bb686ec..31cf0ebd2 100644
--- a/fluid/widget_panel.cxx
+++ b/fluid/widget_panel.cxx
@@ -17,7 +17,7 @@
// generated by Fast Light User Interface Designer (fluid) version 1.0400
#include "widget_panel.h"
-extern void comment_cb(Fl_Text_Editor*, void*);
+#include "Fl_Widget_Type.h"
static void cb_(Fl_Tabs* o, void* v) {
propagate_load((Fl_Group *)o,v);
diff --git a/fluid/widget_panel.fl b/fluid/widget_panel.fl
index 38a5b34e8..7b29fd4ab 100644
--- a/fluid/widget_panel.fl
+++ b/fluid/widget_panel.fl
@@ -20,7 +20,7 @@ comment {//
} {in_source in_header
}
-decl {extern void comment_cb(Fl_Text_Editor*, void*);} {private global
+decl {\#include "Fl_Widget_Type.h"} {selected private global
}
Function {make_widget_panel()} {
@@ -28,8 +28,8 @@ Function {make_widget_panel()} {
} {
Fl_Window {} {
comment {Use a Double Window to avoid flickering.} open
- xywh {560 60 420 400} type Double labelsize 11 align 80 hide resizable hotspot
- code0 {o->size_range(o->w(), o->h());} size_range {420 400 0 0}
+ xywh {500 209 420 400} type Double labelsize 11 align 80 resizable hotspot
+ code0 {o->size_range(o->w(), o->h());} size_range {420 400 0 0} visible
} {
Fl_Tabs {} {
callback {propagate_load((Fl_Group *)o,v);} open
@@ -37,7 +37,7 @@ Function {make_widget_panel()} {
} {
Fl_Group {} {
label GUI
- callback propagate_load open
+ callback propagate_load
xywh {10 30 400 330} labelsize 11 when 0 resizable
} {
Fl_Group {} {
@@ -46,7 +46,7 @@ Function {make_widget_panel()} {
xywh {95 40 309 20} labelfont 1 labelsize 11 align 4
} {
Fl_Input {} {
- callback label_cb selected
+ callback label_cb
tooltip {The label text for the widget.
Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 1 textsize 11 resizable
}
@@ -664,7 +664,7 @@ wCallback->do_callback(wCallback, v);} open
}
}
}
- Fl_Group {} {open
+ Fl_Group {} {
xywh {10 370 400 20} labelsize 11
} {
Fl_Box {} {