source: tags/arb-6.0/WINDOW/AW_edit.cxx

Last change on this file was 11525, checked in by westram, 10 years ago
  • hack to allow users to edit arb helpfiles and easily send them to us
File size: 4.8 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : AW_edit.cxx                                        //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Institute of Microbiology (Technical University Munich)        //
7//   http://www.arb-home.de/                                        //
8//                                                                  //
9// ================================================================ //
10
11#include "aw_edit.hxx"
12#include "aw_window.hxx"
13#include "aw_root.hxx"
14#include "aw_msg.hxx"
15
16#include <arbdbt.h>
17
18#include <sys/stat.h>
19
20
21struct fileChanged_cb_data : virtual Noncopyable {
22    char              *fpath;                       // full name of edited file
23    int                lastModtime;                 // last known modification time of 'fpath'
24    bool               editorTerminated;            // do not free before this has been set to 'true'
25    aw_fileChanged_cb  callback;
26
27    fileChanged_cb_data(char **fpath_ptr, aw_fileChanged_cb cb) {
28        fpath            = *fpath_ptr;
29        *fpath_ptr       = 0;   // take ownage
30        lastModtime      = getModtime();
31        editorTerminated = false;
32        callback         = cb;
33    }
34
35    ~fileChanged_cb_data() {
36        free(fpath);
37    }
38
39    int getModtime() {
40        struct stat st;
41        if (stat(fpath, &st) == 0) return st.st_mtime;
42        return 0;
43    }
44
45    bool fileWasChanged() {
46        int  modtime = getModtime();
47        bool changed = modtime != lastModtime;
48        lastModtime  = modtime;
49        return changed;
50    }
51};
52
53static void editor_terminated_cb(const char *IF_DEBUG(message), void *cb_data) {
54    fileChanged_cb_data *data = (fileChanged_cb_data*)cb_data;
55
56#if defined(DEBUG)
57    printf("editor_terminated_cb: message='%s' fpath='%s'\n", message, data->fpath);
58#endif // DEBUG
59
60    data->callback(data->fpath, data->fileWasChanged(), true);
61    data->editorTerminated = true; // trigger removal of check_file_changed_cb
62}
63
64#define AWT_CHECK_FILE_TIMER 700 // in ms
65
66static unsigned check_file_changed_cb(AW_root *, fileChanged_cb_data *data) {
67    unsigned restart = 0;
68    if (data->editorTerminated) {
69        delete data;
70    }
71    else {
72        bool changed = data->fileWasChanged();
73
74        if (changed) data->callback(data->fpath, true, false);
75        restart = AWT_CHECK_FILE_TIMER;
76    }
77    return restart;
78}
79
80void AW_edit(const char *path, aw_fileChanged_cb callback, AW_window *aww, GBDATA *gb_main) {
81    // Start external editor on file 'path' (asynchronously)
82    //
83    // if 'callback' is specified, it is called everytime the file is changed
84    // and once after the editor terminated.
85    //
86    // 'aww' and 'gb_main' have to passed if a callback is specified!
87
88    const char          *editor  = GB_getenvARB_TEXTEDIT();
89    char                *fpath   = GBS_eval_env(path);
90    char                *command = 0;
91    fileChanged_cb_data *cb_data = 0;
92    GB_ERROR             error   = 0;
93
94    if (callback) {
95        aw_assert(aww);
96        aw_assert(gb_main);
97
98        cb_data = new fileChanged_cb_data(&fpath, callback); // fpath now is 0 and belongs to cb_data
99
100        char *arb_notify       = GB_generate_notification(gb_main, editor_terminated_cb, "editor terminated", (void*)cb_data);
101        if (!arb_notify) error = GB_await_error();
102        else {
103            char *arb_message = GBS_global_string_copy("arb_message \"Could not start editor '%s'\"", editor);
104
105            command = GBS_global_string_copy("((%s %s || %s); %s)&", editor, cb_data->fpath, arb_message, arb_notify);
106            free(arb_message);
107            free(arb_notify);
108        }
109    }
110    else {
111        command = GBS_global_string_copy("%s %s &", editor, fpath);
112    }
113
114    if (command) {
115        aw_assert(!error);
116        error = GBK_system(command);
117        if (error) {
118            aw_message(error); error = NULL;
119            if (callback) error = GB_remove_last_notification(gb_main);
120        }
121        else { // successfully started editor
122            // Can't be sure editor really started when callback is used (see command above).
123            // But it doesn't matter, cause arb_notify is called anyway and removes all callbacks
124            if (callback) {
125                // add timed callback tracking file change
126                AW_root *aw_root = aww->get_root();
127                aw_root->add_timed_callback(AWT_CHECK_FILE_TIMER, makeTimedCallback(check_file_changed_cb, cb_data));
128                cb_data          = 0; // now belongs to check_file_changed_cb
129            }
130        }
131    }
132
133    if (error) aw_message(error);
134
135    free(command);
136    delete cb_data;
137    free(fpath);
138}
139
Note: See TracBrowser for help on using the repository browser.