Fluid: restructuring and commenting.

tl;dr : making Fluid maintainable, no changes in code execution and logic.

This is a pretty extensive restructuring of the Fluid source tree.
It was neccessary because source and header files were getting
much too big to handle. Many source files had no header, and many
headers declared functions that were in diffrent source files.

Reorganized much of the include statements.
Added comments to some of the files.
Added Doxygen configuration file for standalone Fluid docs.

Tested everything by rebuilding Fluid .fl designs with the resorted
version of Fluid.
This commit is contained in:
Matthias Melcher 2021-12-08 15:52:15 +01:00
parent 2d18c6f650
commit 16dae3ea06
51 changed files with 3836 additions and 2461 deletions

View File

@ -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
)

View File

@ -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();

View File

@ -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);
};
// ---- CodeViewer declaration
class CodeViewer : public CodeEditor {
public:
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();
};

View File

@ -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;
}

View File

@ -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();

View File

@ -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
/// Set a current class, so that the code of the children is generated correctly.
Fl_Class_Type *current_class = NULL;
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[];
/**
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;
}
extern int batch_mode;
extern void redraw_browser();
extern void goto_source_dir();
extern void leave_source_dir();
extern Fl_Window *main_window;
////////////////////////////////////////////////////////////////
// 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
int Fl_Function_Type::is_public() const {return public_;}
/** \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)
{ }
/**
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;
/**
Constructor.
*/
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);
}
/**
If this Type resides inside a class, this function returns the class type, or null.
Return 1 if this class is marked public.
*/
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;
int Fl_Class_Type::is_public() const {
return 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;

230
fluid/Fl_Function_Type.h Normal file
View File

@ -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

View File

@ -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) {

158
fluid/Fl_Group_Type.h Normal file
View File

@ -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

View File

@ -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);

212
fluid/Fl_Menu_Type.h Normal file
View File

@ -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

View File

@ -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.
/** \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 "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"
#include <FL/Fl.H>
#include <FL/Fl_Browser_.H>
#include <FL/fl_draw.H>
#include <stdlib.h>
#include "../src/flstring.h"
#include <stdlib.h>
#include <stdio.h>
#include "Fl_Type.h"
#include "undo.h"
// ---- global variables
#include "pixmaps.h"
Fl_Type *Fl_Type::first = NULL;
Fl_Type *Fl_Type::last = NULL;
extern int show_comments;
Fl_Type *in_this_only; // set if menu popped-up in window
////////////////////////////////////////////////////////////////
// ---- various functions
// 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
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;
}
if (*str) { // string was truncated
strcpy(p,"..."); p += 3;
}
if (quote) *p++ = '"'; // closing quote
*p = 0; // terminating null byte
return p;
}
////////////////////////////////////////////////////////////////
class Widget_Browser : public Fl_Browser_ {
friend class Fl_Type;
// 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);
};
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));
}
void redraw_widget_browser(Fl_Type *caller)
{
if (caller) {
widget_browser->display(caller);
}
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;
}
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();
}
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;
}
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,1,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);
}
}
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);
}
}
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;
}
void redraw_browser() {
widget_browser->redraw();
}
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();
for (Fl_Type *t = Fl_Type::first; t; t = t->next)
widget_browser->select(t,1,0);
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);
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);
}
// 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);
}
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;
}
}
// 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;
}
selection_changed(0);
}
// 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;
}
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;
}
}
// ---- 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);
@ -870,21 +485,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.
*/
@ -962,25 +562,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()'
@ -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() {
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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;

125
fluid/Fl_Window_Type.h Normal file
View File

@ -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

View File

@ -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();

View File

@ -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_;

View File

@ -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

View File

@ -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

View File

@ -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[] = {

View File

@ -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

View File

@ -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}
}

View File

@ -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

View File

@ -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

25
fluid/align_widget.h Normal file
View File

@ -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

View File

@ -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 {} {

View File

@ -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>

View File

@ -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>
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;
/// \defgroup cfile C Code File Operations
/// \{
// return true if c can be in a C identifier. I needed this so
// it is not messed up by locale settings:
static FILE *code_file = NULL;
static FILE *header_file = NULL;
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() {}
/// \}

44
fluid/code.h Normal file
View File

@ -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

View File

@ -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;

29
fluid/factory.h Normal file
View File

@ -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

View File

@ -19,21 +19,55 @@
// https://www.fltk.org/bugs.php
//
#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/fl_message.H>
#include "../src/flstring.h"
#include <stdio.h>
#include <stdlib.h>
#include "../src/flstring.h"
#include <stdarg.h>
#include "alignment_panel.h"
#include <FL/Fl.H>
#include <FL/fl_string.h>
#include "Fl_Widget_Type.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:
static FILE *fout;
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() {
}
}
}
/// \}

40
fluid/file.h Normal file
View File

@ -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

File diff suppressed because it is too large Load Diff

118
fluid/fluid.h Normal file
View File

@ -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

View File

@ -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.

View File

@ -20,40 +20,35 @@ comment {//
} {in_source in_header
}
decl {\#include <FL/Fl_Pixmap.H>} {private local
decl {\#include "fluid.h"} {private local
}
decl {\#include "pixmaps.h"} {private local
}
decl {\#include "factory.h"} {private local
}
decl {\#include "Fl_Type.h"} {private local
}
decl {\#include "widget_browser.h"} {selected private local
}
decl {\#include "undo.h"} {private local
}
decl {extern class Fl_Pixmap *pixmap[];} {private local
}
decl {extern class Fl_Type *Fl_Type_make(const char*);} {private local
}
decl {extern void select_only(Fl_Type*);} {private local
}
decl {extern void exit_cb(Fl_Widget*, void*);} {private global
}
decl {extern void toggle_widgetbin_cb(Fl_Widget*, void*);} {private global
}
Function {use_tab_navigation(int, Fl_Text_Editor*)} {
comment {Allow widget navigation on text fields with Tab.} private return_type int
} {
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]);}
}

View File

@ -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;

View File

@ -20,29 +20,26 @@ comment {//
} {in_source in_header
}
decl {\#include <stdio.h>} {private local
}
decl {\#include <stdlib.h>} {private local
}
decl {\#include "../src/flstring.h"} {private local
decl {\#include "fluid.h"} {selected private local
}
decl {\#include <FL/fl_string.h>} {private local
}
decl {\#include <FL/Fl_Preferences.H>} {private local
decl {\#include "../src/flstring.h"} {private local
}
decl {extern Fl_Preferences fluid_prefs;} {private local
decl {\#include <stdlib.h>} {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:}

234
fluid/shell_command.cxx Normal file
View File

@ -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();
}

67
fluid/shell_command.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -20,33 +20,33 @@ comment {//
} {in_source in_header
}
decl {\#include "fluid.h"} {private local
}
decl {\#include <FL/Fl_Shared_Image.H>} {private local
}
decl {\#include <FL/fl_ask.H>} {private local
}
decl {\#include <FL/fl_string.h>} {private local
}
decl {\#include <FL/filename.H>} {selected private local
}
decl {\#include "../src/flstring.h"} {private local
}
decl {\#include <stdio.h>} {private local
}
decl {\#include <stdlib.h>} {private local
}
decl {\#include "../src/flstring.h"} {private local
}
decl {\#include <FL/fl_string.h>} {private local
}
decl {\#include <errno.h>} {private local
}
decl {\#include <FL/filename.H>} {private local
}
decl {\#include <FL/fl_ask.H>} {private local
}
decl {\#include <FL/Fl_Shared_Image.H>} {private local
}
decl {\#include <FL/Fl_Preferences.H>} {private local
}
declblock {\#if defined(_WIN32) && !defined(__CYGWIN__)} {after {\#endif // _WIN32 && !__CYGWIN__}
} {
decl {\#include <io.h>} {private local
@ -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);} {}
}

View File

@ -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

View File

@ -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

507
fluid/widget_browser.cxx Normal file
View File

@ -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);
}

62
fluid/widget_browser.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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 {} {