~ubuntu-branches/debian/jessie/arb/jessie

« back to all changes in this revision

Viewing changes to AWT/AWT_sel_boxes.cxx

  • Committer: Package Import Robot
  • Author(s): Elmar Pruesse, Andreas Tille, Elmar Pruesse
  • Date: 2014-09-02 15:15:06 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20140902151506-jihq58b3iz342wif
Tags: 6.0.2-1
[ Andreas Tille ]
* New upstream version
  Closes: #741890
* debian/upstream -> debian/upstream/metadata
* debian/control:
   - Build-Depends: added libglib2.0-dev
   - Depends: added mafft, mrbayes
* debian/rules
   - Add explicite --remove-section=.comment option to manual strip call
* cme fix dpkg-control
* arb-common.dirs: Do not create unneeded lintian dir
* Add turkish debconf translation (thanks for the patch to Mert Dirik
  <mertdirik@gmail.com>)
  Closes: #757497

[ Elmar Pruesse ]
* patches removed:
   - 10_config.makefiles.patch,
     80_no_GL.patch
       removed in favor of creating file from config.makefile.template via 
       sed in debian/control
   - 20_Makefile_main.patch
       merged upstream
   - 21_Makefiles.patch
       no longer needed
   - 30_tmpfile_CVE-2008-5378.patch: 
       merged upstream
   - 50_fix_gcc-4.8.patch:
       merged upstream
   - 40_add_libGLU.patch:
       libGLU not needed for arb_ntree)
   - 60_use_debian_packaged_raxml.patch:
       merged upstream
   - 70_hardening.patch
       merged upstream
   - 72_add_math_lib_to_linker.patch
       does not appear to be needed
* patches added:
   - 10_upstream_r12793__show_db_load_progress:
       backported patch showing progress while ARB is loading a database
       (needed as indicator/splash screen while ARB is launching)
   - 20_upstream_r12794__socket_permissions:
       backported security fix
   - 30_upstream_r12814__desktop_keywords:
       backported add keywords to desktop (fixes lintian warning)
   - 40_upstream_r12815__lintian_spelling:
       backported fix for lintian reported spelling errors
   - 50_private_nameservers
       change configuration to put nameservers into users home dirs
       (avoids need for shared writeable directory)
   - 60_use_debian_phyml
       use phyml from debian package for both interfaces in ARB
* debian/rules:
   - create config.makefile from override_dh_configure target
   - use "make tarfile" in override_dh_install
   - remove extra cleaning not needed for ARB 6
   - use "dh_install --list-missing" to avoid missing files
   - added override_dh_fixperms target
* debian/control:
   - added libarb-dev package
   - Depends: added phyml, xdg-utils
   - Suggests: removed phyml
   - fix lintian duplicate-short-description (new descriptions)
* debian/*.install:
   - "unrolled" confusing globbing to select files
   - pick files from debian/tmp
   - moved all config files to /etc/arb
* debian/arb-common.templates: updated
* scripts:
   - removed arb-add-pt-server
   - launch-wrapper: 
     - only add demo.arb to newly created $ARBUSERDATA
     - pass commandline arguments through bin/arb wrapper
   - preinst: removing old PT server index files on upgrade from 5.5*
   - postinst: set setgid on shared PT dir
* rewrote arb.1 manfile
* added file icon for ARB databases
* using upstream arb_tcp.dat

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <stdio.h>
2
 
#include <stdlib.h>
3
 
#include <unistd.h>
4
 
#include <time.h>
5
 
#include <string.h>
6
 
// #include <malloc.h>
7
 
#include <memory.h>
8
 
#include <sys/stat.h>
 
1
// ================================================================ //
 
2
//                                                                  //
 
3
//   File      : AWT_sel_boxes.cxx                                  //
 
4
//   Purpose   :                                                    //
 
5
//                                                                  //
 
6
//   Institute of Microbiology (Technical University Munich)        //
 
7
//   http://www.arb-home.de/                                        //
 
8
//                                                                  //
 
9
// ================================================================ //
9
10
 
10
 
#include <arbdb.h>
11
 
#include <arbdbt.h>
12
 
#include <ad_config.h>
13
 
#include <aw_root.hxx>
14
 
#include <aw_device.hxx>
15
 
#include <aw_window.hxx>
16
 
#include <aw_awars.hxx>
17
 
#include <aw_global.hxx>
18
11
#include "awt.hxx"
19
 
#include "awtlocal.hxx"
20
12
#include "awt_sel_boxes.hxx"
21
 
#include "awt_item_sel_list.hxx"
22
 
 
23
 
// ******************** selection boxes on alignments ********************
24
 
 
25
 
static void awt_create_selection_list_on_ad_cb(GBDATA *, struct adawcbstruct *cbs) {
26
 
    cbs->aws->clear_selection_list(cbs->id);
27
 
 
28
 
    for (GBDATA * gb_alignment = GB_search(cbs->gb_main, "presets/alignment", GB_FIND);
29
 
         gb_alignment;
30
 
         gb_alignment = GB_nextEntry(gb_alignment))
31
 
    {
32
 
        char *alignment_type = GBT_read_string(gb_alignment, "alignment_type");
33
 
        char *alignment_name = GBT_read_string(gb_alignment, "alignment_name");
34
 
        char *str            = GBS_string_eval(alignment_type, cbs->comm, 0);
35
 
 
36
 
        if (!*str) {
37
 
            cbs->aws->insert_selection(cbs->id, alignment_name, alignment_name);
38
 
        }
39
 
        free(str);
40
 
        free(alignment_type);
41
 
        free(alignment_name);
42
 
    }
43
 
    cbs->aws->insert_default_selection(cbs->id, "????", "????");
44
 
    cbs->aws->update_selection_list(cbs->id);
45
 
}
46
 
 
47
 
 
48
 
void awt_create_selection_list_on_ad(GBDATA *gb_main,AW_window *aws, const char *varname,const char *comm)
49
 
// if comm is set then only those alignments are taken
50
 
// which can be parsed by comm
51
 
{
52
 
    AW_selection_list *id;
53
 
    GBDATA            *gb_presets;
54
 
 
55
 
    GB_push_transaction(gb_main);
56
 
 
57
 
    id  = aws->create_selection_list(varname,0,"",20,3);
58
 
    struct adawcbstruct *cbs = new adawcbstruct;
59
 
    memset(cbs, 0, sizeof(*cbs));
60
 
 
61
 
    cbs->aws     = aws;
62
 
    cbs->awr     = aws->get_root();
63
 
    cbs->gb_main = gb_main;
64
 
    cbs->id      = id;
65
 
    cbs->comm    = 0; if (comm) cbs->comm = strdup(comm);
66
 
 
67
 
    awt_create_selection_list_on_ad_cb(0,cbs);
68
 
 
69
 
    gb_presets = GB_search(gb_main,"presets",GB_CREATE_CONTAINER);
70
 
    GB_add_callback(gb_presets,GB_CB_CHANGED, (GB_CB)awt_create_selection_list_on_ad_cb, (int *)cbs);
71
 
 
72
 
    GB_pop_transaction(gb_main);
73
 
}
74
 
 
75
 
 
76
 
// ******************** selection boxes on trees ********************
77
 
 
78
 
void awt_create_selection_list_on_trees_cb(GBDATA *dummy, struct adawcbstruct *cbs) {
79
 
    AWUSE(dummy);
80
 
 
81
 
    cbs->aws->clear_selection_list(cbs->id);
82
 
    char **tree_names = GBT_get_tree_names(cbs->gb_main);
83
 
    if (tree_names) {
84
 
        int maxTreeNameLen = 0;
85
 
        for (char **tree= tree_names ; *tree; tree++){
86
 
            int len = strlen(*tree);
87
 
            if (len>maxTreeNameLen) maxTreeNameLen = len;
88
 
        }
89
 
        for (char **tree= tree_names ; *tree; tree++){
90
 
            const char *info = GBT_tree_info_string(cbs->gb_main, *tree, maxTreeNameLen);
91
 
            if (info) {
92
 
                cbs->aws->insert_selection( cbs->id, info, *tree );
93
 
            } else {
94
 
                cbs->aws->insert_selection( cbs->id, *tree, *tree );
95
 
            }
96
 
        }
97
 
        GBT_free_names(tree_names);
98
 
    }
99
 
    cbs->aws->insert_default_selection( cbs->id, "????", "????" );
100
 
    cbs->aws->update_selection_list( cbs->id );
101
 
}
102
 
 
103
 
void awt_create_selection_list_on_trees(GBDATA *gb_main,AW_window *aws,const char *varname) {
104
 
    AW_selection_list *id;
105
 
    GBDATA            *gb_tree_data;
106
 
    
107
 
    GB_push_transaction(gb_main);
108
 
 
109
 
    id = aws->create_selection_list(varname,0,"",40,4);
110
 
    struct adawcbstruct *cbs = new adawcbstruct;
111
 
    memset(cbs, 0, sizeof(*cbs));
112
 
 
113
 
    cbs->aws     = aws;
114
 
    cbs->awr     = aws->get_root();
115
 
    cbs->gb_main = gb_main;
116
 
    cbs->id      = id;
117
 
 
118
 
    awt_create_selection_list_on_trees_cb(0,cbs);
119
 
 
120
 
    gb_tree_data = GB_search(gb_main,"tree_data",GB_CREATE_CONTAINER);
121
 
    GB_add_callback(gb_tree_data,GB_CB_CHANGED, (GB_CB)awt_create_selection_list_on_trees_cb, (int *)cbs);
122
 
 
123
 
    GB_pop_transaction(gb_main);
124
 
}
125
 
 
126
 
// ******************** selection boxes on pt-servers ********************
127
 
 
128
 
#define PT_SERVERNAME_LENGTH        23 // that's for buttons
129
 
#define PT_SERVERNAME_SELLIST_WIDTH 30 // this for lists
130
 
#define PT_SERVER_TRACKLOG_TIMER    10000 // every 10 seconds
131
 
 
132
 
struct selection_list_handle {
133
 
    AW_window                    *aws;
134
 
    AW_selection_list            *sellst;
135
 
    struct selection_list_handle *next;
136
 
};
137
 
 
138
 
static selection_list_handle *allPTserverSellists = 0; // all pt server selection lists
139
 
 
140
 
static void fill_pt_server_selection_list(AW_window *aws, AW_selection_list *id) {
141
 
    aws->clear_selection_list(id);
142
 
 
 
13
 
 
14
#include <item_sel_list.h>
 
15
 
 
16
#include <aw_awars.hxx>
 
17
#include <aw_file.hxx>
 
18
#include <aw_msg.hxx>
 
19
#include <aw_root.hxx>
 
20
#include <aw_edit.hxx>
 
21
 
 
22
#include <ad_config.h>
 
23
#include <ad_cb.h>
 
24
 
 
25
#include <arbdbt.h>
 
26
#include <arb_strbuf.h>
 
27
#include <arb_strarray.h>
 
28
#include <arb_file.h>
 
29
#include <arb_global_defs.h>
 
30
 
 
31
#include <list>
 
32
#include "awt_modules.hxx"
 
33
#include <BufferedFileReader.h>
 
34
 
 
35
using namespace std;
 
36
 
 
37
 
 
38
 
 
39
// --------------------------------------
 
40
//      selection boxes on alignments
 
41
 
 
42
class AWT_alignment_selection : public AW_DB_selection { // derived from a Noncopyable
 
43
    char *ali_type_match;                           // filter for wanted alignments (GBS_string_eval command)
 
44
public:
 
45
    AWT_alignment_selection(AW_selection_list *sellist_, GBDATA *gb_presets, const char *ali_type_match_)
 
46
        : AW_DB_selection(sellist_, gb_presets)
 
47
        , ali_type_match(nulldup(ali_type_match_))
 
48
    {}
 
49
    
 
50
    void fill() OVERRIDE {
 
51
        GBDATA         *gb_presets = get_gbd();
 
52
        GB_transaction  ta(gb_presets);
 
53
 
 
54
        for (GBDATA *gb_alignment = GB_entry(gb_presets, "alignment");
 
55
             gb_alignment;
 
56
             gb_alignment = GB_nextEntry(gb_alignment))
 
57
        {
 
58
            char *alignment_type = GBT_read_string(gb_alignment, "alignment_type");
 
59
            char *alignment_name = GBT_read_string(gb_alignment, "alignment_name");
 
60
            char *str            = GBS_string_eval(alignment_type, ali_type_match, 0);
 
61
 
 
62
            if (!*str) insert(alignment_name, alignment_name);
 
63
            free(str);
 
64
            free(alignment_type);
 
65
            free(alignment_name);
 
66
        }
 
67
        insert_default(DISPLAY_NONE, NO_ALI_SELECTED);
 
68
    }
 
69
 
 
70
    void reconfigure(const char *new_ali_type_match) {
 
71
        freedup(ali_type_match, new_ali_type_match);
 
72
        refresh();
 
73
    }
 
74
};
 
75
 
 
76
AW_DB_selection *awt_create_selection_list_on_alignments(GBDATA *gb_main, AW_window *aws, const char *varname, const char *ali_type_match) {
 
77
    // Create selection lists on alignments
 
78
    //
 
79
    // if 'ali_type_match' is set, then only insert alignments,
 
80
    // where 'ali_type_match' GBS_string_eval's the alignment type
 
81
 
 
82
    GBDATA *gb_presets;
 
83
    {
 
84
        GB_transaction ta(gb_main);
 
85
        gb_presets = GBT_get_presets(gb_main);
 
86
    }
 
87
    AW_selection_list       *sellist = aws->create_selection_list(varname, 20, 3, true);
 
88
    AWT_alignment_selection *alisel  = new AWT_alignment_selection(sellist, gb_presets, ali_type_match);
 
89
    alisel->refresh(); // belongs to window now
 
90
    return alisel;
 
91
}
 
92
 
 
93
void awt_reconfigure_selection_list_on_alignments(AW_DB_selection *dbsel, const char *ali_type_match) {
 
94
    AWT_alignment_selection *alisel = dynamic_cast<AWT_alignment_selection*>(dbsel);
 
95
    alisel->reconfigure(ali_type_match);
 
96
}
 
97
 
 
98
// ---------------------------------
 
99
//      selection boxes on trees
 
100
 
 
101
struct AWT_tree_selection: public AW_DB_selection {
 
102
    AWT_tree_selection(AW_selection_list *sellist_, GBDATA *gb_tree_data)
 
103
        : AW_DB_selection(sellist_, gb_tree_data)
 
104
    {}
 
105
 
 
106
    void fill() OVERRIDE {
 
107
        GBDATA         *gb_main = get_gb_main();
 
108
        GB_transaction  ta(gb_main);
 
109
 
 
110
        ConstStrArray tree_names;
 
111
        GBT_get_tree_names(tree_names, gb_main, true);
 
112
 
 
113
        if (!tree_names.empty()) {
 
114
            int maxTreeNameLen = 0;
 
115
            for (int i = 0; tree_names[i]; ++i) {
 
116
                const char *tree = tree_names[i];
 
117
                int         len  = strlen(tree);
 
118
                if (len>maxTreeNameLen) maxTreeNameLen = len;
 
119
            }
 
120
            for (int i = 0; tree_names[i]; ++i) {
 
121
                const char *tree = tree_names[i];
 
122
                const char *info = GBT_tree_info_string(gb_main, tree, maxTreeNameLen);
 
123
                if (info) {
 
124
                    insert(info, tree);
 
125
                }
 
126
                else {
 
127
                    aw_message(GB_await_error());
 
128
                    insert(tree, tree);
 
129
                }
 
130
            }
 
131
        }
 
132
        insert_default(DISPLAY_NONE, NO_TREE_SELECTED); 
 
133
    }
 
134
};
 
135
 
 
136
AW_DB_selection *awt_create_selection_list_on_trees(GBDATA *gb_main, AW_window *aws, const char *varname, bool fallback2default) {
 
137
    GBDATA *gb_tree_data;
 
138
    {
 
139
        GB_transaction ta(gb_main);
 
140
        gb_tree_data = GBT_get_tree_data(gb_main);
 
141
    }
 
142
    AW_selection_list  *sellist = aws->create_selection_list(varname, 40, 4, fallback2default);
 
143
    AWT_tree_selection *treesel = new AWT_tree_selection(sellist, gb_tree_data); // owned by nobody
 
144
    treesel->refresh();
 
145
    return treesel;
 
146
}
 
147
 
 
148
 
 
149
// --------------------------------------
 
150
//      selection boxes on pt-servers
 
151
 
 
152
#define PT_SERVERNAME_LENGTH        23              // that's for buttons
 
153
#define PT_SERVERNAME_SELLIST_WIDTH 30              // this for lists
 
154
#define PT_SERVER_TRACKLOG_TIMER    10000           // every 10 seconds
 
155
 
 
156
class AWT_ptserver_selection : public AW_selection {
 
157
    typedef list<AWT_ptserver_selection*> PTserverSelections;
 
158
    
 
159
    static PTserverSelections ptserver_selections;
 
160
public:
 
161
    AWT_ptserver_selection(AW_selection_list *sellist_);
 
162
 
 
163
    void fill() OVERRIDE;
 
164
 
 
165
    static void refresh_all();
 
166
};
 
167
 
 
168
AWT_ptserver_selection::PTserverSelections AWT_ptserver_selection::ptserver_selections;
 
169
 
 
170
void AWT_ptserver_selection::fill() {
143
171
    const char * const *pt_servers = GBS_get_arb_tcp_entries("ARB_PT_SERVER*");
144
172
 
145
173
    int count = 0;
151
179
            aw_message(GB_await_error());
152
180
            break;
153
181
        }
154
 
        aws->insert_selection(id,choice,(long)i);
 
182
        insert(choice, (long)i);
155
183
        free(choice);
156
184
    }
157
185
 
158
 
    aws->insert_default_selection(id, "-undefined-", (long)-1);
159
 
    aws->update_selection_list(id);
 
186
    insert_default("-undefined-", (long)-1);
160
187
}
161
188
 
162
 
void awt_refresh_all_pt_server_selection_lists() {
163
 
    // refresh content of all PT_server selection lists
164
 
    selection_list_handle *serverList = allPTserverSellists;
165
 
 
166
 
    while (serverList) {
167
 
        fill_pt_server_selection_list(serverList->aws, serverList->sellst);
168
 
        serverList = serverList->next;
 
189
void AWT_ptserver_selection::refresh_all() {
 
190
    PTserverSelections::iterator end = ptserver_selections.end();
 
191
    for (PTserverSelections::iterator pts_sel = ptserver_selections.begin(); pts_sel != end; ++pts_sel) {
 
192
        (*pts_sel)->refresh();
169
193
    }
170
194
}
171
 
 
172
 
static void track_log_cb(AW_root *awr) {
 
195
static void awt_refresh_all_pt_server_selection_lists() {
 
196
    AWT_ptserver_selection::refresh_all();
 
197
}
 
198
static unsigned track_log_cb(AW_root *) {
173
199
    static long  last_ptserverlog_mod = 0;
174
200
    const char  *ptserverlog          = GBS_ptserver_logname();
175
201
    long         ptserverlog_mod      = GB_time_of_file(ptserverlog);
178
204
#if defined(DEBUG)
179
205
        fprintf(stderr, "%s modified!\n", ptserverlog);
180
206
#endif // DEBUG
 
207
        AWT_ptserver_selection::refresh_all();
 
208
        last_ptserverlog_mod = ptserverlog_mod;
 
209
    }
 
210
 
 
211
    return PT_SERVER_TRACKLOG_TIMER;
 
212
}
 
213
 
 
214
AWT_ptserver_selection::AWT_ptserver_selection(AW_selection_list *sellist_)
 
215
    : AW_selection(sellist_)
 
216
{
 
217
    if (ptserver_selections.empty()) {
 
218
        // first pt server selection list -> install log tracker
 
219
        AW_root::SINGLETON->add_timed_callback(PT_SERVER_TRACKLOG_TIMER, makeTimedCallback(track_log_cb));
 
220
    }
 
221
    ptserver_selections.push_back(this);
 
222
}
 
223
 
 
224
 
 
225
static void arb_tcp_dat_changed_cb(const char * /* path */, bool fileChanged, bool /* editorTerminated */) {
 
226
    if (fileChanged) {
181
227
        awt_refresh_all_pt_server_selection_lists();
182
 
        last_ptserverlog_mod = ptserverlog_mod;
183
 
    }
184
 
 
185
 
    awr->add_timed_callback(PT_SERVER_TRACKLOG_TIMER, track_log_cb);
186
 
}
187
 
 
188
 
static void announce_pt_server_selection_list(AW_window *aws, AW_selection_list *id) {
189
 
#if defined(DEBUG)
190
 
    selection_list_handle *serverList = allPTserverSellists;
191
 
    while (serverList) {
192
 
        awt_assert(aws != serverList->aws || id != serverList->sellst); // oops - added twice
193
 
        serverList = serverList->next;
194
 
    }
195
 
#endif // DEBUG
196
 
 
197
 
    if (!allPTserverSellists) { // first pt server selection list -> install log tracker
198
 
        aws->get_root()->add_timed_callback(PT_SERVER_TRACKLOG_TIMER, track_log_cb);
199
 
    }
200
 
 
201
 
    selection_list_handle *newServerList = (selection_list_handle *)malloc(sizeof(*newServerList));
202
 
 
203
 
    newServerList->aws    = aws;
204
 
    newServerList->sellst = id;
205
 
    newServerList->next   = allPTserverSellists;
206
 
 
207
 
    allPTserverSellists = newServerList;
208
 
}
209
 
 
210
 
// --------------------------------------------------------------------------------
211
 
 
 
228
    }
 
229
}
 
230
 
 
231
void awt_edit_arbtcpdat_cb(AW_window *aww, GBDATA *gb_main) {
 
232
    char *filename = GB_arbtcpdat_path();
 
233
    AW_edit(filename, arb_tcp_dat_changed_cb, aww, gb_main);
 
234
    free(filename);
 
235
}
 
236
 
 
237
#if !defined(ARB_GTK)
212
238
static char *readable_pt_servername(int index, int maxlength) {
213
239
    char *fullname = GBS_ptserver_id_to_choice(index, 0);
214
240
    if (!fullname) {
215
241
#ifdef DEBUG
216
 
      printf("awar given to awt_create_selection_list_on_pt_servers() does not contain a valid index\n");
 
242
        printf("awar given to awt_create_selection_list_on_pt_servers() does not contain a valid index\n");
217
243
#endif
218
 
      //        awt_assert(0); // awar given to awt_create_selection_list_on_pt_servers() does not contain a valid index
 
244
        GB_clear_error();
219
245
        return strdup("-undefined-");
220
246
    }
221
247
 
232
258
    return fullname;
233
259
}
234
260
 
235
 
static void update_ptserver_button(AW_root *aw_root, AW_CL cl_varname) {
236
 
    const char *varname              = (const char *)cl_varname;
237
 
    char       *awar_buttontext_name = GBS_global_string_copy("/tmp/%s_BUTTON", varname);
238
 
    char       *readable_name        = readable_pt_servername(aw_root->awar(varname)->read_int(), PT_SERVERNAME_LENGTH);
 
261
static void update_ptserver_button(AW_root *aw_root, const char *varname) {
 
262
    char *awar_buttontext_name = GBS_global_string_copy("/tmp/%s_BUTTON", varname);
 
263
    char *readable_name        = readable_pt_servername(aw_root->awar(varname)->read_int(), PT_SERVERNAME_LENGTH);
239
264
 
240
265
    aw_root->awar(awar_buttontext_name)->write_string(readable_name);
241
266
 
243
268
    free(awar_buttontext_name);
244
269
}
245
270
 
246
 
AW_window *awt_popup_selection_list_on_pt_servers(AW_root *aw_root, const char *varname) {
 
271
static AW_window *create_selection_list_on_pt_servers_window(AW_root *aw_root, const char *varname) {
247
272
    AW_window_simple *aw_popup = new AW_window_simple;
248
273
 
249
274
    aw_popup->init(aw_root, "SELECT_PT_SERVER", "Select a PT-Server");
251
276
 
252
277
    aw_popup->at_newline();
253
278
    aw_popup->callback((AW_CB0)AW_POPDOWN);
254
 
    AW_selection_list *id = aw_popup->create_selection_list(varname, 0, "", PT_SERVERNAME_SELLIST_WIDTH, 20);
 
279
    AW_selection_list *sellist = aw_popup->create_selection_list(varname, PT_SERVERNAME_SELLIST_WIDTH, 20, true);
255
280
 
256
281
    aw_popup->at_newline();
257
282
    aw_popup->callback((AW_CB0)AW_POPDOWN);
258
283
    aw_popup->create_button("CLOSE", "CLOSE", "C");
259
284
 
260
285
    aw_popup->window_fit();
 
286
    aw_popup->recalc_pos_atShow(AW_REPOS_TO_MOUSE);
261
287
 
262
 
    announce_pt_server_selection_list(aw_popup, id);
263
 
    fill_pt_server_selection_list(aw_popup, id);
 
288
    (new AWT_ptserver_selection(sellist))->refresh();
264
289
 
265
290
    return aw_popup;
266
291
}
 
292
#endif // ARB_GTK
267
293
 
268
 
void awt_create_selection_list_on_pt_servers(AW_window *aws, const char *varname, bool popup)
269
 
{
 
294
void awt_create_selection_list_on_pt_servers(AW_window *aws, const char *varname, bool popup) {
270
295
    if (popup) {
 
296
#ifdef ARB_GTK
 
297
        (new AWT_ptserver_selection(aws->create_option_menu(varname, true)))->refresh();
 
298
 
 
299
        int old_button_length = aws->get_button_length();
 
300
        aws->button_length(PT_SERVERNAME_LENGTH+1);
 
301
        aws->update_option_menu();
 
302
        aws->button_length(old_button_length);
 
303
#else
 
304
 
271
305
        AW_root *aw_root              = aws->get_root();
272
306
        char    *awar_buttontext_name = GBS_global_string_copy("/tmp/%s_BUTTON", varname);
273
307
        int      ptserver_index       = aw_root->awar(varname)->read_int();
277
311
            aw_root->awar(varname)->write_int(ptserver_index);
278
312
        }
279
313
 
280
 
        char *readable_name = readable_pt_servername(ptserver_index, PT_SERVERNAME_LENGTH);
 
314
        char        *readable_name = readable_pt_servername(ptserver_index, PT_SERVERNAME_LENGTH);
 
315
        char *const  varnameDup    = strdup(varname);
281
316
 
282
 
        AW_CL cl_varname = (AW_CL)strdup(varname); // make copy of awar_name for callbacks
 
317
        awt_assert(!GB_have_error());
283
318
 
284
319
        aw_root->awar_string(awar_buttontext_name, readable_name, AW_ROOT_DEFAULT);
285
 
        aw_root->awar(varname)->add_callback(update_ptserver_button, cl_varname);
 
320
        aw_root->awar(varname)->add_callback(makeRootCallback(update_ptserver_button, varnameDup));
286
321
 
287
322
        int old_button_length = aws->get_button_length();
288
323
 
289
324
        aws->button_length(PT_SERVERNAME_LENGTH+1);
290
 
        aws->callback(AW_POPUP, (AW_CL)awt_popup_selection_list_on_pt_servers, cl_varname);
 
325
        aws->callback(makeCreateWindowCallback(create_selection_list_on_pt_servers_window, varnameDup));
291
326
        aws->create_button("CURR_PT_SERVER", awar_buttontext_name);
292
327
 
293
328
        aws->button_length(old_button_length);
294
329
 
295
330
        free(readable_name);
296
331
        free(awar_buttontext_name);
 
332
#endif
297
333
    }
298
334
    else {
299
 
        AW_selection_list *id = aws->create_selection_list(varname);
300
 
        announce_pt_server_selection_list(aws, id);
301
 
        fill_pt_server_selection_list(aws, id);
 
335
        (new AWT_ptserver_selection(aws->create_selection_list(varname, true)))->refresh();
302
336
    }
303
337
}
304
338
 
305
 
 
306
 
// ******************** selection boxes on tables ********************
307
 
 
308
 
void awt_create_selection_list_on_tables_cb(GBDATA *dummy, struct awt_sel_list_for_tables *cbs){
309
 
    AWUSE(dummy);
310
 
    cbs->aws->clear_selection_list(cbs->id);
 
339
// ----------------------------------
 
340
//      selection boxes on tables
 
341
 
 
342
 
 
343
#if defined(WARN_TODO)
 
344
#warning derive awt_sel_list_for_tables from AW_DB_selection
 
345
#endif
 
346
 
 
347
struct awt_sel_list_for_tables {
 
348
    AW_window         *aws;
 
349
    GBDATA            *gb_main;
 
350
    AW_selection_list *id;
 
351
    const char        *table_name;
 
352
};
 
353
 
 
354
static void awt_create_selection_list_on_tables_cb(GBDATA *, struct awt_sel_list_for_tables *cbs) {
 
355
    cbs->id->clear();
311
356
    GBDATA *gb_table;
312
357
    for (gb_table = GBT_first_table(cbs->gb_main);
313
358
         gb_table;
314
 
         gb_table = GBT_next_table(gb_table)){
 
359
         gb_table = GBT_next_table(gb_table)) {
315
360
 
316
 
        GBDATA *gb_name = GB_entry(gb_table,"name");
317
 
        GBDATA *gb_description = GB_search(gb_table,"description",GB_STRING);
 
361
        GBDATA *gb_name = GB_entry(gb_table, "name");
 
362
        GBDATA *gb_description = GB_search(gb_table, "description", GB_STRING);
318
363
        if (!gb_name) continue;
319
364
        char *table_name = GB_read_string(gb_name);
320
365
        char *description = GB_read_string(gb_description);
321
 
        const char *info_text = GBS_global_string("%s: %s",table_name,description);
322
 
        cbs->aws->insert_selection(cbs->id,info_text,table_name);
 
366
        const char *info_text = GBS_global_string("%s: %s", table_name, description);
 
367
        cbs->id->insert(info_text, table_name);
323
368
        free(table_name);
324
369
        free(description);
325
370
    }
326
 
    cbs->aws->insert_default_selection( cbs->id, "", "" );
327
 
    cbs->aws->update_selection_list( cbs->id );
 
371
    cbs->id->insert_default("", "");
 
372
    cbs->id->update();
328
373
}
329
374
 
330
 
void awt_create_selection_list_on_tables(GBDATA *gb_main,AW_window *aws,const char *varname)
 
375
void awt_create_selection_list_on_tables(GBDATA *gb_main, AW_window *aws, const char *varname)
331
376
{
332
377
    AW_selection_list *id;
333
378
    GBDATA  *gb_table_data;
334
379
    struct awt_sel_list_for_tables *cbs;
335
380
    GB_push_transaction(gb_main);
336
381
 
337
 
    id = aws->create_selection_list(varname,0,"",40,8);
 
382
    id = aws->create_selection_list(varname, 40, 8, true);
338
383
    cbs = new awt_sel_list_for_tables;
339
384
    cbs->aws = aws;
340
385
    cbs->gb_main = gb_main;
341
386
    cbs->id = id;
342
387
 
343
 
    awt_create_selection_list_on_tables_cb(0,cbs);
 
388
    awt_create_selection_list_on_tables_cb(0, cbs);
344
389
 
345
 
    gb_table_data = GB_search(gb_main,"table_data",GB_CREATE_CONTAINER);
346
 
    GB_add_callback(gb_table_data,GB_CB_CHANGED,(GB_CB)awt_create_selection_list_on_tables_cb, (int *)cbs);
 
390
    gb_table_data = GB_search(gb_main, "table_data", GB_CREATE_CONTAINER);
 
391
    GB_add_callback(gb_table_data, GB_CB_CHANGED, makeDatabaseCallback(awt_create_selection_list_on_tables_cb, cbs));
347
392
 
348
393
    GB_pop_transaction(gb_main);
349
394
}
350
 
// ******************** selection boxes on tables ********************
351
395
 
352
 
void awt_create_selection_list_on_table_fields_cb(GBDATA *dummy, struct awt_sel_list_for_tables *cbs){
353
 
    AWUSE(dummy);
354
 
    cbs->aws->clear_selection_list(cbs->id);
355
 
    GBDATA  *gb_table = GBT_open_table(cbs->gb_main,cbs->table_name, GB_TRUE); // read only
 
396
static void awt_create_selection_list_on_table_fields_cb(GBDATA *, struct awt_sel_list_for_tables *cbs) {
 
397
    cbs->id->clear();
 
398
    GBDATA  *gb_table = GBT_open_table(cbs->gb_main, cbs->table_name, true); // read only
356
399
    GBDATA *gb_table_field;
357
400
    for (gb_table_field = GBT_first_table_field(gb_table);
358
401
         gb_table_field;
359
402
         gb_table_field = GBT_next_table_field(gb_table_field))
360
403
    {
361
 
        GBDATA *gb_name = GB_entry(gb_table_field,"name");
362
 
        GBDATA *gb_description = GB_search(gb_table_field,"description",GB_STRING);
 
404
        GBDATA *gb_name = GB_entry(gb_table_field, "name");
 
405
        GBDATA *gb_description = GB_search(gb_table_field, "description", GB_STRING);
363
406
        if (!gb_name) continue;
364
407
        char *table_name = GB_read_string(gb_name);
365
408
        char *description = GB_read_string(gb_description);
366
 
        const char *info_text = GBS_global_string("%s: %s",table_name,description);
367
 
        cbs->aws->insert_selection(cbs->id,info_text,table_name);
 
409
        const char *info_text = GBS_global_string("%s: %s", table_name, description);
 
410
        cbs->id->insert(info_text, table_name);
368
411
        free(table_name);
369
412
        free(description);
370
413
    }
371
 
    cbs->aws->insert_default_selection( cbs->id, "", "" );
372
 
    cbs->aws->update_selection_list( cbs->id );
 
414
    cbs->id->insert_default("", "");
 
415
    cbs->id->update();
373
416
}
374
417
 
375
 
void awt_create_selection_list_on_table_fields(GBDATA *gb_main,AW_window *aws,const char *table_name, const char *varname)
376
 
{
377
 
    AW_selection_list *id;
 
418
void awt_create_selection_list_on_table_fields(GBDATA *gb_main, AW_window *aws, const char *table_name, const char *varname) {
 
419
    // if tablename == 0 -> take fields from species table
 
420
 
 
421
    AW_selection_list              *id;
378
422
    struct awt_sel_list_for_tables *cbs;
379
423
    GB_push_transaction(gb_main);
380
424
 
381
 
    id = aws->create_selection_list(varname,0,"",40,8);
 
425
    id = aws->create_selection_list(varname, 40, 8, true);
382
426
    cbs = new awt_sel_list_for_tables;
383
427
    cbs->aws = aws;
384
428
    cbs->gb_main = gb_main;
385
429
    cbs->id = id;
386
430
    cbs->table_name = strdup(table_name);
387
431
 
388
 
    awt_create_selection_list_on_table_fields_cb(0,cbs);
 
432
    awt_create_selection_list_on_table_fields_cb(0, cbs);
389
433
 
390
 
    GBDATA  *gb_table = GBT_open_table(gb_main,table_name, GB_TRUE); // read only
391
 
    if (gb_table){
392
 
        GB_add_callback(gb_table,GB_CB_CHANGED,(GB_CB)awt_create_selection_list_on_table_fields_cb, (int *)cbs);
 
434
    GBDATA  *gb_table = GBT_open_table(gb_main, table_name, true); // read only
 
435
    if (gb_table) {
 
436
        GB_add_callback(gb_table, GB_CB_CHANGED, makeDatabaseCallback(awt_create_selection_list_on_table_fields_cb, cbs));
393
437
    }
394
438
    GB_pop_transaction(gb_main);
395
439
}
396
440
 
397
 
// ******************** selection boxes on editor configurations ********************
398
 
 
399
 
void awt_create_selection_list_on_configurations_cb(GBDATA*, struct adawcbstruct *cbs) {
400
 
    cbs->aws->clear_selection_list(cbs->id);
401
 
 
402
 
    int    config_count;
403
 
    char **config = GBT_get_configuration_names_and_count(cbs->gb_main, &config_count);
404
 
 
405
 
    if (config) {
406
 
        for (int c = 0; c<config_count; c++) {
407
 
            cbs->aws->insert_selection(cbs->id, config[c], config[c]);
 
441
// -------------------------------------------------
 
442
//      selection boxes on editor configurations
 
443
 
 
444
struct AWT_configuration_selection : public AW_DB_selection {
 
445
    AWT_configuration_selection(AW_selection_list *sellist_, GBDATA *gb_configuration_data)
 
446
        : AW_DB_selection(sellist_, gb_configuration_data)
 
447
    {}
 
448
 
 
449
    void fill() OVERRIDE {
 
450
        ConstStrArray config;
 
451
        GBT_get_configuration_names(config, get_gb_main());
 
452
 
 
453
        if (!config.empty()) {
 
454
            for (int c = 0; config[c]; c++) insert(config[c], config[c]);
408
455
        }
409
 
        GBT_free_names(config);
410
 
    }
411
 
 
412
 
    cbs->aws->insert_default_selection(cbs->id, "????", "????");
413
 
    cbs->aws->update_selection_list(cbs->id);
414
 
}
415
 
 
416
 
void awt_create_selection_list_on_configurations(GBDATA *gb_main,AW_window *aws,const char *varname)
417
 
{
418
 
    AW_selection_list *id;
419
 
    GBDATA  *gb_configuration_data;
420
 
    GB_push_transaction(gb_main);
421
 
 
422
 
    id = aws->create_selection_list(varname,0,"",40,15);
423
 
    
424
 
    struct adawcbstruct *cbs = new adawcbstruct;
425
 
    memset(cbs, 0, sizeof(*cbs));
426
 
 
427
 
    cbs->aws     = aws;
428
 
    cbs->awr     = aws->get_root();
429
 
    cbs->gb_main = gb_main;
430
 
    cbs->id      = id;
431
 
 
432
 
    awt_create_selection_list_on_configurations_cb(0,cbs);
433
 
 
434
 
    gb_configuration_data = GB_search(gb_main,AWAR_CONFIG_DATA,GB_CREATE_CONTAINER);
435
 
    GB_add_callback(gb_configuration_data,GB_CB_CHANGED,
436
 
                    (GB_CB)awt_create_selection_list_on_configurations_cb, (int *)cbs);
437
 
 
438
 
    GB_pop_transaction(gb_main);
 
456
        insert_default(DISPLAY_NONE, NO_CONFIG_SELECTED);
 
457
    }
 
458
};
 
459
 
 
460
void awt_create_selection_list_on_configurations(GBDATA *gb_main, AW_window *aws, const char *varname, bool fallback2default) {
 
461
    GBDATA *gb_configuration_data;
 
462
    {
 
463
        GB_transaction ta(gb_main);
 
464
        gb_configuration_data = GB_search(gb_main, CONFIG_DATA_PATH, GB_CREATE_CONTAINER);
 
465
    }
 
466
    AW_selection_list *sellist = aws->create_selection_list(varname, 40, 15, fallback2default);
 
467
    (new AWT_configuration_selection(sellist, gb_configuration_data))->refresh();
439
468
}
440
469
 
441
470
char *awt_create_string_on_configurations(GBDATA *gb_main) {
442
471
    // returns semicolon-separated string containing configuration names
443
472
    // (or NULL if no configs exist)
444
 
    
 
473
 
445
474
    GB_push_transaction(gb_main);
446
475
 
447
 
    int    config_count;
448
 
    char **config = GBT_get_configuration_names_and_count(gb_main, &config_count);
449
 
    char  *result = 0;
450
 
 
451
 
    if (config) {
 
476
    ConstStrArray config;
 
477
    GBT_get_configuration_names(config, gb_main);
 
478
 
 
479
    char *result = 0;
 
480
 
 
481
    if (!config.empty()) {
452
482
        GBS_strstruct *out = GBS_stropen(1000);
453
 
        for (int c = 0; c<config_count; c++) {
 
483
        for (int c = 0; config[c]; c++) {
454
484
            if (c>0) GBS_chrcat(out, ';');
455
485
            GBS_strcat(out, config[c]);
456
486
        }
461
491
    return result;
462
492
}
463
493
 
464
 
// ******************** selection boxes on SAIs ********************
465
 
 
466
 
void awt_create_selection_list_on_extendeds_update(GBDATA *dummy, void *cbsid)
467
 
{
468
 
#if defined(DEVEL_RALF)
469
 
    printf("start awt_create_selection_list_on_extendeds_update\n"); // @@@
470
 
#endif // DEVEL_RALF
471
 
 
472
 
    struct awt_sel_list_for_sai *cbs = (struct awt_sel_list_for_sai *)cbsid;
473
 
 
474
 
    AWUSE(dummy);
475
 
    cbs->aws->clear_selection_list(cbs->id);
476
 
    GB_transaction ta(cbs->gb_main);
477
 
 
478
 
    for (GBDATA *gb_extended = GBT_first_SAI(cbs->gb_main);
 
494
// ----------------------
 
495
//      SAI selection
 
496
 
 
497
 
 
498
class AWT_sai_selection : public AW_DB_selection { // derived from a Noncopyable
 
499
    awt_sai_sellist_filter filter_poc;
 
500
    AW_CL                  filter_cd;
 
501
 
 
502
public:
 
503
 
 
504
    AWT_sai_selection(AW_selection_list *sellist_, GBDATA *gb_sai_data, awt_sai_sellist_filter filter_poc_, AW_CL filter_cd_)
 
505
        : AW_DB_selection(sellist_, gb_sai_data),
 
506
          filter_poc(filter_poc_),
 
507
          filter_cd(filter_cd_)
 
508
    {}
 
509
 
 
510
    void fill() OVERRIDE;
 
511
};
 
512
 
 
513
void AWT_sai_selection::fill() {
 
514
    AW_selection_list *sel = get_sellist();
 
515
    sel->clear();
 
516
 
 
517
    GBDATA         *gb_main = get_gb_main();
 
518
    GB_transaction  ta(gb_main);
 
519
 
 
520
    for (GBDATA *gb_extended = GBT_first_SAI(gb_main);
479
521
         gb_extended;
480
522
         gb_extended = GBT_next_SAI(gb_extended))
481
523
    {
482
 
        if (cbs->filter_poc) {
483
 
            char *res = cbs->filter_poc(gb_extended,cbs->filter_cd);
 
524
        if (filter_poc) {
 
525
            char *res = filter_poc(gb_extended, filter_cd);
484
526
            if (res) {
485
 
                cbs->aws->insert_selection( cbs->id, res, GBT_read_name(gb_extended));
 
527
                sel->insert(res, GBT_read_name(gb_extended));
486
528
                free(res);
487
529
            }
488
530
        }
493
535
            if (gb_group) {
494
536
                const char *group          = GB_read_char_pntr(gb_group);
495
537
                char       *group_and_name = GBS_global_string_copy("[%s] %s", group, name);
496
 
                
497
 
                cbs->aws->insert_selection(cbs->id, group_and_name, name);
 
538
 
 
539
                sel->insert(group_and_name, name);
498
540
                free(group_and_name);
499
541
            }
500
542
            else {
501
 
                cbs->aws->insert_selection( cbs->id, name, name );
502
 
            }
503
 
        }
504
 
    }
505
 
    cbs->aws->sort_selection_list(cbs->id, 0, 0);
506
 
 
507
 
    if (cbs->add_selected_species) {
508
 
        GBDATA *gb_sel = GB_search(cbs->gb_main,AWAR_SPECIES_NAME,GB_STRING);
509
 
        char   *name   = GB_read_string(gb_sel);
510
 
        if (strlen(name)){
511
 
            char *sname = (char *)calloc(1, strlen(name)+2);
512
 
            sprintf(sname+1,"%s",name);
513
 
            sname[0] = 1;
514
 
            char *text = (char *)GBS_global_string("Selected Species: '%s'",name);
515
 
            cbs->aws->insert_selection( cbs->id, text, sname );
516
 
            delete name;
517
 
        }
518
 
        delete name;
519
 
    }
520
 
    cbs->aws->insert_default_selection( cbs->id, "- none -", "none" );
521
 
    cbs->aws->update_selection_list( cbs->id );
522
 
    
523
 
#if defined(DEVEL_RALF)
524
 
    printf("done  awt_create_selection_list_on_extendeds_update\n"); // @@@
525
 
#endif // DEVEL_RALF
526
 
}
527
 
 
528
 
void *awt_create_selection_list_on_extendeds(GBDATA *gb_main,AW_window *aws, const char *varname,
529
 
                                             char *(*filter_poc)(GBDATA *gb_ext, AW_CL), AW_CL filter_cd,
530
 
                                             bool add_sel_species)
531
 
{
532
 
    AW_selection_list           *id;
533
 
    struct awt_sel_list_for_sai *cbs;
534
 
 
535
 
    GB_push_transaction(gb_main);
536
 
 
537
 
    id  = aws->create_selection_list(varname,0,"",40,4);
538
 
    cbs = new awt_sel_list_for_sai;
539
 
 
540
 
    cbs->aws                  = aws;
541
 
    cbs->gb_main              = gb_main;
542
 
    cbs->id                   = id;
543
 
    cbs->filter_poc           = filter_poc;
544
 
    cbs->filter_cd            = filter_cd;
545
 
    cbs->add_selected_species = add_sel_species;
546
 
 
547
 
    awt_create_selection_list_on_extendeds_update(0,(void *)cbs);
548
 
 
549
 
    GBDATA *gb_sai_data = GBT_get_SAI_data(gb_main);
550
 
    GB_add_callback(gb_sai_data,GB_CB_CHANGED, (GB_CB)awt_create_selection_list_on_extendeds_update, (int *)cbs);
551
 
 
552
 
    if (add_sel_species){       // update box if another species is selected
553
 
        GBDATA *gb_sel = GB_search(gb_main,AWAR_SPECIES_NAME,GB_STRING);
554
 
        GB_add_callback(gb_sel,GB_CB_CHANGED, (GB_CB)awt_create_selection_list_on_extendeds_update, (int *)cbs);
555
 
    }
556
 
    GB_pop_transaction(gb_main);
557
 
 
558
 
    return (void *)cbs;
559
 
}
560
 
 
561
 
 
562
 
 
563
 
 
564
 
// ******************** selection boxes on saving selection lists ********************
565
 
 
566
 
void create_save_box_for_selection_lists_save(AW_window *aws,AW_CL selidcd,AW_CL basenamecd)
567
 
{
568
 
    AW_selection_list *selid       = (AW_selection_list *)selidcd;
569
 
    char              *awar_prefix = (char *)basenamecd;
570
 
 
571
 
    char bline_anz[GB_PATH_MAX];
572
 
    sprintf(bline_anz,"%s/line_anz",awar_prefix);
573
 
 
574
 
    AW_root *aw_root  = aws->get_root();
575
 
    long     lineanz  = aw_root->awar(bline_anz)->read_int();
576
 
    char    *filename = awt_get_selected_fullname(aw_root, awar_prefix);
577
 
 
578
 
    GB_ERROR error = aws->save_selection_list(selid,filename,lineanz);
579
 
 
580
 
    if (!error) awt_refresh_selection_box(aw_root, awar_prefix);
581
 
    aws->hide_or_notify(error);
582
 
    free(filename);
583
 
}
584
 
 
585
 
AW_window *create_save_box_for_selection_lists(AW_root *aw_root,AW_CL selid)
586
 
{
587
 
    AW_selection_list *selection_list = (AW_selection_list*)selid;
588
 
 
589
 
    char *var_id         = GBS_string_2_key(selection_list->variable_name);
590
 
    char *awar_base_name = GBS_global_string_copy("tmp/save_box_sel_%s", var_id); // don't free (passed to callback)
591
 
    char *awar_line_anz  = GBS_global_string_copy("%s/line_anz", awar_base_name);
 
543
                sel->insert(name, name);
 
544
            }
 
545
        }
 
546
    }
 
547
    sel->sort(false, false);
 
548
 
 
549
    sel->insert_default(DISPLAY_NONE, "");
 
550
    sel->update();
 
551
}
 
552
 
 
553
void awt_selection_list_on_sai_update_cb(UNFIXED, AWT_sai_selection *saisel) {
 
554
    /* update the selection box defined by awt_create_selection_list_on_sai
 
555
     *
 
556
     * useful only when filterproc is defined
 
557
     * (changes to SAIs will automatically callback this function)
 
558
     */
 
559
 
 
560
    saisel->refresh();
 
561
}
 
562
 
 
563
AWT_sai_selection *SAI_selection_list_spec::create_list(AW_window *aws, bool fallback2default) const {
 
564
    GB_transaction ta(gb_main);
 
565
 
 
566
    AW_selection_list *sellist     = aws->create_selection_list(awar_name, 40, 4, fallback2default);
 
567
    GBDATA            *gb_sai_data = GBT_get_SAI_data(gb_main);
 
568
    AWT_sai_selection *saisel      = new AWT_sai_selection(sellist, gb_sai_data, filter_poc, filter_cd);
 
569
 
 
570
    awt_selection_list_on_sai_update_cb(0, saisel);
 
571
    GB_add_callback(gb_sai_data, GB_CB_CHANGED, makeDatabaseCallback(awt_selection_list_on_sai_update_cb, saisel));
 
572
 
 
573
    return saisel;
 
574
}
 
575
 
 
576
static void popup_filtered_sai_selection_list(AW_root *aw_root, const SAI_selection_list_spec *spec) {
 
577
    const char *awar_name = spec->get_awar_name();
 
578
 
 
579
    static GB_HASH *SAI_window_hash       = 0;
 
580
    if (!SAI_window_hash) SAI_window_hash = GBS_create_hash(10, GB_MIND_CASE);
 
581
 
 
582
    AW_window_simple *aws = reinterpret_cast<AW_window_simple *>(GBS_read_hash(SAI_window_hash, awar_name));
 
583
 
 
584
    if (!aws) {
 
585
        aws = new AW_window_simple;
 
586
        aws->init(aw_root, "SELECT_SAI", "SELECT SAI");
 
587
        aws->load_xfig("select_simple.fig");
 
588
 
 
589
        aws->at("selection");
 
590
        aws->callback((AW_CB0)AW_POPDOWN);
 
591
        spec->create_list(aws, true);
 
592
 
 
593
        aws->at("button");
 
594
        aws->callback(AW_POPDOWN);
 
595
        aws->create_button("CLOSE", "CLOSE", "C");
 
596
 
 
597
        aws->window_fit();
 
598
 
 
599
        GBS_write_hash(SAI_window_hash, awar_name, reinterpret_cast<long>(aws));
 
600
    }
 
601
 
 
602
    aws->activate();
 
603
}
 
604
static void popup_filtered_sai_selection_list(AW_window *aww, const SAI_selection_list_spec *spec) {
 
605
    popup_filtered_sai_selection_list(aww->get_root(), spec);
 
606
}
 
607
 
 
608
void awt_popup_sai_selection_list(AW_window *aww, const char *awar_name, GBDATA *gb_main) {
 
609
    SAI_selection_list_spec spec(awar_name, gb_main);
 
610
    popup_filtered_sai_selection_list(aww, &spec);
 
611
}
 
612
 
 
613
AWT_sai_selection *awt_create_selection_list_on_sai(GBDATA *gb_main, AW_window *aws, const char *varname, bool fallback2default, awt_sai_sellist_filter filter_poc, AW_CL filter_cd) {
 
614
    /* Selection list for SAIs
 
615
     *
 
616
     * if filter_proc is set then show only those items on which
 
617
     * filter_proc returns a string (string must be a heap copy)
 
618
     */
 
619
    SAI_selection_list_spec spec(varname, gb_main);
 
620
    spec.define_filter(filter_poc, filter_cd);
 
621
    return spec.create_list(aws, fallback2default);
 
622
}
 
623
 
 
624
void awt_create_SAI_selection_button(GBDATA *gb_main, AW_window *aws, const char *varname, awt_sai_sellist_filter filter_poc, AW_CL filter_cd) {
 
625
    SAI_selection_list_spec *spec = new SAI_selection_list_spec(varname, gb_main);
 
626
    spec->define_filter(filter_poc, filter_cd);
 
627
    aws->callback(makeWindowCallback(popup_filtered_sai_selection_list, spec));
 
628
    aws->create_button("SELECT_SAI", varname);
 
629
}
 
630
 
 
631
// --------------------------------------------------
 
632
//      save/load selection content to/from file
 
633
 
 
634
static GB_ERROR standard_list2file(const CharPtrArray& display, const CharPtrArray& value, StrArray& line) {
 
635
    GB_ERROR error = NULL;
 
636
    for (size_t i = 0; i<display.size() && !error; ++i) {
 
637
        const char *disp = display[i];
 
638
 
 
639
        if (disp[0] == '#') { // would interpret as comment when loaded
 
640
            error = "Invalid character '#' at start of displayed text (won't load)";
 
641
        }
 
642
        else {
 
643
            if (strchr(disp, ',')) {
 
644
                // would be interpreted as separator between display and value on load
 
645
                error = "Invalid character ',' in displayed text (won't load correctly)";
 
646
            }
 
647
            else {
 
648
                awt_assert(strchr(disp, '\n') == 0);
 
649
 
 
650
                const char *val = value[i];
 
651
                if (strcmp(disp, val) == 0) {
 
652
                    line.put(strdup(disp));
 
653
                }
 
654
                else {
 
655
                    char *escaped = GBS_escape_string(val, "\n", '\\');
 
656
                    line.put(GBS_global_string_copy("%s,%s", disp, escaped));
 
657
                    free(escaped);
 
658
                }
 
659
            }
 
660
        }
 
661
    }
 
662
    return NULL;
 
663
}
 
664
 
 
665
 
 
666
 
 
667
static GB_ERROR standard_file2list(const CharPtrArray& line, StrArray& display, StrArray& value) {
 
668
    for (size_t i = 0; i<line.size(); ++i) {
 
669
        if (line[i][0] == '#') continue; // ignore comments
 
670
 
 
671
        const char *comma = strchr(line[i], ',');
 
672
        if (comma) {
 
673
            display.put(GB_strpartdup(line[i], comma-1));
 
674
 
 
675
            comma++;
 
676
            const char *rest      = comma+strspn(comma, " \t");
 
677
            char       *unescaped = GBS_unescape_string(rest, "\n", '\\');
 
678
            value.put(unescaped);
 
679
        }
 
680
        else {
 
681
            display.put(strdup(line[i]));
 
682
            value.put(strdup(line[i]));
 
683
        }
 
684
    }
 
685
 
 
686
    return NULL;
 
687
}
 
688
 
 
689
StorableSelectionList::StorableSelectionList(const TypedSelectionList& tsl_)
 
690
    : tsl(tsl_),
 
691
      list2file(standard_list2file), 
 
692
      file2list(standard_file2list)
 
693
{}
 
694
 
 
695
inline char *get_shared_sellist_awar_base(const TypedSelectionList& typedsellst) {
 
696
    return GBS_global_string_copy("tmp/sellist/%s", typedsellst.get_shared_id());
 
697
}
 
698
inline char *get_shared_sellist_awar_name(const TypedSelectionList& typedsellst, const char *name) {
 
699
    char *base      = get_shared_sellist_awar_base(typedsellst);
 
700
    char *awar_name = GBS_global_string_copy("%s/%s", base, name);
 
701
    free(base);
 
702
    return awar_name;
 
703
}
 
704
 
 
705
GB_ERROR StorableSelectionList::save(const char *filename, long number_of_lines) const {
 
706
    // number_of_lines == 0 -> save all lines (otherwise truncate after 'number_of_lines')
 
707
 
 
708
    StrArray           display, values;
 
709
    AW_selection_list *sellist = tsl.get_sellist();
 
710
 
 
711
    sellist->to_array(display, false);
 
712
    sellist->to_array(values, true);
 
713
 
 
714
    awt_assert(display.size() == values.size());
 
715
 
 
716
    if (number_of_lines>0) { // limit number of lines?
 
717
        display.resize(number_of_lines);
 
718
        values.resize(number_of_lines);
 
719
    }
 
720
 
 
721
    GB_ERROR error = NULL;
 
722
    if (display.size()<1) {
 
723
        error = "List is empty (did not save)";
 
724
    }
 
725
    else {
 
726
        StrArray line;
 
727
        error = list2file(display, values, line);
 
728
        if (!error) {
 
729
            if (line.size()<1) {
 
730
                error = "list>file conversion produced nothing (internal error)";
 
731
            }
 
732
            else {
 
733
                FILE *out = fopen(filename, "wt");
 
734
                if (!out) {
 
735
                    error = GB_IO_error("writing", filename);
 
736
                }
 
737
                else {
 
738
                    const char *warning = NULL;
 
739
                    for (size_t i = 0; i<line.size(); ++i) {
 
740
                        if (!warning && strchr(line[i], '\n')) {
 
741
                            warning = "Warning: Saved content contains LFs (loading will be impossible)";
 
742
                        }
 
743
                        fputs(line[i], out);
 
744
                        fputc('\n', out);
 
745
                    }
 
746
                    fclose(out);
 
747
                    error = warning;
 
748
                }
 
749
            }
 
750
        }
 
751
    }
 
752
 
 
753
    return error;
 
754
}
 
755
 
 
756
 
 
757
 
 
758
inline char *string2heapcopy(const string& s) {
 
759
    char *copy = (char*)malloc(s.length()+1);
 
760
    memcpy(copy, s.c_str(), s.length()+1);
 
761
    return copy;
 
762
}
 
763
 
 
764
GB_ERROR StorableSelectionList::load(const char *filemask, bool append) const {
 
765
    GB_ERROR error = NULL;
 
766
    StrArray fnames;
 
767
 
 
768
    if (GB_is_directory(filemask)) {
 
769
        error = GBS_global_string("refusing to load all files from directory\n"
 
770
                                  "'%s'\n"
 
771
                                  "(one possibility is to enter '*.%s')'",
 
772
                                  filemask, get_filter());
 
773
    }
 
774
    else {
 
775
        GBS_read_dir(fnames, filemask, NULL);
 
776
        if (fnames.empty() && GB_have_error()) {
 
777
            error = GB_await_error();
 
778
        }
 
779
    }
 
780
 
 
781
    StrArray lines;
 
782
    for (int f = 0; fnames[f] && !error; ++f) {
 
783
        FILE *in = fopen(fnames[f], "rb");
 
784
        if (!in) {
 
785
            error = GB_IO_error("reading", fnames[f]);
 
786
        }
 
787
        else {
 
788
            BufferedFileReader file(fnames[f], in);
 
789
            string line;
 
790
            while (file.getLine(line)) {
 
791
                if (!line.empty()) lines.put(string2heapcopy(line));
 
792
            }
 
793
        }
 
794
    }
 
795
 
 
796
    AW_selection_list *sellist = tsl.get_sellist();
 
797
    if (!append) sellist->clear();
 
798
 
 
799
    if (!error) {
 
800
        StrArray displayed, values;
 
801
        error = file2list(lines, displayed, values);
 
802
        if (!error) {
 
803
            int dsize = displayed.size();
 
804
            int vsize = values.size();
 
805
 
 
806
            if (dsize != vsize) {
 
807
                error = GBS_global_string("Error in translation (value/display mismatch: %i!=%i)", vsize, dsize);
 
808
            }
 
809
            else {
 
810
                for (int i = 0; i<dsize; ++i) {
 
811
                    sellist->insert(displayed[i], values[i]);
 
812
                }
 
813
                sellist->insert_default("", "");
 
814
            }
 
815
        }
 
816
    }
 
817
 
 
818
    if (error) {
 
819
        sellist->insert_default(GBS_global_string("Error: %s", error), "");
 
820
    }
 
821
    sellist->update();
 
822
 
 
823
    return error;
 
824
}
 
825
 
 
826
static void save_list_cb(AW_window *aww, const StorableSelectionList *storabsellist) {
 
827
    const TypedSelectionList& typedsellist = storabsellist->get_typedsellist();
 
828
 
 
829
    char    *awar_prefix = get_shared_sellist_awar_base(typedsellist);
 
830
    char    *bline_anz   = get_shared_sellist_awar_name(typedsellist, "line_anz");
 
831
    AW_root *aw_root     = aww->get_root();
 
832
    char    *filename    = AW_get_selected_fullname(aw_root, awar_prefix);
 
833
 
 
834
    long     lineLimit = aw_root->awar(bline_anz)->read_int();
 
835
    GB_ERROR error     = storabsellist->save(filename, lineLimit);
 
836
 
 
837
    if (!error) AW_refresh_fileselection(aw_root, awar_prefix);
 
838
    aww->hide_or_notify(error);
 
839
 
 
840
    free(filename);
 
841
    free(bline_anz);
 
842
    free(awar_prefix);
 
843
}
 
844
 
 
845
static void load_list_cb(AW_window *aww, const StorableSelectionList *storabsellist) {
 
846
    const TypedSelectionList& typedsellist = storabsellist->get_typedsellist();
 
847
 
 
848
    AW_root  *aw_root     = aww->get_root();
 
849
    char     *awar_prefix = get_shared_sellist_awar_base(typedsellist);
 
850
    char     *awar_append = get_shared_sellist_awar_name(typedsellist, "append");
 
851
    bool      append      = aw_root->awar(awar_append)->read_int();
 
852
    char     *filename    = AW_get_selected_fullname(aw_root, awar_prefix);
 
853
    GB_ERROR  error       = storabsellist->load(filename, append);
 
854
 
 
855
    aww->hide_or_notify(error);
 
856
 
 
857
    free(filename);
 
858
    free(awar_append);
 
859
    free(awar_prefix);
 
860
}
 
861
 
 
862
AW_window *create_save_box_for_selection_lists(AW_root *aw_root, const StorableSelectionList *storabsellist) {
 
863
    const TypedSelectionList& typedsellist = storabsellist->get_typedsellist();
 
864
 
 
865
    char *awar_base     = get_shared_sellist_awar_base(typedsellist);
 
866
    char *awar_line_anz = get_shared_sellist_awar_name(typedsellist, "line_anz");
592
867
    {
593
 
        aw_create_selection_box_awars(aw_root, awar_base_name, ".", GBS_global_string("noname.list"), "list");
 
868
        char *def_name = GBS_string_2_key(typedsellist.whats_contained());
 
869
        AW_create_fileselection_awars(aw_root, awar_base, ".", storabsellist->get_filter(), def_name);
 
870
        free(def_name);
594
871
        aw_root->awar_int(awar_line_anz, 0, AW_ROOT_DEFAULT);
595
872
    }
596
873
 
597
 
    AW_window_simple *aws       = new AW_window_simple;
598
 
    char             *window_id = GBS_global_string_copy("SAVE_SELECTION_BOX_%s", var_id);
599
 
 
600
 
    aws->init(aw_root, window_id, "SAVE BOX");
 
874
    AW_window_simple *aws = new AW_window_simple;
 
875
 
 
876
    char *window_id    = GBS_global_string_copy("SAVE_SELECTION_BOX_%s", typedsellist.get_unique_id());
 
877
    char *window_title = GBS_global_string_copy("Save %s", typedsellist.whats_contained());
 
878
 
 
879
    aws->init(aw_root, window_id, window_title);
601
880
    aws->load_xfig("sl_s_box.fig");
602
881
 
603
 
    aws->at("close");aws->callback((AW_CB0)AW_POPDOWN);
604
 
    aws->create_button("CLOSE", "CLOSE","C");
 
882
    aws->button_length(10);
 
883
 
 
884
    aws->at("cancel");
 
885
    aws->callback((AW_CB0)AW_POPDOWN);
 
886
    aws->create_button("CANCEL", "CANCEL", "C");
605
887
 
606
888
    aws->at("save");
607
889
    aws->highlight();
608
 
    aws->callback(create_save_box_for_selection_lists_save,selid,(AW_CL)awar_base_name); // loose ownership of awar_base_name!
609
 
    aws->create_button("SAVE", "SAVE","S");
 
890
    aws->callback(makeWindowCallback(save_list_cb, storabsellist));
 
891
    aws->create_button("SAVE", "SAVE", "S");
610
892
 
611
893
    aws->at("nlines");
612
 
    aws->create_option_menu(awar_line_anz, 0, "");
613
 
    aws->insert_default_option("all","a",0);
614
 
    aws->insert_option(   "50", "a",    50);
615
 
    aws->insert_option(  "100", "a",   100);
616
 
    aws->insert_option(  "500", "a",   500);
617
 
    aws->insert_option( "1000", "a",  1000);
618
 
    aws->insert_option( "5000", "a",  5000);
619
 
    aws->insert_option("10000", "a", 10000);
 
894
    aws->create_option_menu(awar_line_anz, true);
 
895
    aws->insert_default_option("all",   "a", 0);
 
896
    aws->insert_option        ("10",    "",  10);
 
897
    aws->insert_option        ("50",    "",  50);
 
898
    aws->insert_option        ("100",   "",  100);
 
899
    aws->insert_option        ("500",   "",  500);
 
900
    aws->insert_option        ("1000",  "",  1000);
 
901
    aws->insert_option        ("5000",  "",  5000);
 
902
    aws->insert_option        ("10000", "",  10000);
620
903
    aws->update_option_menu();
621
904
 
622
 
    awt_create_selection_box(aws,awar_base_name);
 
905
    AW_create_standard_fileselection(aws, awar_base);
623
906
 
 
907
    free(window_title);
624
908
    free(window_id);
625
909
    free(awar_line_anz);
626
 
    free(var_id);
 
910
    free(awar_base);
 
911
 
 
912
    aws->recalc_pos_atShow(AW_REPOS_TO_MOUSE);
627
913
 
628
914
    return aws;
629
915
}
630
916
 
631
 
void AWT_load_list(AW_window *aww, AW_CL sel_id, AW_CL ibase_name)
632
 
{
633
 
    AW_selection_list * selid       = (AW_selection_list *)sel_id;
634
 
    char *basename = (char *)ibase_name;
635
 
 
636
 
    AW_root     *aw_root    = aww->get_root();
637
 
    GB_ERROR    error;
638
 
 
639
 
    //     char     bfile_name[GB_PATH_MAX];
640
 
    //     sprintf(bfile_name,"%s/file_name",basename);
641
 
    //     char *filename = aw_root->awar(bfile_name)->read_string();
642
 
 
643
 
    char *filename = awt_get_selected_fullname(aw_root, basename);
644
 
    error          = aww->load_selection_list(selid,filename);
645
 
 
646
 
    if (error) aw_message(error);
647
 
 
648
 
    AW_POPDOWN(aww);
649
 
 
650
 
    delete filename;
651
 
}
652
 
 
653
 
AW_window *create_load_box_for_selection_lists(AW_root *aw_root, AW_CL selid)
654
 
{
655
 
    char base_name[100];
656
 
    sprintf(base_name,"tmp/load_box_sel_%li",(long)selid);
657
 
 
658
 
    aw_create_selection_box_awars(aw_root, base_name, ".", "list", "");
 
917
AW_window *create_load_box_for_selection_lists(AW_root *aw_root, const StorableSelectionList *storabsellist) {
 
918
    const TypedSelectionList& typedsellist = storabsellist->get_typedsellist();
 
919
 
 
920
    char *awar_base_name = get_shared_sellist_awar_base(typedsellist);
 
921
    char *awar_append    = get_shared_sellist_awar_name(typedsellist, "append");
 
922
 
 
923
    AW_create_fileselection_awars(aw_root, awar_base_name, ".", storabsellist->get_filter(), "");
 
924
    aw_root->awar_int(awar_append, 1); // append is default ( = old behavior)
659
925
 
660
926
    AW_window_simple *aws = new AW_window_simple;
661
 
    aws->init( aw_root, "LOAD_SELECTION_BOX", "Load box");
 
927
 
 
928
    char *window_id    = GBS_global_string_copy("LOAD_SELECTION_BOX_%s", typedsellist.get_unique_id());
 
929
    char *window_title = GBS_global_string_copy("Load %s", typedsellist.whats_contained());
 
930
 
 
931
    aws->init(aw_root, window_id, window_title);
662
932
    aws->load_xfig("sl_l_box.fig");
663
933
 
664
 
    aws->at("close");
 
934
    aws->at("cancel");
665
935
    aws->callback((AW_CB0)AW_POPDOWN);
666
 
    aws->create_button("CLOSE", "CLOSE","C");
 
936
    aws->create_button("CANCEL", "CANCEL", "C");
667
937
 
668
938
    aws->at("load");
669
939
    aws->highlight();
670
 
    aws->callback(AWT_load_list,selid,(AW_CL)strdup(base_name));
671
 
    aws->create_button("LOAD", "LOAD","L");
672
 
 
673
 
    awt_create_selection_box((AW_window *)aws,base_name);
674
 
    return (AW_window*) aws;
675
 
}
676
 
 
677
 
 
678
 
void create_print_box_for_selection_lists(AW_window *aw_window,AW_CL selid){
679
 
    AW_root *aw_root = aw_window->get_root();
680
 
    char *data = aw_window->get_selection_list_contents((AW_selection_list *)selid);
681
 
    AWT_create_ascii_print_window(aw_root,data,"no title");
682
 
    delete data;
683
 
}
684
 
 
685
 
 
686
 
 
687
 
/* ************************************************** */
688
 
AW_window *awt_create_load_box(AW_root *aw_root, const char *load_what, const char *file_extension, char **set_file_name_awar,
689
 
                               void (*callback)(AW_window*),
690
 
                               AW_window* (*create_popup)(AW_root *, AW_default))
691
 
 
692
 
    /*      You can either provide a normal callback or a create_popup-callback
693
 
     *      (the not-used callback has to be 0)
 
940
    aws->callback(makeWindowCallback(load_list_cb, storabsellist));
 
941
    aws->create_button("LOAD", "LOAD", "L");
 
942
 
 
943
    aws->at("append");
 
944
    aws->label("Append?");
 
945
    aws->create_toggle(awar_append);
 
946
 
 
947
    AW_create_fileselection(aws, awar_base_name, "", "PWD", ANY_DIR, true);
 
948
 
 
949
    aws->recalc_pos_atShow(AW_REPOS_TO_MOUSE);
 
950
 
 
951
    free(window_title);
 
952
    free(window_id);
 
953
    free(awar_append);
 
954
    free(awar_base_name);
 
955
 
 
956
    return aws;
 
957
}
 
958
 
 
959
void awt_clear_selection_list_cb(AW_window *, AW_selection_list *sellist) {
 
960
    sellist->clear();
 
961
    sellist->insert_default("", "");
 
962
    sellist->update();
 
963
}
 
964
 
 
965
void create_print_box_for_selection_lists(AW_window *aw_window, const TypedSelectionList *typedsellist) {
 
966
    char *data = typedsellist->get_sellist()->get_content_as_string(0);
 
967
    AWT_create_ascii_print_window(aw_window->get_root(), data, typedsellist->whats_contained());
 
968
    free(data);
 
969
}
 
970
 
 
971
AW_window *awt_create_load_box(AW_root     *aw_root,
 
972
                               const char  *action,
 
973
                               const char  *what,
 
974
                               const char  *default_directory,
 
975
                               const char  *file_extension,
 
976
                               char       **set_file_name_awar,
 
977
                               const WindowCallback& ok_cb,
 
978
                               const WindowCallback& close_cb,
 
979
                               const char *close_button_text)
 
980
{
 
981
    /* general purpose file selection box
 
982
     *
 
983
     * 'action' describes what is intended to be done (e.g. "Load").
 
984
     * used for window title and button.
 
985
     *
 
986
     * 'what' describes what is going to be loaded (e.g. "destination database")
 
987
     * It is also used to create the awars for the filebox, i.e. same description for multiple
 
988
     * fileboxes makes them share the awars.
 
989
     *
 
990
     * if 'set_file_name_awar' is non-NULL, it'll be set to a heap-copy of the awar-name
 
991
     * containing the full selected filename.
 
992
     *
 
993
     * 'default_directory' specifies the directory opened in the filebox
 
994
     *
 
995
     * 'file_extension' specifies the filter to be used (which files are shown)
 
996
     *
 
997
     * You have to provide an 'ok_cb', which will be called when 'OK' is pressed.
 
998
     * Optionally you may pass a 'close_cb' which will be called when 'CLOSE' is pressed.
 
999
     * If not given, AW_POPDOWN will be called.
 
1000
     *
 
1001
     * Both callbacks will be called as callbacks of the load-box-window.
 
1002
     * The load-box does not popdown, the callback has to do that.
 
1003
     *
 
1004
     * Optionally you may also pass the button text for the 'CLOSE'-button (e.g. 'EXIT' or 'Abort')
694
1005
     */
695
1006
 
696
1007
 
697
 
{
698
 
    char *base_name = GBS_global_string_copy("tmp/load_box_%s",load_what);
 
1008
    char *what_key  = GBS_string_2_key(what);
 
1009
    char *base_name = GBS_global_string_copy("tmp/load_box_%s", what_key);
699
1010
 
700
 
    aw_create_selection_box_awars(aw_root, base_name, ".", file_extension, "");
 
1011
    AW_create_fileselection_awars(aw_root, base_name, default_directory, file_extension, "");
701
1012
 
702
1013
    if (set_file_name_awar) {
703
1014
        *set_file_name_awar = GBS_global_string_copy("%s/file_name", base_name);
706
1017
    AW_window_simple *aws = new AW_window_simple;
707
1018
    {
708
1019
        char title[100];
709
 
        sprintf(title, "Load %s", load_what);
710
 
        aws->init( aw_root, title, title);
 
1020
        sprintf(title, "%s %s", action, what);
 
1021
        aws->init(aw_root, title, title);
711
1022
        aws->load_xfig("load_box.fig");
712
1023
    }
713
1024
 
714
1025
    aws->at("close");
715
 
    aws->callback((AW_CB0)AW_POPDOWN);
716
 
    aws->create_button("CLOSE", "CLOSE","C");
 
1026
    aws->callback(close_cb);
 
1027
    if (close_button_text) {
 
1028
        aws->create_button("CLOSE", close_button_text, "");
 
1029
    }
 
1030
    else {
 
1031
        aws->create_button("CLOSE", "CLOSE", "C");
 
1032
    }
 
1033
#if defined(ARB_GTK)
 
1034
    aws->set_close_action("CLOSE");
 
1035
#endif
717
1036
 
 
1037
#if 0
 
1038
    // @@@ allow to pass helpfile
718
1039
    aws->at("help");
719
 
    aws->callback(AW_POPUP_HELP,(AW_CL)"");
720
 
    aws->create_button("HELP","HELP");
 
1040
    aws->callback(makeHelpCallback(""));
 
1041
    aws->create_button("HELP", "HELP");
 
1042
#endif
721
1043
 
722
1044
    aws->at("go");
723
 
    aws->highlight();
724
 
 
725
 
    if (callback) {
726
 
        awt_assert(!create_popup);
727
 
        aws->callback((AW_CB0)callback);
728
 
    }
729
 
    else  {
730
 
        awt_assert(create_popup);
731
 
        aws->callback((AW_CB1)AW_POPUP, (AW_CL)create_popup);
732
 
    }
733
 
 
734
 
    aws->create_button("LOAD", "LOAD","L");
735
 
 
736
 
    awt_create_selection_box((AW_window *)aws,base_name);
 
1045
    aws->callback(ok_cb);
 
1046
    aws->create_button("GO", action);
 
1047
 
 
1048
    AW_create_standard_fileselection(aws, base_name);
737
1049
    free(base_name);
738
 
    return (AW_window*) aws;
739
 
}
740
 
 
741
 
/* ************************************************** */
742
 
 
743
 
 
744
 
 
745
 
void awt_set_long(AW_window *aws, AW_CL varname, AW_CL value)   // set an awar
746
 
{
747
 
    aws->get_root()->awar((char *)varname)->write_int((long) value);
748
 
}
749
 
 
750
 
void awt_write_string( AW_window *aws, AW_CL varname, AW_CL value)  // set an awar
751
 
{
752
 
    aws->get_root()->awar((char *)varname)->write_string((char *)value);
753
 
}
754
 
 
755
 
struct fileChanged_cb_data {
756
 
    char               *fpath;  // full name of edited file
757
 
    int                 lastModtime; // last known modification time of 'fpath'
758
 
    bool                editorTerminated; // do not free before this has been set to 'true'
759
 
    awt_fileChanged_cb  callback;
760
 
 
761
 
    fileChanged_cb_data(char **fpath_ptr, awt_fileChanged_cb cb) {
762
 
        fpath            = *fpath_ptr;
763
 
        *fpath_ptr       = 0;   // take ownage
764
 
        lastModtime      = getModtime();
765
 
        editorTerminated = false;
766
 
        callback         = cb;
767
 
    }
768
 
 
769
 
    ~fileChanged_cb_data() {
770
 
        free(fpath);
771
 
    }
772
 
 
773
 
    int getModtime() {
774
 
        struct stat st;
775
 
        if (stat(fpath, &st) == 0) return st.st_mtime;
776
 
        return 0;
777
 
    }
778
 
 
779
 
    bool fileWasChanged() {
780
 
        int  modtime = getModtime();
781
 
        bool changed = modtime != lastModtime;
782
 
        lastModtime  = modtime;
783
 
        return changed;
 
1050
    free(what_key);
 
1051
    aws->recalc_pos_atShow(AW_REPOS_TO_MOUSE);
 
1052
 
 
1053
    return aws;
 
1054
}
 
1055
 
 
1056
// --------------------------------------------------------------------------------
 
1057
 
 
1058
#define SUBSET_NOELEM_DISPLAY "<none>"
 
1059
 
 
1060
class AW_subset_selection : public AW_selection {
 
1061
    AW_selection_list& parent_sellist;
 
1062
 
 
1063
    static void finish_fill_box(AW_selection_list *parent_sellist, AW_selection_list *sub_sellist) {
 
1064
        sub_sellist->insert_default(parent_sellist->get_default_display(), parent_sellist->get_default_value());
 
1065
        sub_sellist->update();
 
1066
    }
 
1067
 
 
1068
    static AW_selection_list *create_box(AW_window *aww, AW_selection_list& parent_sellist) {
 
1069
        const char *parent_awar_name = parent_sellist.get_awar_name();
 
1070
        awt_assert(parent_awar_name[0] != '/');
 
1071
        awt_assert(parent_sellist.get_awar_type() == GB_STRING); // only impl for strings
 
1072
 
 
1073
        AW_root *aw_root   = aww->get_root();
 
1074
        char    *awar_name = GBS_global_string_copy("tmp/subsel/%s", parent_awar_name);
 
1075
 
 
1076
        aw_root->awar_string(awar_name);
 
1077
 
 
1078
        AW_selection_list *sub_sellist = aww->create_selection_list(awar_name, true);
 
1079
        finish_fill_box(&parent_sellist, sub_sellist);
 
1080
 
 
1081
        free(awar_name);
 
1082
 
 
1083
        return sub_sellist;
 
1084
    }
 
1085
 
 
1086
public:
 
1087
    AW_subset_selection(AW_window *aww, AW_selection_list& parent_sellist_)
 
1088
        : AW_selection(create_box(aww, parent_sellist_)),
 
1089
          parent_sellist(parent_sellist_)
 
1090
    {}
 
1091
 
 
1092
    AW_selection_list *get_parent_sellist() const { return &parent_sellist; }
 
1093
 
 
1094
    const char *default_select_value() const { return parent_sellist.get_default_value(); }
 
1095
    const char *default_select_display() const { return parent_sellist.get_default_display(); }
 
1096
 
 
1097
    void get_subset(StrArray& subset) {
 
1098
        get_sellist()->to_array(subset, true);
 
1099
    }
 
1100
 
 
1101
    void fill() OVERRIDE { awt_assert(0); } // unused
 
1102
 
 
1103
    void collect_subset_cb(awt_collect_mode what) {
 
1104
        AW_selection_list *subset_list = get_sellist();
 
1105
        AW_selection_list *whole_list  = get_parent_sellist();
 
1106
 
 
1107
        switch(what) {
 
1108
            case ACM_FILL:
 
1109
                for (AW_selection_list_iterator listEntry(whole_list); listEntry; ++listEntry) {
 
1110
                    if (subset_list->get_index_of(listEntry.get_value()) == -1) { // only add not already existing elements
 
1111
                        subset_list->insert(listEntry.get_displayed(), listEntry.get_value());
 
1112
                    }
 
1113
                }
 
1114
                finish_fill_box(whole_list, subset_list);
 
1115
                break;
 
1116
 
 
1117
            case ACM_ADD: {
 
1118
                if (!whole_list->default_is_selected()) {
 
1119
                    const char *selected   = whole_list->get_awar_value();
 
1120
                    int         src_index = whole_list->get_index_of(selected);
 
1121
                    
 
1122
                    if (subset_list->get_index_of(selected) == -1) { // not yet in subset_list
 
1123
                        AW_selection_list_iterator entry(whole_list, src_index);
 
1124
                        subset_list->insert(entry.get_displayed(), entry.get_value());
 
1125
                        subset_list->update();
 
1126
                    }
 
1127
 
 
1128
                    subset_list->set_awar_value(selected); // position right side to newly added or already existing alignment
 
1129
                    whole_list->select_element_at(src_index+1);    // go down 1 position on left side
 
1130
                }
 
1131
 
 
1132
                break;
 
1133
            }
 
1134
            case ACM_REMOVE: {
 
1135
                if (!subset_list->default_is_selected()) {
 
1136
                    char *selected     = strdup(subset_list->get_awar_value());
 
1137
                    int   old_position = subset_list->get_index_of(selected);
 
1138
 
 
1139
                    subset_list->delete_element_at(old_position);
 
1140
                    finish_fill_box(whole_list, subset_list);
 
1141
 
 
1142
                    subset_list->select_element_at(old_position);
 
1143
                    whole_list->set_awar_value(selected); // set left selection to deleted alignment
 
1144
                    free(selected);
 
1145
                }
 
1146
                break;
 
1147
            }
 
1148
            case ACM_EMPTY:
 
1149
                subset_list->clear();
 
1150
                finish_fill_box(whole_list, subset_list);
 
1151
                break;
 
1152
        }
 
1153
    }
 
1154
    void reorder_subset_cb(awt_reorder_mode dest) {
 
1155
        AW_selection_list *subset_list = get_sellist();
 
1156
 
 
1157
        if (!subset_list->default_is_selected()) {
 
1158
            const char *selected = subset_list->get_awar_value();
 
1159
 
 
1160
            StrArray listContent;
 
1161
            subset_list->to_array(listContent, true);
 
1162
 
 
1163
            int old_pos = GBT_names_index_of(listContent, selected);
 
1164
            if (old_pos >= 0) {
 
1165
                int new_pos = 0;
 
1166
                switch (dest) {
 
1167
                    case ARM_TOP:    new_pos= 0;         break;
 
1168
                    case ARM_UP:     new_pos= old_pos-1; break;
 
1169
                    case ARM_DOWN:   new_pos= old_pos+1; break;
 
1170
                    case ARM_BOTTOM: new_pos= -1;        break;
 
1171
                }
 
1172
                if (old_pos != new_pos) {
 
1173
                    GBT_names_move(listContent, old_pos, new_pos);
 
1174
                    subset_list->init_from_array(listContent, subset_list->get_default_value());
 
1175
                }
 
1176
            }
 
1177
        }
784
1178
    }
785
1179
};
786
1180
 
787
 
static void editor_terminated_cb(const char *IF_DEBUG(message), void *cb_data) {
788
 
    fileChanged_cb_data *data = (fileChanged_cb_data*)cb_data;
789
 
 
790
 
#if defined(DEBUG)
791
 
    printf("editor_terminated_cb: message='%s' fpath='%s'\n", message, data->fpath);
792
 
#endif // DEBUG
793
 
 
794
 
    data->callback(data->fpath, data->fileWasChanged(), true);
795
 
    data->editorTerminated = true; // trigger removal of check_file_changed_cb
796
 
}
797
 
 
798
 
#define AWT_CHECK_FILE_TIMER 700 // in ms
799
 
 
800
 
static void check_file_changed_cb(AW_root *aw_root, AW_CL cl_cbdata) {
801
 
    fileChanged_cb_data *data = (fileChanged_cb_data*)cl_cbdata;
802
 
 
803
 
    if (data->editorTerminated) {
804
 
        delete data;
805
 
    }
806
 
    else {
807
 
        bool changed = data->fileWasChanged();
808
 
 
809
 
        if (changed) data->callback(data->fpath, true, false);
810
 
        aw_root->add_timed_callback(AWT_CHECK_FILE_TIMER, check_file_changed_cb, cl_cbdata);
811
 
    }
812
 
}
813
 
 
814
 
void AWT_edit(const char *path, awt_fileChanged_cb callback, AW_window *aww, GBDATA *gb_main) {
815
 
    // Start external editor on file 'path' (asynchronously)
816
 
    // if 'callback' is specified, it is called everytime the file is changed
817
 
    // [aww and gb_main may be 0 if callback is 0]
818
 
 
819
 
    const char          *editor  = GB_getenvARB_TEXTEDIT();
820
 
    char                *fpath   = GBS_eval_env(path);
821
 
    char                *command = 0;
822
 
    fileChanged_cb_data *cb_data = 0;
823
 
    GB_ERROR             error   = 0;
824
 
 
825
 
    if (callback) {
826
 
        awt_assert(aww);
827
 
        awt_assert(gb_main);
828
 
 
829
 
        cb_data = new fileChanged_cb_data(&fpath, callback); // fpath now is 0 and belongs to cb_data
830
 
 
831
 
        char *arb_notify       = GB_generate_notification(gb_main, editor_terminated_cb, "editor terminated", (void*)cb_data);
832
 
        if (!arb_notify) error = GB_await_error();
833
 
        else {
834
 
            char *arb_message = GBS_global_string_copy("arb_message \"Could not start editor '%s'\"", editor);
835
 
 
836
 
            command = GBS_global_string_copy("((%s %s || %s); %s)&", editor, cb_data->fpath, arb_message, arb_notify);
837
 
            free(arb_message);
838
 
            free(arb_notify);
839
 
        }
840
 
    }
841
 
    else {
842
 
        command = GBS_global_string_copy("%s %s &", editor, fpath);
843
 
    }
844
 
 
845
 
    if (command) {
846
 
        awt_assert(!error);
847
 
        error = GB_system(command);
848
 
        if (error) {
849
 
            aw_message(error); error = NULL;
850
 
            if (callback) error = GB_remove_last_notification(gb_main);
851
 
        }
852
 
        else { // successfully started editor
853
 
            // Can't be sure editor really started when callback is used (see command above).
854
 
            // But it doesn't matter, cause arb_notify is called anyway and removes all callbacks
855
 
            if (callback) {
856
 
                // add timed callback tracking file change
857
 
                AW_root *aw_root = aww->get_root();
858
 
                aw_root->add_timed_callback(AWT_CHECK_FILE_TIMER, check_file_changed_cb, (AW_CL)cb_data);
859
 
                cb_data          = 0; // now belongs to check_file_changed_cb 
860
 
            }
861
 
        }
862
 
    }
863
 
 
864
 
    if (error) aw_message(error);
865
 
 
866
 
    free(command);
867
 
    delete cb_data;
868
 
    free(fpath);
869
 
}
870
 
 
871
 
 
872
 
void AWT_popup_select_species_field_window(AW_window *aww, AW_CL cl_awar_name, AW_CL cl_gb_main)
873
 
{
874
 
    static AW_window_simple *aws = 0;
875
 
 
876
 
    // everytime map selection awar to latest user awar:
877
 
    AW_root    *aw_root   = aww->get_root();
878
 
    const char *awar_name = (const char *)cl_awar_name;
879
 
    aw_root->awar("tmp/viewkeys/key_text_select")->map(awar_name);
880
 
 
881
 
    if (!aws) {
882
 
        aws = new AW_window_simple;
883
 
        
884
 
        aws->init( aw_root, "SELECT_SPECIES_FIELD", "Select species field");
885
 
        aws->load_xfig("awt/nds_sel.fig");
886
 
        aws->button_length(13);
887
 
 
888
 
        aws->callback( AW_POPDOWN);
889
 
        aws->at("close");
890
 
        aws->create_button("CLOSE", "CLOSE","C");
891
 
 
892
 
        awt_create_selection_list_on_scandb((GBDATA *)cl_gb_main,
893
 
                                            aws,
894
 
                                            "tmp/viewkeys/key_text_select",
895
 
                                            AWT_NDS_FILTER,
896
 
                                            "scandb","rescandb", &AWT_species_selector, 20, 10);
897
 
    }
898
 
    aws->activate();
899
 
}
 
1181
static void collect_subset_cb(AW_window *, awt_collect_mode what, AW_CL cl_subsel) { ((AW_subset_selection*)cl_subsel)->collect_subset_cb(what); }
 
1182
static void reorder_subset_cb(AW_window *, awt_reorder_mode dest, AW_CL cl_subsel) { ((AW_subset_selection*)cl_subsel)->reorder_subset_cb(dest); }
 
1183
 
 
1184
AW_selection *awt_create_subset_selection_list(AW_window *aww, AW_selection_list *parent_selection, const char *at_box, const char *at_add, const char *at_sort) {
 
1185
    awt_assert(parent_selection);
 
1186
 
 
1187
    aww->at(at_box);
 
1188
    int x_list = aww->get_at_xposition();
 
1189
 
 
1190
    AW_subset_selection *subsel = new AW_subset_selection(aww, *parent_selection);
 
1191
 
 
1192
    aww->button_length(0);
 
1193
 
 
1194
    aww->at(at_add);
 
1195
    int x_buttons = aww->get_at_xposition();
 
1196
 
 
1197
    bool move_rightwards = x_list>x_buttons;
 
1198
    awt_create_collect_buttons(aww, move_rightwards, collect_subset_cb, (AW_CL)subsel);
 
1199
 
 
1200
    aww->at(at_sort);
 
1201
    awt_create_order_buttons(aww, reorder_subset_cb, (AW_CL)subsel);
 
1202
 
 
1203
    return subsel;
 
1204
}
 
1205
 
900
1206