source: tags/svn.1.5.4/WINDOW/AW_edit.cxx

Last change on this file was 8103, checked in by westram, 14 years ago

merge from ptpan_back [8071] [8075] [8076] [8077] [8079]

  • moved ARBDB/GB_system → CORE/GBK_system
  • moved basic file related functions from ARBDB to CORE
    • GB_time_of_file (no longer automatically evaluates given path)
File size: 4.9 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 void check_file_changed_cb(AW_root *aw_root, AW_CL cl_cbdata) {
67    fileChanged_cb_data *data = (fileChanged_cb_data*)cl_cbdata;
68
69    if (data->editorTerminated) {
70        delete data;
71    }
72    else {
73        bool changed = data->fileWasChanged();
74
75        if (changed) data->callback(data->fpath, true, false);
76        aw_root->add_timed_callback(AWT_CHECK_FILE_TIMER, check_file_changed_cb, cl_cbdata);
77    }
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    // if 'callback' is specified, it is called everytime the file is changed
83    // [aww and gb_main may be 0 if callback is 0]
84
85    const char          *editor  = GB_getenvARB_TEXTEDIT();
86    char                *fpath   = GBS_eval_env(path);
87    char                *command = 0;
88    fileChanged_cb_data *cb_data = 0;
89    GB_ERROR             error   = 0;
90
91    if (callback) {
92        aw_assert(aww);
93        aw_assert(gb_main);
94
95        cb_data = new fileChanged_cb_data(&fpath, callback); // fpath now is 0 and belongs to cb_data
96
97        char *arb_notify       = GB_generate_notification(gb_main, editor_terminated_cb, "editor terminated", (void*)cb_data);
98        if (!arb_notify) error = GB_await_error();
99        else {
100            char *arb_message = GBS_global_string_copy("arb_message \"Could not start editor '%s'\"", editor);
101
102            command = GBS_global_string_copy("((%s %s || %s); %s)&", editor, cb_data->fpath, arb_message, arb_notify);
103            free(arb_message);
104            free(arb_notify);
105        }
106    }
107    else {
108        command = GBS_global_string_copy("%s %s &", editor, fpath);
109    }
110
111    if (command) {
112        aw_assert(!error);
113        error = GBK_system(command);
114        if (error) {
115            aw_message(error); error = NULL;
116            if (callback) error = GB_remove_last_notification(gb_main);
117        }
118        else { // successfully started editor
119            // Can't be sure editor really started when callback is used (see command above).
120            // But it doesn't matter, cause arb_notify is called anyway and removes all callbacks
121            if (callback) {
122                // add timed callback tracking file change
123                AW_root *aw_root = aww->get_root();
124                aw_root->add_timed_callback(AWT_CHECK_FILE_TIMER, check_file_changed_cb, (AW_CL)cb_data);
125                cb_data          = 0; // now belongs to check_file_changed_cb
126            }
127        }
128    }
129
130    if (error) aw_message(error);
131
132    free(command);
133    delete cb_data;
134    free(fpath);
135}
136
137void AW_system(AW_window *aww, const char *command, const char *auto_help_file) {
138    if (auto_help_file) AW_POPUP_HELP(aww, (AW_CL)auto_help_file);
139    aw_message_if(GBK_system(command));
140}
Note: See TracBrowser for help on using the repository browser.