>       I'll try to follow up with a rewrite of your app, so that you can get
>       an idea of how it should be laid out. Shouldn't be hard.

   I rewrote it -- you may not recognize it, but this is more likely
   how it should be laid out.. this approach will 'scale' to larger apps.

   Notice how everything is in the EditorWindow class now.. this
   way all the methods/callbacks can access all the data it needs
   without it being global.

   This means you can easily create several instances of EditorWindow,
   each with its own commands that can be running concurrently.

   Notes on what I removed (for brevity):

       > I wasn't sure what the multibrowser was for, so I took it out.

       > I also removed the file load stuff, because it seemed unrelated
         to the problem. Note that Fl_Text_Buffer has a loadfile() method,
         so you can use that to load the editor with a text file, rather
         than writing it yourself, though maybe you needed something custom,
         I didn't look.

       > I rewrote the menu code a bit.. I dislike using that static menu
         array stuff, and prefer using the menubar->add() approach.

   Study the design of this, and see if you can see why it has
   been laid out this way. Putting all the variables into the class
   cleans up all the variable scoping, so that everything has access
   to what it needs, cleanly, without all those nasty globals.

   Follow up with questions if you need to, but I think if you look
   at it carefully, you'll get it.

   The nasty globals in the original demo app were just to keep
   the demo simple. It's assumed the reader is familiar with the
   mechanics of C++, and after reading the example, can re-scope the
   the variables as they please.

   HTH.

---- snip

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef _WIN32
#include <windows.h>
#define popen  _popen
#define pclose _pclose
#else
#include <unistd.h>
#endif
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Text_Buffer.H>
#include <FL/Fl_Text_Editor.H>
#include <FL/Fl_Window.H>

class EditorWindow : public Fl_Double_Window {
    // Menubar
    Fl_Menu_Bar *menubar;

    // File editor
    Fl_Text_Editor *file_edit;
    Fl_Text_Buffer *file_buff;

    // Console editor
    Fl_Text_Editor *console_edit;
    Fl_Text_Buffer *console_buff;

    // Popen stuff
    FILE *fp;
    char command[512];

    // DATA CALLBACK: Handle reading data from running command
    void HandleFD() {
        static char s[1024];
        if ( fgets(s, sizeof(s)-1, fp) == NULL ) {
            Fl::remove_fd(fileno(fp));
            pclose(fp);
            fp = 0;
            console_buff->append("--- COMMAND COMPLETED\n");
        } else {
            console_buff->append(s);
        }
    }
    static void HandleFD_CB(int, void *userdata) {
        EditorWindow *ewin = (EditorWindow*)userdata;
        ewin->HandleFD();                               // avoids having to do 
ewin->xxx to access vars
    }
    // MENU CALLBACK: Build command
    static void MakeCommand_CB(Fl_Widget*, void*userdata) {
        EditorWindow *ewin = (EditorWindow*)userdata;
        strcpy(ewin->command, "netstat -an 2>&1");      // create the command
    }
    // MENU CALLBACK: Start command running
    void RunCommand() {
        if ( fp != 0 ) return;                          // command already 
running? ignore
        console_buff->text("");                         // clear window
        if ( command[0] == 0 ) {                        // no command? complain
            console_buff->text("No command specified");
            return;
        }
        fp = popen(command, "r");                       // start command 
running..
        if ( fp == NULL ) {                             // Failed? show error
            console_buff->append("ERROR: popen: ");
            console_buff->append(strerror(errno));
        } else {                                        // Worked? setup handler
            Fl::add_fd(fileno(fp), HandleFD_CB, (void*)this);
        }
    }
    // MENU CALLBACK: Start command running
    static void RunCommand_CB(Fl_Widget*, void*userdata) {
        EditorWindow *ewin = (EditorWindow*)userdata;
        ewin->RunCommand();                             // avoids having to do 
ewin->xxx to access vars
    }

public:
    // Ctor
    EditorWindow(int w, int h, const char* t) : Fl_Double_Window(w, h, t) {
        // Create menu bar
        menubar = new Fl_Menu_Bar(0, 0, w, 25);
        menubar->add("&File/Make Command", FL_CTRL+'s', MakeCommand_CB, 
(void*)this);
        menubar->add("&File/Run",          FL_CTRL+'r', RunCommand_CB,  
(void*)this);

        // Create file editor
        file_edit = new Fl_Text_Editor(0, 40, w, 260, "File Editor");
        file_buff = new Fl_Text_Buffer();
        file_edit->buffer(file_buff);
        file_edit->textfont(FL_COURIER);

        // Create console editor
        console_edit = new Fl_Text_Editor(0, 320, w, 260, "Console Output");
        console_buff = new Fl_Text_Buffer();
        console_edit->buffer(console_buff);
        console_edit->textfont(FL_COURIER);

        // Popen stuff
        fp = NULL;
        command[0] = 0;

        end();
        resizable(this);
    }
    ~EditorWindow() {
    }
};

int main(int argc, char **argv) {
    EditorWindow *ewin = new EditorWindow(600, 600, "Test");
    ewin->show();
    return(Fl::run());
}
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to