summaryrefslogtreecommitdiff
path: root/fluid/ExternalCodeEditor_UNIX.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'fluid/ExternalCodeEditor_UNIX.cxx')
-rw-r--r--fluid/ExternalCodeEditor_UNIX.cxx230
1 files changed, 136 insertions, 94 deletions
diff --git a/fluid/ExternalCodeEditor_UNIX.cxx b/fluid/ExternalCodeEditor_UNIX.cxx
index c0f753550..8ff27d036 100644
--- a/fluid/ExternalCodeEditor_UNIX.cxx
+++ b/fluid/ExternalCodeEditor_UNIX.cxx
@@ -3,6 +3,14 @@
//
// Note: This entire file Unix only
+#include "ExternalCodeEditor_UNIX.h"
+
+#include "fluid.h"
+
+#include <FL/Fl.H> /* Fl_Timeout_Handler.. */
+#include <FL/fl_ask.H> /* fl_alert() */
+#include <FL/fl_string.h> /* fl_strdup() */
+
#include <errno.h> /* errno */
#include <string.h> /* strerror() */
#include <sys/types.h> /* stat().. */
@@ -14,14 +22,6 @@
#include <stdlib.h> /* free().. */
#include <stdio.h> /* snprintf().. */
-#include <FL/Fl.H> /* Fl_Timeout_Handler.. */
-#include <FL/fl_ask.H> /* fl_alert() */
-#include <FL/fl_string.h> /* fl_strdup() */
-
-#include "ExternalCodeEditor_UNIX.h"
-
-extern int G_debug; // defined in fluid.cxx
-
// Static local data
static int L_editors_open = 0; // keep track of #editors open
static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer callback
@@ -40,7 +40,20 @@ static int is_dir(const char *dirname) {
return(S_ISDIR(buf.st_mode) ? 1 : 0); // a dir?
}
-// CTOR
+// ---- ExternalCodeEditor implementation
+
+/** \class ExternalCodeEditor
+ Support for an external C++ code editor for Fluid Code block.
+
+ This class can launch and quit a user defined program for editiing
+ code outside of Fluid.
+ It observes changes in the external file and updates the Fluid
+ widget to stay synchronized.
+ */
+
+/**
+ Create the manager for external code editors.
+ */
ExternalCodeEditor::ExternalCodeEditor() {
pid_ = -1;
filename_ = 0;
@@ -48,7 +61,10 @@ ExternalCodeEditor::ExternalCodeEditor() {
file_size_ = 0;
}
-// DTOR
+/**
+ Destroy the manager.
+ This also closes the external editor.
+ */
ExternalCodeEditor::~ExternalCodeEditor() {
if ( G_debug )
printf("ExternalCodeEditor() DTOR CALLED (this=%p, pid=%ld)\n",
@@ -57,20 +73,28 @@ ExternalCodeEditor::~ExternalCodeEditor() {
set_filename(0); // free()s filename
}
-// [Protected] Set the filename. Handles memory allocation/free
-// If set to NULL, frees memory.
-//
+/**
+ Set the filename for the file we wish to edit.
+ Handles memory allocation/free.
+ If set to NULL, frees memory.
+ \param[in] val new filename
+ */
void ExternalCodeEditor::set_filename(const char *val) {
if ( filename_ ) free((void*)filename_);
filename_ = val ? fl_strdup(val) : 0;
}
-// [Public] Is editor running?
+/**
+ Is editor running?
+ \return 1 if we are currently editing a file.
+ */
int ExternalCodeEditor::is_editing() {
return( (pid_ != -1) ? 1 : 0 );
}
-// [Protected] Wait for editor to close
+/**
+ Wait for editor to close
+ */
void ExternalCodeEditor::close_editor() {
if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pid_));
// Wait until editor is closed + reaped
@@ -101,10 +125,12 @@ void ExternalCodeEditor::close_editor() {
}
}
-// [Protected] Kill the running editor (if any)
-// Kills the editor, reaps the process, and removes the tmp file.
-// The dtor calls this to ensure no editors remain running when fluid exits.
-//
+/**
+ Kill the running editor (if any).
+
+ Kills the editor, reaps the process, and removes the tmp file.
+ The dtor calls this to ensure no editors remain running when fluid exits.
+ */
void ExternalCodeEditor::kill_editor() {
if ( G_debug ) printf("kill_editor() called: pid=%ld\n", (long)pid_);
if ( !is_editing() ) return; // editor not running? return..
@@ -137,15 +163,18 @@ void ExternalCodeEditor::kill_editor() {
return;
}
-// [Public] Handle if file changed since last check, and update records if so.
-// Load new data into 'code', which caller must free().
-// If 'force' set, forces reload even if file size/time didn't change.
-//
-// Returns:
-// 0 -- file unchanged or not editing
-// 1 -- file changed, internal records updated, 'code' has new content
-// -1 -- error getting file info (strerror() has reason)
-//
+/**
+ Handle if file changed since last check, and update records if so.
+
+ Load new data into 'code', which caller must free().
+ If 'force' set, forces reload even if file size/time didn't change.
+
+ \param[in] code
+ \param[in] force
+ \return 0 if file unchanged or not editing
+ \return 1 if file changed, internal records updated, 'code' has new content
+ \return -1 error getting file info (strerror() has reason)
+*/
int ExternalCodeEditor::handle_changes(const char **code, int force) {
code[0] = 0;
if ( !is_editing() ) return 0;
@@ -190,12 +219,12 @@ int ExternalCodeEditor::handle_changes(const char **code, int force) {
return ret;
}
-// [Public] Remove the tmp file (if it exists), and zero out filename/mtime/size
-// Returns:
-// -1 -- on error (dialog is posted as to why)
-// 0 -- no file to remove
-// 1 -- file was removed
-//
+/**
+ Remove the tmp file (if it exists), and zero out filename/mtime/size.
+ \return -1 on error (dialog is posted as to why)
+ \return 0 no file to remove
+ \return 1 -- file was removed
+ */
int ExternalCodeEditor::remove_tmpfile() {
const char *tmpfile = filename();
if ( !tmpfile ) return 0;
@@ -213,18 +242,20 @@ int ExternalCodeEditor::remove_tmpfile() {
return 1;
}
-// [Static/Public] Return tmpdir name for this fluid instance.
-// Returns pointer to static memory.
-//
+/**
+ Return tmpdir name for this fluid instance.
+ \return pointer to static memory.
+ */
const char* ExternalCodeEditor::tmpdir_name() {
static char dirname[100];
snprintf(dirname, sizeof(dirname), "/tmp/.fluid-%ld", (long)getpid());
return dirname;
}
-// [Static/Public] Clear the external editor's tempdir
-// Static so that the main program can call it on exit to clean up.
-//
+/**
+ Clear the external editor's tempdir.
+ Static so that the main program can call it on exit to clean up.
+ */
void ExternalCodeEditor::tmpdir_clear() {
const char *tmpdir = tmpdir_name();
if ( is_dir(tmpdir) ) {
@@ -235,9 +266,11 @@ void ExternalCodeEditor::tmpdir_clear() {
}
}
-// [Protected] Creates temp dir (if doesn't exist) and returns the dirname
-// as a static string. Returns NULL on error, dialog shows reason.
-//
+/**
+ Creates temp dir (if doesn't exist) and returns the dirname
+ as a static string.
+ \return NULL on error, dialog shows reason.
+ */
const char* ExternalCodeEditor::create_tmpdir() {
const char *dirname = tmpdir_name();
if ( ! is_dir(dirname) ) {
@@ -250,26 +283,26 @@ const char* ExternalCodeEditor::create_tmpdir() {
return dirname;
}
-// [Protected] Returns temp filename in static buffer.
-// Returns NULL if can't, posts dialog explaining why.
-//
+/**
+ Returns temp filename in static buffer.
+ \return NULL if can't, posts dialog explaining why.
+ */
const char* ExternalCodeEditor::tmp_filename() {
static char path[512];
const char *tmpdir = create_tmpdir();
if ( !tmpdir ) return 0;
- extern const char *code_file_name; // fluid's global
const char *ext = code_file_name; // e.g. ".cxx"
snprintf(path, sizeof(path), "%s/%p%s", tmpdir, (void*)this, ext);
path[sizeof(path)-1] = 0;
return path;
}
-// [Static/Local] Save string 'code' to 'filename', returning file's mtime/size
-// 'code' can be NULL -- writes an empty file if so.
-// Returns:
-// 0 on success
-// -1 on error (posts dialog with reason)
-//
+/**
+ Save string 'code' to 'filename', returning file's mtime/size.
+ 'code' can be NULL -- writes an empty file if so.
+ \return 0 on success
+ \return -1 on error (posts dialog with reason)
+ */
static int save_file(const char *filename, const char *code) {
int fd = open(filename, O_WRONLY|O_CREAT, 0666);
if ( fd == -1 ) {
@@ -291,14 +324,14 @@ static int save_file(const char *filename, const char *code) {
return(ret);
}
-// [Static/Local] Convert string 's' to array of argv[], useful for execve()
-// o 's' will be modified (words will be NULL separated)
-// o argv[] will end up pointing to the words of 's'
-// o Caller must free argv with: free(argv);
-// Returns:
-// o -1 in case of memory allocation error
-// o number of arguments in argv (same value as in argc)
-//
+/**
+ Convert string 's' to array of argv[], useful for execve().
+ - 's' will be modified (words will be NULL separated)
+ - argv[] will end up pointing to the words of 's'
+ - Caller must free argv with: free(argv);
+ \return -1 in case of memory allocation error
+ \return number of arguments in argv (same value as in argc)
+ */
static int make_args(char *s, // string containing words (gets trashed!)
int *aargc, // pointer to argc
char ***aargv) { // pointer to argv
@@ -316,11 +349,11 @@ static int make_args(char *s, // string containing words (gets trashed!)
return(t);
}
-// [Protected] Start editor in background (fork/exec)
-// Returns:
-// > 0 on success, leaves editor child process running as 'pid_'
-// > -1 on error, posts dialog with reason (child exits)
-//
+/**
+ Start editor in background (fork/exec)
+ \return 0 on success, leaves editor child process running as 'pid_'
+ \return -1 on error, posts dialog with reason (child exits)
+ */
int ExternalCodeEditor::start_editor(const char *editor_cmd,
const char *filename) {
if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n",
@@ -354,17 +387,18 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd,
return 0;
}
-// [Public] Try to reap external editor process
-// If 'pid_reaped' not NULL, returns PID of reaped editor.
-// Returns:
-// -2 -- editor not open
-// -1 -- waitpid() failed (errno has reason)
-// 0 -- process still running
-// 1 -- process finished + reaped ('pid_reaped' has pid), pid_ set to -1.
-// Handles removing tmpfile/zeroing file_mtime/file_size/filename
-//
-// If return value <=0, 'pid_reaped' is set to zero.
-//
+/**
+ Try to reap external editor process.
+
+ If 'pid_reaped' not NULL, returns PID of reaped editor.
+
+ \return -2: editor not open
+ \return -1: waitpid() failed (errno has reason)
+ \return 0: process still running
+ \return 1: process finished + reaped ('pid_reaped' has pid), pid_ set to -1.
+ Handles removing tmpfile/zeroing file_mtime/file_size/filename
+ \return If return value <=0, 'pid_reaped' is set to zero.
+ */
int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) {
if ( pid_reaped ) *pid_reaped = 0;
if ( !is_editing() ) return -2;
@@ -388,14 +422,15 @@ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) {
return 1;
}
-// [Public] Open external editor using 'editor_cmd' to edit 'code'
-// 'code' contains multiline code to be edited as a temp file.
-//
-// Returns:
-// 0 if succeeds
-// -1 if can't open editor (already open, etc),
-// errors were shown to user in a dialog
-//
+/**
+ Open external editor using 'editor_cmd' to edit 'code'.
+
+ 'code' contains multiline code to be edited as a temp file.
+
+ \return 0 if succeeds
+ \return -1 if can't open editor (already open, etc),
+ errors were shown to user in a dialog
+ */
int ExternalCodeEditor::open_editor(const char *editor_cmd,
const char *code) {
// Make sure a temp filename exists
@@ -446,31 +481,38 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd,
return 0;
}
-// [Public/Static] Start update timer
+/**
+ Start update timer.
+ */
void ExternalCodeEditor::start_update_timer() {
if ( !L_update_timer_cb ) return;
if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n");
Fl::add_timeout(2.0, L_update_timer_cb);
}
-// [Public/Static] Stop update timer
+/**
+ Stop update timer.
+ */
void ExternalCodeEditor::stop_update_timer() {
if ( !L_update_timer_cb ) return;
if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n");
Fl::remove_timeout(L_update_timer_cb);
}
-// [Public/Static] Set app's external editor update timer callback
-// This is the app's callback callback we start while editors are open,
-// and stop when all editors are closed.
-//
+/**
+ Set app's external editor update timer callback.
+
+ This is the app's callback callback we start while editors are open,
+ and stop when all editors are closed.
+ */
void ExternalCodeEditor::set_update_timer_callback(Fl_Timeout_Handler cb) {
L_update_timer_cb = cb;
}
-// [Static/Public] See if any external editors are open.
-// App's timer cb can see if any editors need checking..
-//
+/**
+ See if any external editors are open.
+ App's timer cb can see if any editors need checking..
+ */
int ExternalCodeEditor::editors_open() {
return L_editors_open;
}