summaryrefslogtreecommitdiff
path: root/fluid/tools
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2025-03-16 17:16:12 -0400
committerGitHub <noreply@github.com>2025-03-16 17:16:12 -0400
commit51a55bc73660f64e8f4b32b8b4d3858f2a786f7b (patch)
tree122ad9f838fcf8f61ed7cf5fa031e8ed69817e10 /fluid/tools
parent13a7073a1e007ce5b71ef70bced1a9b15158820d (diff)
Fluid: restructuring and rejuvenation of the source code.
* Add classes for application and project * Removed all globals from Fluid.h * Extracting args and project history into their own classes * Moving globals into Application class * Initialize values inside headers for some classes. * Undo functionality wrapped in a class inside Project. * File reader and writer are now linked to a project. * Avoid global project access * Nodes (former Types) will be managed by a new Tree class. * Removed static members (hidden globals) form Node/Fl_Type. * Adding Tree iterator. * Use nullptr instead of 0, NULL, or 0L * Renamed Fl_..._Type to ..._Node, FL_OVERRIDE -> override * Renaming ..._type to ...::prototype * Splitting Widget Panel into multiple files. * Moved callback code into widget panel file. * Cleaning up Fluid_Image -> Image_asset * Moving Fd_Snap_Action into new namespace fld::app::Snap_Action etc. * Moved mergeback into proj folder. * `enum ID` is now `enum class Type`.
Diffstat (limited to 'fluid/tools')
-rw-r--r--fluid/tools/ExternalCodeEditor_UNIX.cxx76
-rw-r--r--fluid/tools/ExternalCodeEditor_UNIX.h4
-rw-r--r--fluid/tools/ExternalCodeEditor_WIN32.cxx92
-rw-r--r--fluid/tools/ExternalCodeEditor_WIN32.h2
-rw-r--r--fluid/tools/autodoc.cxx64
-rw-r--r--fluid/tools/autodoc.h2
-rw-r--r--fluid/tools/filename.cxx32
-rw-r--r--fluid/tools/filename.h5
8 files changed, 154 insertions, 123 deletions
diff --git a/fluid/tools/ExternalCodeEditor_UNIX.cxx b/fluid/tools/ExternalCodeEditor_UNIX.cxx
index bf472d896..9e9ffd00e 100644
--- a/fluid/tools/ExternalCodeEditor_UNIX.cxx
+++ b/fluid/tools/ExternalCodeEditor_UNIX.cxx
@@ -5,8 +5,8 @@
#include "ExternalCodeEditor_UNIX.h"
-#include "app/fluid.h"
-#include "app/project.h"
+#include "Fluid.h"
+#include "Project.h"
#include <FL/Fl.H> /* Fl_Timeout_Handler.. */
#include <FL/fl_ask.H> /* fl_alert() */
@@ -23,9 +23,11 @@
#include <stdlib.h> /* free().. */
#include <stdio.h> /* snprintf().. */
+using namespace fld;
+
// 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
+static Fl_Timeout_Handler L_update_timer_cb = nullptr; // app's update timer callback
// [Static/Local] See if file exists
static int is_file(const char *filename) {
@@ -57,7 +59,7 @@ static int is_dir(const char *dirname) {
*/
ExternalCodeEditor::ExternalCodeEditor() {
pid_ = -1;
- filename_ = 0;
+ filename_ = nullptr;
file_mtime_ = 0;
file_size_ = 0;
alert_pipe_[0] = alert_pipe_[1] = -1;
@@ -69,11 +71,11 @@ ExternalCodeEditor::ExternalCodeEditor() {
This also closes the external editor.
*/
ExternalCodeEditor::~ExternalCodeEditor() {
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("ExternalCodeEditor() DTOR CALLED (this=%p, pid=%ld)\n",
(void*)this, (long)pid_);
close_editor(); // close editor, delete tmp file
- set_filename(0); // free()s filename
+ set_filename(nullptr); // free()s filename
if (alert_pipe_open_) {
Fl::remove_fd(alert_pipe_[0]);
@@ -85,12 +87,12 @@ ExternalCodeEditor::~ExternalCodeEditor() {
/**
Set the filename for the file we wish to edit.
Handles memory allocation/free.
- If set to NULL, frees memory.
+ If set to nullptr, 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;
+ filename_ = val ? fl_strdup(val) : nullptr;
}
/**
@@ -105,7 +107,7 @@ int ExternalCodeEditor::is_editing() {
Wait for editor to close
*/
void ExternalCodeEditor::close_editor() {
- if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pid_));
+ if ( Fluid.debug_external_editor ) printf("close_editor() called: pid=%ld\n", long(pid_));
// Wait until editor is closed + reaped
while ( is_editing() ) {
switch ( reap_editor() ) {
@@ -119,7 +121,7 @@ void ExternalCodeEditor::close_editor() {
switch ( fl_choice("Please close external editor\npid=%ld file=%s",
"Force Close", // button 0
"Closed", // button 1
- 0, // button 2
+ nullptr, // button 2
long(pid_), filename() ) ) {
case 0: // Force Close
kill_editor();
@@ -141,7 +143,7 @@ void ExternalCodeEditor::close_editor() {
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 ( Fluid.debug_external_editor ) printf("kill_editor() called: pid=%ld\n", (long)pid_);
if ( !is_editing() ) return; // editor not running? return..
kill(pid_, SIGTERM); // kill editor
int wcount = 0;
@@ -164,7 +166,7 @@ void ExternalCodeEditor::kill_editor() {
}
continue;
case 1: // process reaped (reap_editor() sets pid_ to -1)
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("*** REAPED KILLED EXTERNAL EDITOR: PID %ld\n", (long)pid_reaped);
break;
}
@@ -185,7 +187,7 @@ void ExternalCodeEditor::kill_editor() {
\return -1 error getting file info (strerror() has reason)
*/
int ExternalCodeEditor::handle_changes(const char **code, int force) {
- code[0] = 0;
+ code[0] = nullptr;
if ( !is_editing() ) return 0;
// Get current time/size info, see if file changed
int changed = 0;
@@ -239,13 +241,13 @@ int ExternalCodeEditor::remove_tmpfile() {
if ( !tmpfile ) return 0;
// Filename set? remove (if exists) and zero filename/mtime/size
if ( is_file(tmpfile) ) {
- if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile);
+ if ( Fluid.debug_external_editor ) printf("Removing tmpfile '%s'\n", tmpfile);
if ( remove(tmpfile) < 0 ) {
fl_alert("WARNING: Can't remove() '%s': %s", tmpfile, strerror(errno));
return -1;
}
}
- set_filename(0);
+ set_filename(nullptr);
file_mtime_ = 0;
file_size_ = 0;
return 1;
@@ -268,7 +270,7 @@ const char* ExternalCodeEditor::tmpdir_name() {
void ExternalCodeEditor::tmpdir_clear() {
const char *tmpdir = tmpdir_name();
if ( is_dir(tmpdir) ) {
- if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir);
+ if ( Fluid.debug_external_editor ) printf("Removing tmpdir '%s'\n", tmpdir);
if ( rmdir(tmpdir) < 0 ) {
fl_alert("WARNING: Can't rmdir() '%s': %s", tmpdir, strerror(errno));
}
@@ -278,7 +280,7 @@ void ExternalCodeEditor::tmpdir_clear() {
/**
Creates temp dir (if doesn't exist) and returns the dirname
as a static string.
- \return NULL on error, dialog shows reason.
+ \return nullptr on error, dialog shows reason.
*/
const char* ExternalCodeEditor::create_tmpdir() {
const char *dirname = tmpdir_name();
@@ -286,7 +288,7 @@ const char* ExternalCodeEditor::create_tmpdir() {
if ( mkdir(dirname, 0777) < 0 ) {
fl_alert("can't create directory '%s': %s",
dirname, strerror(errno));
- return NULL;
+ return nullptr;
}
}
return dirname;
@@ -294,13 +296,13 @@ const char* ExternalCodeEditor::create_tmpdir() {
/**
Returns temp filename in static buffer.
- \return NULL if can't, posts dialog explaining why.
+ \return nullptr if can't, posts dialog explaining why.
*/
const char* ExternalCodeEditor::tmp_filename() {
static char path[FL_PATH_MAX+1];
const char *tmpdir = create_tmpdir();
- if ( !tmpdir ) return 0;
- const char *ext = g_project.code_file_name.c_str(); // e.g. ".cxx"
+ if ( !tmpdir ) return nullptr;
+ const char *ext = Fluid.proj.code_file_name.c_str(); // e.g. ".cxx"
snprintf(path, FL_PATH_MAX, "%s/%p%s", tmpdir, (void*)this, ext);
path[FL_PATH_MAX] = 0;
return path;
@@ -308,12 +310,12 @@ const char* ExternalCodeEditor::tmp_filename() {
/**
Save string 'code' to 'filename', returning file's mtime/size.
- 'code' can be NULL -- writes an empty file if so.
+ 'code' can be nullptr -- 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) {
- if ( code == 0 ) code = ""; // NULL? write an empty file
+ if ( code == nullptr ) code = ""; // nullptr? write an empty file
int fd = open(filename, O_WRONLY|O_CREAT, 0666);
if ( fd == -1 ) {
fl_alert("ERROR: open() '%s': %s", filename, strerror(errno));
@@ -336,7 +338,7 @@ static int save_file(const char *filename, const char *code) {
/**
Convert string 's' to array of argv[], useful for execve().
- - 's' will be modified (words will be NULL separated)
+ - 's' will be modified (words will be nullptr 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
@@ -346,14 +348,14 @@ static int make_args(char *s, // string containing words (gets trashed!)
int *aargc, // pointer to argc
char ***aargv) { // pointer to argv
char *ss, **argv;
- if ((argv=(char**)malloc(sizeof(char*) * (strlen(s)/2)))==NULL) {
+ if ((argv=(char**)malloc(sizeof(char*) * (strlen(s)/2)))==nullptr) {
return -1;
}
int t;
- for(t=0; (t==0)?(ss=strtok(s," \t")):(ss=strtok(0," \t")); t++) {
+ for(t=0; (t==0)?(ss=strtok(s," \t")):(ss=strtok(nullptr," \t")); t++) {
argv[t] = ss;
}
- argv[t] = 0;
+ argv[t] = nullptr;
aargv[0] = argv;
aargc[0] = t;
return(t);
@@ -383,7 +385,7 @@ void ExternalCodeEditor::open_alert_pipe() {
*/
int ExternalCodeEditor::start_editor(const char *editor_cmd,
const char *filename) {
- if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n",
+ if ( Fluid.debug_external_editor ) printf("start_editor() cmd='%s', filename='%s'\n",
editor_cmd, filename);
char cmd[1024];
snprintf(cmd, sizeof(cmd), "%s %s", editor_cmd, filename);
@@ -399,7 +401,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd,
// NOTE: no FLTK calls after a fork. Use a pipe to tell the app if the
// command can't launch
int nargs;
- char **args = 0;
+ char **args = nullptr;
if (make_args(cmd, &nargs, &args) > 0) {
execvp(args[0], args); // run command - doesn't return if succeeds
if (alert_pipe_open_) {
@@ -416,7 +418,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd,
default: // parent
if ( L_editors_open++ == 0 ) // first editor? start timers
{ start_update_timer(); }
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("--- EDITOR STARTED: pid_=%ld #open=%d\n", (long)pid_, L_editors_open);
break;
}
@@ -426,7 +428,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd,
/**
Try to reap external editor process.
- If 'pid_reaped' not NULL, returns PID of reaped editor.
+ If 'pid_reaped' not nullptr, returns PID of reaped editor.
\return -2: editor not open
\return -1: waitpid() failed (errno has reason)
@@ -453,7 +455,7 @@ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) {
{ stop_update_timer(); }
break;
}
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("*** EDITOR REAPED: pid=%ld #open=%d\n", long(wpid), L_editors_open);
return 1;
}
@@ -462,7 +464,7 @@ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) {
Open external editor using 'editor_cmd' to edit 'code'.
'code' contains multiline code to be edited as a temp file.
- 'code' can be NULL -- edits an empty file if so.
+ 'code' can be nullptr -- edits an empty file if so.
\return 0 if succeeds
\return -1 if can't open editor (already open, etc),
@@ -492,7 +494,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
filename(), (long)pid_);
return 0;
case 1: // process reaped, wpid is pid reaped
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", (long)wpid);
break; // fall thru to open new editor instance
}
@@ -512,7 +514,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
file_mtime_ = sbuf.st_mtime;
file_size_ = sbuf.st_size;
if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor
- if ( G_debug ) printf("Editor failed to start\n");
+ if ( Fluid.debug_external_editor ) printf("Editor failed to start\n");
return -1; // errors were shown in dialog
}
return 0;
@@ -523,7 +525,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
*/
void ExternalCodeEditor::start_update_timer() {
if ( !L_update_timer_cb ) return;
- if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n");
+ if ( Fluid.debug_external_editor ) printf("--- TIMER: STARTING UPDATES\n");
Fl::add_timeout(2.0, L_update_timer_cb);
}
@@ -532,7 +534,7 @@ void ExternalCodeEditor::start_update_timer() {
*/
void ExternalCodeEditor::stop_update_timer() {
if ( !L_update_timer_cb ) return;
- if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n");
+ if ( Fluid.debug_external_editor ) printf("--- TIMER: STOPPING UPDATES\n");
Fl::remove_timeout(L_update_timer_cb);
}
diff --git a/fluid/tools/ExternalCodeEditor_UNIX.h b/fluid/tools/ExternalCodeEditor_UNIX.h
index 644f22afa..2142d5a10 100644
--- a/fluid/tools/ExternalCodeEditor_UNIX.h
+++ b/fluid/tools/ExternalCodeEditor_UNIX.h
@@ -7,7 +7,7 @@
#ifndef _EXTCODEEDITOR_H
#define _EXTCODEEDITOR_H
-#include "app/fluid.h"
+#include "Fluid.h"
#include <FL/Fl.H>
@@ -42,7 +42,7 @@ public:
ExternalCodeEditor();
~ExternalCodeEditor();
int is_editing();
- int reap_editor(pid_t *pid_reaped=NULL);
+ int reap_editor(pid_t *pid_reaped=nullptr);
void close_editor();
const char *filename() { return filename_; }
int open_editor(const char *editor_cmd, const char *code);
diff --git a/fluid/tools/ExternalCodeEditor_WIN32.cxx b/fluid/tools/ExternalCodeEditor_WIN32.cxx
index 09688d16a..64d791400 100644
--- a/fluid/tools/ExternalCodeEditor_WIN32.cxx
+++ b/fluid/tools/ExternalCodeEditor_WIN32.cxx
@@ -17,8 +17,8 @@
// Note: This entire file Windows only.
#include "tools/ExternalCodeEditor_WIN32.h"
-#include "app/fluid.h"
-#include "app/project.h"
+#include "Fluid.h"
+#include "Project.h"
#include <FL/Fl.H> // Fl_Timeout_Handler..
#include <FL/fl_ask.H> // fl_alert()
@@ -28,17 +28,17 @@
#include <stdio.h> // snprintf()
#include <stdlib.h>
-extern int G_debug; // defined in fluid.cxx
+using namespace fld;
// 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
-static wchar_t *wbuf = NULL;
-static char *abuf = NULL;
+static wchar_t *wbuf = nullptr;
+static char *abuf = nullptr;
static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) {
unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8);
- unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length
+ unsigned wn = fl_utf8toUtf16(utf8, len, nullptr, 0) + 1; // Query length
wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn);
wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string
wbuf[wn] = 0;
@@ -47,7 +47,7 @@ static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) {
static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) {
unsigned len = (unsigned)wcslen(wstr);
- unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length
+ unsigned wn = fl_utf8fromwc(nullptr, 0, wstr, len) + 1; // query length
utf8 = (char *)realloc(utf8, wn);
wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string
utf8[wn] = 0;
@@ -68,7 +68,7 @@ static const char *get_ms_errmsg() {
DWORD msize = 0;
// Get error message from Windows
- msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, NULL);
+ msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, nullptr);
if ( msize == 0 ) {
_snprintf(emsg, sizeof(emsg), "Error #%ld", (unsigned long)lastErr);
} else {
@@ -119,7 +119,7 @@ ExternalCodeEditor::~ExternalCodeEditor() {
}
// [Protected] Set the filename. Handles memory allocation/free
-// If set to NULL, frees memory.
+// If set to nullptr, frees memory.
//
void ExternalCodeEditor::set_filename(const char *val) {
if ( filename_ ) free((void*)filename_);
@@ -137,7 +137,7 @@ static BOOL CALLBACK terminate_app_enum(HWND hwnd, LPARAM lParam) {
GetWindowThreadProcessId(hwnd, &dwID);
if (dwID == (DWORD)lParam) {
PostMessage(hwnd, WM_CLOSE, 0, 0);
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("terminate_app_enum() sends WIN_CLOSE to hwnd=%p\n", (void*)hwnd);
}
return TRUE;
@@ -154,12 +154,12 @@ static int terminate_app(DWORD pid, DWORD msecTimeout) {
// Wait on handle. If it closes, great. If it times out, use TerminateProcess()
int ret = 0;
if ( WaitForSingleObject(hProc, msecTimeout) != WAIT_OBJECT_0 ) {
- if ( G_debug ) {
+ if ( Fluid.debug_external_editor ) {
printf("WARNING: sent WIN_CLOSE, but timeout after %ld msecs.."
"trying TerminateProcess\n", msecTimeout);
}
if ( TerminateProcess(hProc, 0) == 0 ) {
- if ( G_debug ) {
+ if ( Fluid.debug_external_editor ) {
printf("ERROR: TerminateProcess() for pid=%ld failed: %s\n",
long(pid), get_ms_errmsg());
}
@@ -176,7 +176,7 @@ static int terminate_app(DWORD pid, DWORD msecTimeout) {
// [Protected] Wait for editor to close
void ExternalCodeEditor::close_editor() {
- if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pinfo_.dwProcessId));
+ if ( Fluid.debug_external_editor ) printf("close_editor() called: pid=%ld\n", long(pinfo_.dwProcessId));
// Wait until editor is closed + reaped
while ( is_editing() ) {
switch ( reap_editor() ) {
@@ -210,7 +210,7 @@ void ExternalCodeEditor::close_editor() {
// The dtor calls this to ensure no editors remain running when fluid exits.
//
void ExternalCodeEditor::kill_editor() {
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("kill_editor() called: pid=%ld\n", (long)pinfo_.dwProcessId);
if ( !is_editing() ) return;
switch ( terminate_app(pinfo_.dwProcessId, 500) ) { // kill editor, wait up to 1/2 sec to die
@@ -222,7 +222,7 @@ void ExternalCodeEditor::kill_editor() {
case 0: { // success -- process reaped
DWORD pid = pinfo_.dwProcessId; // save pid
reap_cleanup(); // clears pinfo_
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("*** kill_editor() REAP pid=%ld #open=%ld\n",
long(pid), long(L_editors_open));
break;
@@ -252,10 +252,10 @@ int ExternalCodeEditor::handle_changes(const char **code, int force) {
HANDLE fh = CreateFileW(wbuf, // file to read
GENERIC_READ, // reading only
FILE_SHARE_READ, // sharing -- allow read share; just getting file size
- NULL, // security
+ nullptr, // security
OPEN_EXISTING, // create flags -- must exist
0, // misc flags
- NULL); // templates
+ nullptr); // templates
if ( fh == INVALID_HANDLE_VALUE ) return -1;
LARGE_INTEGER fsize;
// Get file size
@@ -315,18 +315,18 @@ int ExternalCodeEditor::handle_changes(const char **code, int force) {
//
int ExternalCodeEditor::remove_tmpfile() {
const char *tmpfile = filename();
- if ( G_debug ) printf("remove_tmpfile() '%s'\n", tmpfile ? tmpfile : "(empty)");
+ if ( Fluid.debug_external_editor ) printf("remove_tmpfile() '%s'\n", tmpfile ? tmpfile : "(empty)");
if ( !tmpfile ) return 0;
// Filename set? remove (if exists) and zero filename/mtime/size
if ( is_file(tmpfile) ) {
- if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile);
+ if ( Fluid.debug_external_editor ) printf("Removing tmpfile '%s'\n", tmpfile);
utf8_to_wchar(tmpfile, wbuf);
if (DeleteFileW(wbuf) == 0) {
fl_alert("WARNING: Can't DeleteFile() '%s': %s", tmpfile, get_ms_errmsg());
return -1;
}
} else {
- if ( G_debug ) printf("remove_tmpfile(): is_file(%s) failed\n", tmpfile);
+ if ( Fluid.debug_external_editor ) printf("remove_tmpfile(): is_file(%s) failed\n", tmpfile);
}
set_filename(0);
memset(&file_mtime_, 0, sizeof(file_mtime_));
@@ -348,7 +348,7 @@ const char* ExternalCodeEditor::tmpdir_name() {
static char dirname[100];
_snprintf(dirname, sizeof(dirname), "%s.fluid-%ld",
tempdir, (long)GetCurrentProcessId());
- if ( G_debug ) printf("tmpdir_name(): '%s'\n", dirname);
+ if ( Fluid.debug_external_editor ) printf("tmpdir_name(): '%s'\n", dirname);
return dirname;
}
@@ -358,7 +358,7 @@ const char* ExternalCodeEditor::tmpdir_name() {
void ExternalCodeEditor::tmpdir_clear() {
const char *tmpdir = tmpdir_name();
if ( is_dir(tmpdir) ) {
- if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir);
+ if ( Fluid.debug_external_editor ) printf("Removing tmpdir '%s'\n", tmpdir);
utf8_to_wchar(tmpdir, wbuf);
if ( RemoveDirectoryW(wbuf) == 0 ) {
fl_alert("WARNING: Can't RemoveDirectory() '%s': %s",
@@ -368,7 +368,7 @@ 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.
+// as a static string. Returns nullptr on error, dialog shows reason.
//
const char* ExternalCodeEditor::create_tmpdir() {
const char *dirname = tmpdir_name();
@@ -377,27 +377,27 @@ const char* ExternalCodeEditor::create_tmpdir() {
if (CreateDirectoryW(wbuf, 0) == 0) {
fl_alert("can't create directory '%s': %s",
dirname, get_ms_errmsg());
- return NULL;
+ return nullptr;
}
}
return dirname;
}
// [Protected] Returns temp filename in static buffer.
-// Returns NULL if can't, posts dialog explaining why.
+// Returns nullptr 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;
- const char *ext = g_project.code_file_name.c_str(); // e.g. ".cxx"
+ const char *ext = Fluid.proj.code_file_name.c_str(); // 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.
+// 'code' can be nullptr -- writes an empty file if so.
// Returns:
// 0 on success
// -1 on error (posts dialog with reason)
@@ -406,17 +406,17 @@ static int save_file(const char *filename,
const char *code,
FILETIME &file_mtime, // return these since in win32 it's..
LARGE_INTEGER &file_size) { // ..efficient to get while file open
- if ( code == 0 ) code = ""; // NULL? write an empty file
+ if ( code == 0 ) code = ""; // nullptr? write an empty file
memset(&file_mtime, 0, sizeof(file_mtime));
memset(&file_size, 0, sizeof(file_size));
utf8_to_wchar(filename, wbuf);
HANDLE fh = CreateFileW(wbuf, // filename
GENERIC_WRITE, // write only
0, // sharing -- no share during write
- NULL, // security
+ nullptr, // security
CREATE_ALWAYS, // create flags -- recreate
FILE_ATTRIBUTE_NORMAL, // misc flags
- NULL); // templates
+ nullptr); // templates
if ( fh == INVALID_HANDLE_VALUE ) {
fl_alert("ERROR: couldn't create file '%s': %s",
filename, get_ms_errmsg());
@@ -426,7 +426,7 @@ static int save_file(const char *filename,
DWORD clen = (DWORD)strlen(code);
DWORD count = 0;
int ret = 0;
- if ( WriteFile(fh, code, clen, &count, NULL) == 0 ) {
+ if ( WriteFile(fh, code, clen, &count, nullptr) == 0 ) {
fl_alert("ERROR: WriteFile() '%s': %s", filename, get_ms_errmsg());
ret = -1; // fallthru to CloseHandle()
} else if ( count != clen ) {
@@ -459,7 +459,7 @@ static int save_file(const char *filename,
//
int ExternalCodeEditor::start_editor(const char *editor_cmd,
const char *filename) {
- if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n",
+ if ( Fluid.debug_external_editor ) printf("start_editor() cmd='%s', filename='%s'\n",
editor_cmd, filename);
// Startup info
STARTUPINFOW sinfo;
@@ -474,14 +474,14 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd,
_snprintf(cmd, sizeof(cmd), "%s %s", editor_cmd, filename);
utf8_to_wchar(cmd, wbuf);
// Start editor process
- if (CreateProcessW(NULL, // app name
+ if (CreateProcessW(nullptr, // app name
wbuf, // command to exec
- NULL, // secure attribs
- NULL, // thread secure attribs
+ nullptr, // secure attribs
+ nullptr, // thread secure attribs
FALSE, // handle inheritance
0, // creation flags
- NULL, // environ block
- NULL, // current dir
+ nullptr, // environ block
+ nullptr, // current dir
&sinfo, // startup info
&pinfo_) == 0 ) { // process info
fl_alert("CreateProcess() failed to start '%s': %s",
@@ -490,7 +490,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd,
}
if ( L_editors_open++ == 0 ) // first editor? start timers
{ start_update_timer(); }
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("--- EDITOR STARTED: pid_=%ld #open=%d\n",
(long)pinfo_.dwProcessId, L_editors_open);
return 0;
@@ -512,7 +512,7 @@ void ExternalCodeEditor::reap_cleanup() {
}
// [Public] Try to reap external editor process
-// If 'pid_reaped' not NULL, returns PID of reaped editor.
+// If 'pid_reaped' not nullptr, returns PID of reaped editor.
// Returns:
// -2 -- editor not open
// -1 -- WaitForSingleObject() failed (get_ms_errmsg() has reason)
@@ -534,7 +534,7 @@ int ExternalCodeEditor::reap_editor(DWORD *pid_reaped) {
DWORD wpid = pinfo_.dwProcessId; // save pid
reap_cleanup(); // clears pinfo_
if ( pid_reaped ) *pid_reaped = wpid; // return pid to caller
- if ( G_debug ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n",
+ if ( Fluid.debug_external_editor ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n",
long(wpid), L_editors_open);
return 1;
}
@@ -548,7 +548,7 @@ int ExternalCodeEditor::reap_editor(DWORD *pid_reaped) {
// [Public] Open external editor using 'editor_cmd' to edit 'code'.
//
// 'code' contains multiline code to be edited as a temp file.
-// 'code' can be NULL -- edits an empty file if so.
+// 'code' can be nullptr -- edits an empty file if so.
//
// Returns:
// 0 if succeeds
@@ -579,7 +579,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
filename(), long(pinfo_.dwProcessId));
return 0;
case 1: // process reaped, wpid is pid reaped
- if ( G_debug )
+ if ( Fluid.debug_external_editor )
printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", long(wpid));
break; // fall thru to open new editor instance
}
@@ -592,12 +592,12 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
return -1; // errors were shown in dialog
}
if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor
- if ( G_debug ) printf("Editor failed to start\n");
+ if ( Fluid.debug_external_editor ) printf("Editor failed to start\n");
return -1; // errors were shown in dialog
}
// New editor opened -- start update timer (if not already)
if ( L_update_timer_cb && !Fl::has_timeout(L_update_timer_cb) ) {
- if ( G_debug ) printf("--- Editor opened: STARTING UPDATE TIMER\n");
+ if ( Fluid.debug_external_editor ) printf("--- Editor opened: STARTING UPDATE TIMER\n");
Fl::add_timeout(2.0, L_update_timer_cb);
}
return 0;
@@ -606,14 +606,14 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
// [Public/Static] Start update timer
void ExternalCodeEditor::start_update_timer() {
if ( !L_update_timer_cb ) return;
- if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n");
+ if ( Fluid.debug_external_editor ) printf("--- TIMER: STARTING UPDATES\n");
Fl::add_timeout(2.0, L_update_timer_cb);
}
// [Public/Static] Stop update timer
void ExternalCodeEditor::stop_update_timer() {
if ( !L_update_timer_cb ) return;
- if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n");
+ if ( Fluid.debug_external_editor ) printf("--- TIMER: STOPPING UPDATES\n");
Fl::remove_timeout(L_update_timer_cb);
}
diff --git a/fluid/tools/ExternalCodeEditor_WIN32.h b/fluid/tools/ExternalCodeEditor_WIN32.h
index 97d93e495..83c50a742 100644
--- a/fluid/tools/ExternalCodeEditor_WIN32.h
+++ b/fluid/tools/ExternalCodeEditor_WIN32.h
@@ -43,7 +43,7 @@ public:
ExternalCodeEditor();
~ExternalCodeEditor();
int is_editing();
- int reap_editor(DWORD *pid_reaped=NULL);
+ int reap_editor(DWORD *pid_reaped=nullptr);
void close_editor();
const char *filename() { return filename_; }
int open_editor(const char *editor_cmd, const char *code);
diff --git a/fluid/tools/autodoc.cxx b/fluid/tools/autodoc.cxx
index 295ab8d2f..c87b59bc2 100644
--- a/fluid/tools/autodoc.cxx
+++ b/fluid/tools/autodoc.cxx
@@ -18,11 +18,11 @@
#include "tools/autodoc.h"
-#include "app/fluid.h"
-#include "app/project.h"
+#include "Fluid.h"
+#include "Project.h"
#include "nodes/factory.h"
-#include "nodes/Fl_Widget_Type.h"
-#include "nodes/Fl_Window_Type.h"
+#include "nodes/Widget_Node.h"
+#include "nodes/Window_Node.h"
#include "panels/widget_panel.h"
#include "panels/function_panel.h"
#include "panels/settings_panel.h"
@@ -232,7 +232,7 @@ void blend_alpha_bottom(const Fl_RGB_Image *img, int dy) {
created in FLTK resolution, even if the screen uses a higher resolution.
\param[in] filename the snapshot will be written to this file in png format
- \param[in] w draw a bounding box around all widgets in the NULL terminated list
+ \param[in] w draw a bounding box around all widgets in the nullptr terminated list
\param[in] frame add a margin around the bounding box
\param[in] blend add another margin around the bounding box that fades to full transparency
\param[in] scale scale everything by this factor before saving it
@@ -342,7 +342,7 @@ int fl_snapshot(const char *filename, Fl_Widget *w1, Fl_Widget *w2,
const Fl_Rect &blend,
double scale)
{
- Fl_Widget *ww[3] = { w1, w2, NULL };
+ Fl_Widget *ww[3] = { w1, w2, nullptr };
return fl_snapshot(filename, ww, frame, blend, scale);
}
@@ -363,7 +363,7 @@ int fl_snapshot(const char *filename, Fl_Widget *w,
const Fl_Rect &blend,
double scale)
{
- Fl_Widget *ww[2] = { w, NULL };
+ Fl_Widget *ww[2] = { w, nullptr };
return fl_snapshot(filename, ww, frame, blend, scale);
}
@@ -383,27 +383,27 @@ void run_autodoc(const std::string &target_dir) {
// Fl::scheme("gtk+");
// Create a silly project that contains all widgets that we want to document
- new_project(false);
+ Fluid.new_project(false);
- /*Fl_Type *t_func = */ add_new_widget_from_user("Function", Strategy::AS_LAST_CHILD, false);
- Fl_Window_Type *t_win = (Fl_Window_Type*)add_new_widget_from_user("Fl_Window", Strategy::AS_LAST_CHILD, false);
+ /*Node *t_func = */ add_new_widget_from_user("Function", Strategy::AS_LAST_CHILD, false);
+ Window_Node *t_win = (Window_Node*)add_new_widget_from_user("Fl_Window", Strategy::AS_LAST_CHILD, false);
t_win->label("My Main Window");
- Fl_Widget_Type *t_grp = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Group", Strategy::AS_LAST_CHILD, false);
+ Widget_Node *t_grp = (Widget_Node*)add_new_widget_from_user("Fl_Group", Strategy::AS_LAST_CHILD, false);
t_grp->public_ = 0;
- Fl_Widget_Type *t_btn = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false);
+ Widget_Node *t_btn = (Widget_Node*)add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false);
t_btn->comment("Don't press this button!");
t_btn->name("emergency_btn");
((Fl_Button*)t_btn->o)->shortcut(FL_COMMAND|'g');
- Fl_Type *t_sldr = add_new_widget_from_user("Fl_Slider", Strategy::AS_LAST_CHILD, false);
- Fl_Type *t_inp = add_new_widget_from_user("Fl_Input", Strategy::AS_LAST_CHILD, false);
- Fl_Type *t_flx = add_new_widget_from_user("Fl_Flex", Strategy::AS_LAST_CHILD, false);
- Fl_Type *t_flxc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false);
+ Node *t_sldr = add_new_widget_from_user("Fl_Slider", Strategy::AS_LAST_CHILD, false);
+ Node *t_inp = add_new_widget_from_user("Fl_Input", Strategy::AS_LAST_CHILD, false);
+ Node *t_flx = add_new_widget_from_user("Fl_Flex", Strategy::AS_LAST_CHILD, false);
+ Node *t_flxc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false);
select_only(t_grp);
- Fl_Type *t_grd = add_new_widget_from_user("Fl_Grid", Strategy::AS_LAST_CHILD, false);
- Fl_Type *t_grdc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false);
+ Node *t_grd = add_new_widget_from_user("Fl_Grid", Strategy::AS_LAST_CHILD, false);
+ Node *t_grdc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false);
widget_browser->rebuild();
- g_project.update_settings_dialog();
+ Fluid.proj.update_settings_dialog();
// TODO: FLUID overview
@@ -417,9 +417,9 @@ void run_autodoc(const std::string &target_dir) {
// explain menubar?
// explain widget browser
// explain widget browser entry
- main_window->size(350, 320);
- fl_snapshot((target_dir + "main_window.png").c_str(), main_window, win_margin, win_blend);
- fl_snapshot((target_dir + "main_menubar.png").c_str(), main_menubar, row_margin, row_blend);
+ Fluid.main_window->size(350, 320);
+ fl_snapshot((target_dir + "Fluid.main_window.png").c_str(), Fluid.main_window, win_margin, win_blend);
+ fl_snapshot((target_dir + "main_menubar.png").c_str(), Fluid.main_menubar, row_margin, row_blend);
fl_snapshot((target_dir + "main_browser.png").c_str(), widget_browser, FL_SNAP_AREA_CLEAR,
Fl_Rect(0, 30, FL_SNAP_TO_WINDOW, 100), row_blend, 2.0);
@@ -453,7 +453,7 @@ void run_autodoc(const std::string &target_dir) {
codeview_panel->show();
Fl::wait(0.2);
Fl::flush();
- update_codeview_cb(NULL, NULL); // must be visible on screen for this to work
+ update_codeview_cb(nullptr, nullptr); // must be visible on screen for this to work
cv_tab->value(cv_source_tab);
codeview_panel->redraw();
Fl::flush();
@@ -487,41 +487,41 @@ void run_autodoc(const std::string &target_dir) {
// ---- dialog types
// list and show all non-widget types and their respective dialog boxes
- // -- ID_Function
+ // -- Type::Function
Fl_Window *adoc_function_panel = make_function_panel();
f_name_input->value("count_trees(const char *forest_name)");
f_return_type_input->value("unsigned int");
fl_snapshot((target_dir + "function_panel.png").c_str(), adoc_function_panel, win_margin, win_blend);
adoc_function_panel->hide();
- // -- ID_Code
+ // -- Type::Code
Fl_Window *adoc_code_panel = make_code_panel();
code_input->buffer()->text("// increment user count\nif (new_user) {\n user_count++;\n}\n");
fl_snapshot((target_dir + "code_panel.png").c_str(), adoc_code_panel, win_margin, win_blend);
adoc_code_panel->hide();
- // -- ID_CodeBlock
+ // -- Type::CodeBlock
Fl_Window *adoc_codeblock_panel = make_codeblock_panel();
code_before_input->value("if (test())");
code_after_input->value("// test widgets added...");
fl_snapshot((target_dir + "codeblock_panel.png").c_str(), adoc_codeblock_panel, win_margin, win_blend);
adoc_codeblock_panel->hide();
- // -- ID_Decl
+ // -- Type::Decl
Fl_Window *adoc_decl_panel = make_decl_panel();
decl_class_choice->hide();
decl_input->buffer()->text("const char *damage = \"'tis but a scratch\";");
fl_snapshot((target_dir + "decl_panel.png").c_str(), adoc_decl_panel, win_margin, win_blend);
adoc_decl_panel->hide();
- // -- ID_DeclBlock
+ // -- Type::DeclBlock
Fl_Window *adoc_declblock_panel = make_declblock_panel();
declblock_before_input->value("#ifdef NDEBUG");
declblock_after_input->value("#endif // NDEBUG");
fl_snapshot((target_dir + "declblock_panel.png").c_str(), adoc_declblock_panel, win_margin, win_blend);
adoc_declblock_panel->hide();
- // -- ID_Class
+ // -- Type::Class
Fl_Window *adoc_class_panel = make_class_panel();
decl_class_choice->hide();
c_name_input->value("Zoo_Giraffe");
@@ -529,15 +529,15 @@ void run_autodoc(const std::string &target_dir) {
fl_snapshot((target_dir + "class_panel.png").c_str(), adoc_class_panel, win_margin, win_blend);
adoc_class_panel->hide();
- // -- ID_Widget_Class is handled like Fl_Window_Type
+ // -- Type::Widget_Class is handled like Window_Node
- // -- ID_Comment
+ // -- Type::Comment
Fl_Window *adoc_comment_panel = make_comment_panel();
comment_input->buffer()->text("Make sure that the giraffe gets enough hay,\nbut the monkey can't reach it.");
fl_snapshot((target_dir + "comment_panel.png").c_str(), adoc_comment_panel, win_margin, win_blend);
adoc_comment_panel->hide();
- // -- ID_Data
+ // -- Type::Data
Fl_Window *adoc_data_panel = make_data_panel();
data_class_choice->hide();
data_input->value("emulated_ROM");
diff --git a/fluid/tools/autodoc.h b/fluid/tools/autodoc.h
index 33b0bd6fc..136a7e119 100644
--- a/fluid/tools/autodoc.h
+++ b/fluid/tools/autodoc.h
@@ -1,5 +1,5 @@
//
-// Widget snapshot header-only file for the Fast Light Tool Kit (FLTK).
+// Self-generate snapshots of user interface for FLUID documentation.
//
// Copyright 2023-2025 by Bill Spitzak and others.
//
diff --git a/fluid/tools/filename.cxx b/fluid/tools/filename.cxx
index bbd749ce1..a5d6e22b3 100644
--- a/fluid/tools/filename.cxx
+++ b/fluid/tools/filename.cxx
@@ -1,7 +1,7 @@
//
-// Filename expansion routines for the Fast Light Tool Kit (FLTK).
+// Filename handling code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2023 by Bill Spitzak and others.
+// Copyright 1998-2025 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -95,3 +95,31 @@ std::string fl_filename_shortened(const std::string &filename, int max_chars) {
return homed_filename;
}
}
+
+/**
+ Make sure that a path name ends with a forward slash.
+ \param[in] str directory or path name
+ \return a new string, ending with a '/'
+ */
+std::string fld::end_with_slash(const std::string &str) {
+ char last = str[str.size()-1];
+ if (last !='/' && last != '\\')
+ return str + "/";
+ else
+ return str;
+}
+
+/**
+ Replace Windows '\\' directory separator with UNix '/' separators.
+ \param[in] fn a file path in Unix or Windows format
+ \return a copy of the file path in Unix format.
+ */
+std::string fld::fix_separators(const std::string &fn) {
+ std::string ret = fn;
+ for (size_t i=0; i<ret.size(); ++i) {
+ if (ret[i] == '\\') {
+ ret[i] = '/';
+ }
+ }
+ return ret;
+}
diff --git a/fluid/tools/filename.h b/fluid/tools/filename.h
index 13488d399..3a4359633 100644
--- a/fluid/tools/filename.h
+++ b/fluid/tools/filename.h
@@ -1,5 +1,5 @@
/*
- * Filename header file for the Fast Light Tool Kit (FLTK).
+ * Filename handling header file for the Fast Light Tool Kit (FLTK).
*
* Copyright 1998-2025 by Bill Spitzak and others.
*
@@ -27,7 +27,8 @@ std::string fl_filename_shortened(const std::string &filename, int maxchars);
namespace fld {
-using filename = std::string;
+extern std::string end_with_slash(const std::string &fn);
+extern std::string fix_separators(const std::string &fn);
} // namespace fld