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

« back to all changes in this revision

Viewing changes to NTREE/NT_main.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 <string.h>
2
 
#include <stdio.h>
3
 
#include <stdlib.h>
4
 
#include <arbdb.h>
 
1
// =============================================================== //
 
2
//                                                                 //
 
3
//   File      : NT_main.cxx                                       //
 
4
//   Purpose   :                                                   //
 
5
//                                                                 //
 
6
//   Institute of Microbiology (Technical University Munich)       //
 
7
//   http://www.arb-home.de/                                       //
 
8
//                                                                 //
 
9
// =============================================================== //
 
10
 
 
11
#include "NT_local.h"
 
12
#include "NT_cb.h"
 
13
 
 
14
#include <mg_merge.hxx>
 
15
#include <awti_import.hxx>
 
16
#include <insdel.h>
 
17
 
 
18
#include <awt.hxx>
 
19
 
 
20
#include <aw_advice.hxx>
 
21
#include <aw_question.hxx>
 
22
#include <aw_awars.hxx>
 
23
#include <aw_edit.hxx>
 
24
#include <aw_file.hxx>
 
25
#include <aw_msg.hxx>
 
26
#include <aw_window.hxx>
 
27
#include <aw_root.hxx>
 
28
 
5
29
#include <arbdbt.h>
6
30
#include <adGene.h>
7
31
 
8
 
#include <servercntrl.h>
9
 
#include <aw_root.hxx>
10
 
#include <aw_device.hxx>
11
 
#include <aw_window.hxx>
12
 
#include <aw_awars.hxx>
13
 
#include <aw_question.hxx>
14
 
#include <aw_global.hxx>
15
 
#include <awt_canvas.hxx>
16
 
#include <awt_advice.hxx>
17
 
 
18
 
#include <awt_tree.hxx>
19
 
#include <awt_dtree.hxx>
20
 
#include <awt.hxx>
21
 
#include <awti_import.hxx>
22
 
 
23
 
#include <mg_merge.hxx>
24
 
 
25
 
#include "nt_internal.h"
26
 
#include "ntree.hxx"
27
 
#include "nt_cb.hxx"
28
 
#include "NT_dbrepair.hxx"
29
 
 
30
32
#include <arb_version.h>
 
33
#include <arb_progress.h>
 
34
#include <arb_file.h>
 
35
#include <awt_sel_boxes.hxx>
 
36
#include <awt_TreeAwars.hxx>
 
37
#include <macros.hxx>
 
38
#include <signal.h>
31
39
 
32
40
using namespace std;
33
41
 
34
42
AW_HEADER_MAIN
35
43
 
36
 
#define nt_assert(bed) arb_assert(bed)
37
 
 
38
 
#define NT_SERVE_DB_TIMER 50
39
 
#define NT_CHECK_DB_TIMER 200
40
 
 
41
 
GBDATA *GLOBAL_gb_main;                             // global gb_main for arb_ntree
42
 
NT_global GLOBAL_NT = { 0, 0, 0, false };
 
44
NT_global GLOBAL; 
43
45
 
44
46
// NT_format_all_alignments may be called after any operation which causes
45
47
// unformatted alignments (e.g importing sequences)
52
54
    GB_push_transaction(gb_main);
53
55
    GB_push_my_security(gb_main);
54
56
 
55
 
    aw_status("Checking alignments");
56
 
    err = GBT_check_data(gb_main, 0);
57
 
 
58
 
    AW_repeated_question  question;
59
 
    GBDATA               *gb_presets = GB_entry(gb_main,"presets");
60
 
 
61
 
    question.add_help("prompt/format_alignments.hlp");
62
 
 
63
 
    for (GBDATA *gb_ali = GB_entry(gb_presets,"alignment"); gb_ali && !err; gb_ali = GB_nextEntry(gb_ali)) {
64
 
        GBDATA *gb_aligned = GB_search(gb_ali, "aligned", GB_INT);
65
 
 
66
 
        if (GB_read_int(gb_aligned) == 0) { // sequences in alignment are not formatted
67
 
            enum FormatAction {
68
 
                FA_ASK_USER   = 0, // ask user
69
 
                FA_FORMAT_ALL = 1, // format automatically w/o asking
70
 
                FA_SKIP_ALL   = 2, // skip automatically w/o asking
71
 
            };
72
 
            FormatAction  format_action = FA_ASK_USER;
73
 
            GBDATA       *gb_ali_name   = GB_entry(gb_ali,"alignment_name");
74
 
            const char   *ali_name      = GB_read_char_pntr(gb_ali_name);
75
 
 
76
 
            {
77
 
                bool    is_ali_genom   = strcmp(ali_name, GENOM_ALIGNMENT) == 0;
78
 
                GBDATA *gb_auto_format = GB_entry(gb_ali, "auto_format");
79
 
 
80
 
                if (gb_auto_format) {
81
 
                    format_action = FormatAction(GB_read_int(gb_auto_format));
82
 
                    if (is_ali_genom) {
83
 
                        if (format_action != FA_SKIP_ALL) {
84
 
                            format_action = FA_SKIP_ALL; // always skip ali_genom
85
 
                            err           = GB_write_int(gb_auto_format, FA_SKIP_ALL);
86
 
                        }
87
 
                    }
88
 
                }
89
 
                else if (is_ali_genom) {
90
 
                    format_action = FA_SKIP_ALL;
91
 
                    err           = GBT_write_int(gb_ali, "auto_format", FA_SKIP_ALL);  // always skip
92
 
                }
93
 
            }
94
 
 
95
 
            bool perform_format = false;
96
 
            if (!err) {
97
 
                switch (format_action) {
98
 
                    case FA_FORMAT_ALL: perform_format = true; break;
99
 
                    case FA_SKIP_ALL:   perform_format = false; break;
100
 
                    default: {
101
 
                        char *qtext  = GBS_global_string_copy("Alignment '%s' is not formatted. Format?", ali_name);
102
 
                        int   answer = question.get_answer(qtext, "Format,Skip,Always format,Always skip", "all", false);
103
 
 
104
 
                        switch (answer) {
105
 
                            case 2:
106
 
                                err = GBT_write_int(gb_ali, "auto_format", FA_FORMAT_ALL);
107
 
                                // fall-through
108
 
                            case 0:
109
 
                                perform_format = true;
110
 
                                break;
111
 
 
112
 
                            case 3:
113
 
                                err = GBT_write_int(gb_ali, "auto_format", FA_SKIP_ALL);
114
 
                                break;
115
 
                        }
116
 
 
117
 
                        free(qtext);
118
 
                        break;
119
 
                    }
120
 
                }
121
 
            }
122
 
            if (!err && perform_format) {
123
 
                aw_status(GBS_global_string("Formatting '%s'", ali_name));
124
 
                GB_push_my_security(gb_main);
125
 
                err = GBT_format_alignment(gb_main, ali_name);
126
 
                GB_pop_my_security(gb_main);
127
 
            }
 
57
    int ali_count = GBT_count_alignments(gb_main);
 
58
    if (ali_count) {
 
59
        arb_progress progress("Formatting alignments", ali_count);
 
60
        err = GBT_check_data(gb_main, 0);
 
61
 
 
62
        AW_repeated_question question;
 
63
        question.add_help("prompt/format_alignments.hlp");
 
64
 
 
65
        GBDATA *gb_presets = GBT_get_presets(gb_main);
 
66
        for (GBDATA *gb_ali = GB_entry(gb_presets, "alignment");
 
67
             gb_ali && !err;
 
68
             gb_ali        = GB_nextEntry(gb_ali))
 
69
        {
 
70
            GBDATA *gb_aligned = GB_search(gb_ali, "aligned", GB_INT);
 
71
 
 
72
            if (GB_read_int(gb_aligned) == 0) { // sequences in alignment are not formatted
 
73
                enum FormatAction {
 
74
                    FA_ASK_USER   = 0, // ask user
 
75
                    FA_FORMAT_ALL = 1, // format automatically w/o asking
 
76
                    FA_SKIP_ALL   = 2, // skip automatically w/o asking
 
77
                };
 
78
                FormatAction  format_action = FA_ASK_USER;
 
79
                GBDATA       *gb_ali_name   = GB_entry(gb_ali, "alignment_name");
 
80
                const char   *ali_name      = GB_read_char_pntr(gb_ali_name);
 
81
 
 
82
                {
 
83
                    bool    is_ali_genom   = strcmp(ali_name, GENOM_ALIGNMENT) == 0;
 
84
                    GBDATA *gb_auto_format = GB_entry(gb_ali, "auto_format");
 
85
 
 
86
                    if (gb_auto_format) {
 
87
                        format_action = FormatAction(GB_read_int(gb_auto_format));
 
88
                        if (is_ali_genom) {
 
89
                            if (format_action != FA_SKIP_ALL) {
 
90
                                format_action = FA_SKIP_ALL; // always skip ali_genom
 
91
                                err           = GB_write_int(gb_auto_format, FA_SKIP_ALL);
 
92
                            }
 
93
                        }
 
94
                    }
 
95
                    else if (is_ali_genom) {
 
96
                        format_action = FA_SKIP_ALL;
 
97
                        err           = GBT_write_int(gb_ali, "auto_format", FA_SKIP_ALL);  // always skip
 
98
                    }
 
99
                }
 
100
 
 
101
                bool perform_format = false;
 
102
                if (!err) {
 
103
                    switch (format_action) {
 
104
                        case FA_FORMAT_ALL: perform_format = true; break;
 
105
                        case FA_SKIP_ALL:   perform_format = false; break;
 
106
                        default: {
 
107
                            char *qtext  = GBS_global_string_copy("Alignment '%s' is not formatted. Format?", ali_name);
 
108
                            int   answer = question.get_answer("format_alignments", qtext, "Format,Skip,Always format,Always skip", "all", false);
 
109
 
 
110
                            switch (answer) {
 
111
                                case 2:
 
112
                                    err = GBT_write_int(gb_ali, "auto_format", FA_FORMAT_ALL);
 
113
                                    // fall-through
 
114
                                case 0:
 
115
                                    perform_format = true;
 
116
                                    break;
 
117
 
 
118
                                case 3:
 
119
                                    err = GBT_write_int(gb_ali, "auto_format", FA_SKIP_ALL);
 
120
                                    break;
 
121
                            }
 
122
 
 
123
                            free(qtext);
 
124
                            break;
 
125
                        }
 
126
                    }
 
127
                }
 
128
                if (!err && perform_format) {
 
129
                    GB_push_my_security(gb_main);
 
130
                    err = ARB_format_alignment(gb_main, ali_name);
 
131
                    GB_pop_my_security(gb_main);
 
132
                }
 
133
            }
 
134
            progress.inc_and_check_user_abort(err);
128
135
        }
129
136
    }
130
137
 
137
144
// --------------------------------------------------------------------------------
138
145
 
139
146
 
140
 
 
141
 
// called once on ARB_NTREE startup
142
 
//
143
147
static GB_ERROR nt_check_database_consistency() {
144
 
    aw_openstatus("Checking database...");
145
 
 
146
 
    GB_ERROR err = NT_format_all_alignments(GLOBAL_gb_main);
147
 
    if (!err) err = NT_repair_DB(GLOBAL_gb_main);
148
 
 
149
 
    aw_closestatus();
 
148
    // called once on ARB_NTREE startup
 
149
    arb_progress cons_progress("Checking consistency");
 
150
 
 
151
    GB_ERROR err  = NT_format_all_alignments(GLOBAL.gb_main);
 
152
    if (!err) err = NT_repair_DB(GLOBAL.gb_main);
 
153
 
150
154
    return err;
151
155
}
152
156
 
153
 
 
154
 
void serve_db_interrupt(AW_root *awr){
155
 
    GB_BOOL succes = GBCMS_accept_calls(GLOBAL_gb_main,GB_FALSE);
156
 
    while (succes){
157
 
        awr->check_for_remote_command((AW_default)GLOBAL_gb_main,AWAR_NT_REMOTE_BASE);
158
 
        succes = GBCMS_accept_calls(GLOBAL_gb_main,GB_TRUE);
159
 
    }
160
 
 
161
 
    awr->add_timed_callback(NT_SERVE_DB_TIMER,(AW_RCB)serve_db_interrupt,0,0);
162
 
}
163
 
 
164
 
void check_db_interrupt(AW_root *awr){
165
 
    awr->check_for_remote_command((AW_default)GLOBAL_gb_main,AWAR_NT_REMOTE_BASE);
166
 
    awr->add_timed_callback(NT_CHECK_DB_TIMER,(AW_RCB)check_db_interrupt,0,0);
167
 
}
168
 
 
169
 
GB_ERROR create_nt_window(AW_root *aw_root){
170
 
    AW_window *aww;
171
 
    GB_ERROR error = GB_request_undo_type(GLOBAL_gb_main, GB_UNDO_NONE);
172
 
    if (error) aw_message(error);
173
 
    nt_create_all_awars(aw_root,AW_ROOT_DEFAULT);
174
 
    aww = create_nt_main_window(aw_root,0);
175
 
    aww->show();
176
 
    error = GB_request_undo_type(GLOBAL_gb_main, GB_UNDO_UNDO);
177
 
    if (error) aw_message(error);
178
 
    return error;
179
 
}
180
 
 
181
 
// after intro
182
 
void nt_main_startup_main_window(AW_root *aw_root){
183
 
    create_nt_window(aw_root);
184
 
 
185
 
    if (GB_read_clients(GLOBAL_gb_main)==0) { // i am the server
186
 
        GB_ERROR error = GBCMS_open(":",0,GLOBAL_gb_main);
187
 
        if (error) {
188
 
            aw_message(
189
 
                       "THIS PROGRAM HAS PROBLEMS TO OPEN INTERCLIENT COMMUNICATION !!!\n"
190
 
                       "(MAYBE THERE IS ALREADY ANOTHER SERVER RUNNING)\n\n"
191
 
                       "You cannot use any EDITOR or other external SOFTWARE with this dataset!\n\n"
192
 
                       "Advice: Close ARB again, open a console, type 'arb_clean' and restart arb.\n"
193
 
                       "Caution: Any unsaved data in an eventually running ARB will be lost!\n");
194
 
        }else{
195
 
            aw_root->add_timed_callback(NT_SERVE_DB_TIMER,(AW_RCB)serve_db_interrupt,0,0);
 
157
__ATTR__USERESULT static GB_ERROR startup_mainwindow_and_dbserver(AW_root *aw_root, const char *autorun_macro) {
 
158
    AWT_initTreeAwarRegistry(GLOBAL.gb_main);
 
159
 
 
160
    GB_ERROR error = configure_macro_recording(aw_root, "ARB_NT", GLOBAL.gb_main); // @@@ problematic if called from startup-importer
 
161
    if (!error) {
 
162
        nt_create_main_window(aw_root);
 
163
        if (GB_is_server(GLOBAL.gb_main)) {
196
164
            error = nt_check_database_consistency();
197
 
            if (error) aw_message(error);
 
165
            if (!error) NT_repair_userland_problems();
198
166
        }
199
 
    }else{
200
 
        aw_root->add_timed_callback(NT_CHECK_DB_TIMER,(AW_RCB)check_db_interrupt,0,0);
201
167
    }
 
168
 
 
169
    if (!error && autorun_macro) execute_macro(aw_root, autorun_macro); // @@@ triggering execution here is ok, but its a bad place to pass 'autorun_macro'. Should be handled more generally
 
170
 
 
171
    return error;
202
172
}
203
173
 
204
 
int main_load_and_startup_main_window(AW_root *aw_root) // returns 0 when successfull
205
 
{
206
 
 
 
174
static ARB_ERROR load_and_startup_main_window(AW_root *aw_root, const char *autorun_macro) {
207
175
    char *db_server = aw_root->awar(AWAR_DB_PATH)->read_string();
208
 
    GLOBAL_gb_main = GBT_open(db_server,"rw","$(ARBHOME)/lib/pts/*");
 
176
    GLOBAL.gb_main  = GBT_open(db_server, "rw");
209
177
 
210
 
    if (!GLOBAL_gb_main) {
211
 
        aw_popup_ok(GB_await_error());
212
 
        return -1;
 
178
    ARB_ERROR error;
 
179
    if (!GLOBAL.gb_main) {
 
180
        error = GB_await_error();
213
181
    }
214
 
 
215
 
    aw_root->awar(AWAR_DB_PATH)->write_string(db_server);
216
 
 
217
 
#define MAXNAMELEN 35    
218
 
    int len = strlen(db_server);
219
 
    if (len>MAXNAMELEN) {
220
 
        char *nameOnly = strrchr(db_server, '/');
221
 
        if (nameOnly) {
222
 
            nameOnly++;
223
 
            len -= (nameOnly-db_server);
224
 
            memmove(db_server, nameOnly, len+1);
225
 
            if (len>MAXNAMELEN) {
226
 
                strcpy(db_server+MAXNAMELEN-3, "...");
 
182
    else {
 
183
        aw_root->awar(AWAR_DB_PATH)->write_string(db_server);
 
184
 
 
185
#define MAXNAMELEN 35
 
186
        int len = strlen(db_server);
 
187
        if (len>MAXNAMELEN) {
 
188
            char *nameOnly = strrchr(db_server, '/');
 
189
            if (nameOnly) {
 
190
                nameOnly++;
 
191
                len -= (nameOnly-db_server);
 
192
                memmove(db_server, nameOnly, len+1);
 
193
                if (len>MAXNAMELEN) {
 
194
                    strcpy(db_server+MAXNAMELEN-3, "...");
 
195
                }
227
196
            }
228
197
        }
229
 
    }
230
198
#if defined(DEBUG)
231
 
    AWT_announce_db_to_browser(GLOBAL_gb_main, GBS_global_string("ARB database (%s)", db_server));
 
199
        AWT_announce_db_to_browser(GLOBAL.gb_main, GBS_global_string("ARB database (%s)", db_server));
232
200
#endif // DEBUG
233
201
 
 
202
        GB_ERROR problem = startup_mainwindow_and_dbserver(aw_root, autorun_macro);
 
203
        aw_message_if(problem); // no need to terminate ARB
 
204
    }
 
205
 
234
206
    free(db_server);
235
 
    nt_main_startup_main_window(aw_root);
236
 
 
237
 
    return 0;
 
207
    return error;
238
208
}
239
209
 
240
 
void nt_delete_database(AW_window *aww){
241
 
    char *db_server = aww->get_root()->awar(AWAR_DB_PATH)->read_string();
242
 
    if (strlen(db_server)){
243
 
        if (aw_ask_sure(GBS_global_string("Are you sure to delete database %s\nNote: there is no way to undelete it afterwards", db_server))) {
244
 
            GB_ERROR error = 0;
245
 
            error = GB_delete_database(db_server);
 
210
static void nt_delete_database(AW_window *aww) {
 
211
    AW_root *aw_root   = aww->get_root();
 
212
    char    *db_server = aw_root->awar(AWAR_DB_PATH)->read_string();
 
213
 
 
214
    if (strlen(db_server)) {
 
215
        if (aw_ask_sure(NULL, GBS_global_string("Are you sure to delete database %s\nNote: there is no way to undelete it afterwards", db_server))) {
 
216
            GB_ERROR error = GB_delete_database(db_server);
246
217
            if (error) {
247
218
                aw_message(error);
248
219
            }
249
220
            else {
250
 
                aww->get_root()->awar(AWAR_DB"filter")->touch();
 
221
                aw_root->awar(AWAR_DB_FILTER)->touch();
251
222
            }
252
223
        }
253
224
    }
257
228
    free(db_server);
258
229
}
259
230
 
260
 
// after import !!!!!
261
 
void main3(AW_root *aw_root)
262
 
{
263
 
 
264
 
    GLOBAL_NT.awr = aw_root;
265
 
    create_nt_window(aw_root);
266
 
 
267
 
    if (GB_read_clients(GLOBAL_gb_main)==0) {
268
 
        GB_ERROR error = GBCMS_open(":",0,GLOBAL_gb_main);
269
 
        if (error) {
270
 
            aw_message("THIS PROGRAM IS NOT THE ONLY DB SERVER !!!\nDON'T USE ANY ARB PROGRAM !!!!");
271
 
        }else{
272
 
            aw_root->add_timed_callback(NT_SERVE_DB_TIMER, (AW_RCB)serve_db_interrupt,0,0);
273
 
            error = nt_check_database_consistency();
274
 
            if (error) aw_message(error);
275
 
        }
276
 
    }
277
 
    return;
278
 
}
279
 
 
280
 
void nt_intro_start_old(AW_window *aws)
281
 
{
282
 
    aws->hide();
283
 
    if (main_load_and_startup_main_window(aws->get_root())) {
284
 
        aws->show();
285
 
    }
286
 
}
287
 
 
288
 
void nt_intro_start_merge(AW_window *aws,AW_root *awr){
289
 
    if (aws) awr = aws->get_root();
290
 
    create_MG_main_window(awr);
291
 
    if (aws) aws->hide();
292
 
}
293
 
 
294
 
void nt_intro_start_import(AW_window *aws)
295
 
{
296
 
    aws->hide();
297
 
    aws->get_root()->awar_string( AWAR_DB_PATH )->write_string( "noname.arb");
298
 
    aws->get_root()->awar_int(AWAR_READ_GENOM_DB, IMP_PLAIN_SEQUENCE); // Default toggle  in window  "Create&import" is Non-Genom
299
 
    GLOBAL_gb_main = open_AWTC_import_window(aws->get_root(), "", true, 0, (AW_RCB)main3, 0, 0);
300
 
}
301
 
 
302
 
AW_window *nt_create_intro_window(AW_root *awr)
303
 
{
 
231
static void start_main_window_after_import(AW_root *aw_root) {
 
232
    GLOBAL.aw_root = aw_root;
 
233
 
 
234
    GBDATA *gb_imported = AWTI_take_imported_DB_and_cleanup_importer();
 
235
    nt_assert(gb_imported == GLOBAL.gb_main); // import-DB should already be used as main-DB
 
236
    GLOBAL.gb_main      = gb_imported;
 
237
 
 
238
    aw_message_if(startup_mainwindow_and_dbserver(aw_root, NULL));
 
239
}
 
240
 
 
241
static void nt_intro_start_existing(AW_window *aw_intro) {
 
242
    aw_intro->hide();
 
243
    ARB_ERROR error = load_and_startup_main_window(aw_intro->get_root(), NULL);
 
244
    nt_assert(contradicted(error, got_macro_ability(aw_intro->get_root())));
 
245
    if (error) {
 
246
        aw_intro->show();
 
247
        aw_popup_ok(error.deliver());
 
248
    }
 
249
    else {
 
250
        error.expect_no_error();
 
251
    }
 
252
}
 
253
 
 
254
static void nt_intro_start_merge(AW_window *aw_intro) {
 
255
    AW_root    *aw_root    = aw_intro->get_root();
 
256
    const char *dir        = aw_root->awar("tmp/nt/arbdb/directory")->read_char_pntr();
 
257
    char       *merge_args = GBS_global_string_copy("'%s' '%s'", dir, dir);
 
258
 
 
259
    nt_restart(aw_root, merge_args); //  call arb_ntree as merge-tool on exit
 
260
}
 
261
 
 
262
static void nt_intro_start_import(AW_window *aw_intro) {
 
263
    aw_intro->hide();
 
264
 
 
265
    AW_root *aw_root = aw_intro->get_root();
 
266
    aw_root->awar_string(AWAR_DB_PATH)->write_string("noname.arb");
 
267
    aw_root->awar_int(AWAR_READ_GENOM_DB, IMP_PLAIN_SEQUENCE); // Default toggle  in window  "Create&import" is Non-Genom
 
268
 
 
269
    nt_assert(!GLOBAL.gb_main);
 
270
    AWTI_open_import_window(aw_root, "", true, 0, makeRootCallback(start_main_window_after_import));
 
271
    GLOBAL.gb_main = AWTI_peek_imported_DB();
 
272
 
 
273
    nt_assert(got_macro_ability(aw_root));
 
274
}
 
275
 
 
276
static AW_window *nt_create_intro_window(AW_root *awr) {
304
277
    AW_window_simple *aws = new AW_window_simple;
305
 
    aws->init( awr, "ARB_INTRO", "ARB INTRO");
 
278
    aws->init(awr, "ARB_INTRO", "ARB INTRO");
306
279
    aws->load_xfig("arb_intro.fig");
307
280
 
308
 
    aws->callback( (AW_CB0)exit);
 
281
    aws->callback(nt_exit, EXIT_SUCCESS);
309
282
    aws->at("close");
310
 
    aws->create_button("CANCEL","CANCEL","C");
 
283
    aws->create_button("EXIT", "Exit", "x");
311
284
 
312
285
    aws->at("help");
313
 
    aws->callback(AW_POPUP_HELP,(AW_CL)"arb_intro.hlp");
314
 
    aws->create_button("HELP","HELP","H");
 
286
    aws->callback(makeHelpCallback("arb_intro.hlp"));
 
287
    aws->create_button("HELP", "HELP", "H");
315
288
 
316
 
    awt_create_selection_box(aws,"tmp/nt/arbdb");
 
289
    AW_create_standard_fileselection(aws, "tmp/nt/arbdb");
317
290
 
318
291
    aws->button_length(0);
319
292
 
320
293
    aws->at("logo");
321
 
    aws->create_button(0,"#logo.xpm");
 
294
    aws->create_button(0, "#logo.xpm");
322
295
 
323
296
    aws->at("version");
324
297
    aws->create_button(0, GBS_global_string("Version " ARB_VERSION), 0); // version
326
299
    aws->at("copyright");
327
300
    aws->create_button(0, GBS_global_string("(C) 1993-" ARB_BUILD_YEAR), 0);
328
301
 
329
 
    //  aws->button_length(25);
330
 
 
331
302
    aws->at("old");
332
 
    aws->callback(nt_intro_start_old);
333
 
    aws->create_autosize_button("OPEN_SELECTED","OPEN SELECTED","O");
 
303
    aws->callback(nt_intro_start_existing);
 
304
    aws->create_autosize_button("OPEN_SELECTED", "OPEN SELECTED", "O");
334
305
 
335
306
    aws->at("del");
336
307
    aws->callback(nt_delete_database);
337
 
    aws->create_autosize_button("DELETE_SELECTED","DELETE SELECTED");
 
308
    aws->create_autosize_button("DELETE_SELECTED", "DELETE SELECTED");
338
309
 
339
310
    aws->at("new_complex");
340
311
    aws->callback(nt_intro_start_import);
341
 
    aws->create_autosize_button("CREATE_AND_IMPORT","CREATE AND IMPORT","I");
 
312
    aws->create_autosize_button("CREATE_AND_IMPORT", "CREATE AND IMPORT", "I");
342
313
 
343
314
    aws->at("merge");
344
 
    aws->callback((AW_CB1)nt_intro_start_merge,0);
345
 
    aws->create_autosize_button("MERGE_TWO_DATABASES","MERGE TWO ARB DATABASES","O");
 
315
    aws->callback(nt_intro_start_merge);
 
316
    aws->create_autosize_button("MERGE_TWO_DATABASES", "MERGE TWO ARB DATABASES", "O");
346
317
 
347
318
    aws->at("expert");
348
319
    aws->create_toggle(AWAR_EXPERT);
349
320
 
350
 
    return (AW_window *)aws;
 
321
    return aws;
351
322
}
352
323
 
353
 
void AD_set_default_root(AW_root *aw_root);
354
 
 
355
 
//  ----------------------------------------------------------
356
 
//      static void AWAR_DB_PATH_changed_cb(AW_root *awr)
357
 
//  ----------------------------------------------------------
358
324
static void AWAR_DB_PATH_changed_cb(AW_root *awr) {
359
 
    static int avoid_recursion = 0;
 
325
    static bool avoid_recursion = false;
360
326
 
361
327
    if (!avoid_recursion) {
362
 
        avoid_recursion = 1;
 
328
        LocallyModify<bool> flag(avoid_recursion, true);
363
329
 
364
330
        char *value  = awr->awar(AWAR_DB_PATH)->read_string();
365
331
        char *lslash = strrchr(value, '/');
377
343
        }
378
344
 
379
345
        free(value);
380
 
 
381
 
        avoid_recursion = 0;
382
 
    }
383
 
}
384
 
 
385
 
//  ---------------------------------------
386
 
//      int main(int argc, char **argv)
387
 
//  ---------------------------------------
388
 
int main(int argc, char **argv)
389
 
{
390
 
    AW_root *aw_root;
391
 
    AW_default aw_default;
392
 
 
393
 
    const char *db_server =":";
394
 
 
395
 
    unsigned long mtime = GB_time_of_file("$(ARBHOME)/lib/message");
396
 
    unsigned long rtime = GB_time_of_file("$(HOME)/.arb_prop/msgtime");
397
 
    if (mtime > rtime){
398
 
        AWT_edit("${ARBHOME}/lib/message");
399
 
        system("touch ${HOME}/.arb_prop/msgtime");
400
 
    }
401
 
    aw_initstatus();
402
 
    GB_set_verbose();
403
 
 
404
 
    aw_root       = new AW_root;
405
 
    GLOBAL_NT.awr = aw_root;
406
 
    AD_set_default_root(aw_root);                   // set default for AD_map_viewer (as long as no info-box was opened)
407
 
 
408
 
    aw_default = aw_root->open_default(".arb_prop/ntree.arb");
409
 
    aw_root->init_variables(aw_default);
410
 
    aw_root->init_root("ARB_NT", false);
 
346
    }
 
347
}
 
348
 
 
349
class NtreeCommandLine : virtual Noncopyable {
 
350
    int               arg_count;
 
351
    char const*const* args;
 
352
 
 
353
    bool help_requested;
 
354
    bool do_import;
 
355
    
 
356
    const char *macro_name;
 
357
 
 
358
public:
 
359
    NtreeCommandLine(int argc_, char const*const* argv_)
 
360
        : arg_count(argc_-1),
 
361
          args(argv_+1),
 
362
          help_requested(false),
 
363
          do_import(false),
 
364
          macro_name(NULL)
 
365
    {}
 
366
 
 
367
    void shift() { ++args; --arg_count; }
 
368
 
 
369
    int free_args() const { return arg_count; }
 
370
    const char *get_arg(int num) const { return num<arg_count ? args[num] : NULL; }
 
371
 
 
372
    bool wants_help() const { return help_requested; }
 
373
    bool wants_import() const { return do_import; }
 
374
    bool wants_merge() const { return arg_count == 2; }
 
375
 
 
376
    const char *autorun_macro() const { return macro_name; }
 
377
 
 
378
    void print_help(FILE *out) const {
 
379
        fprintf(out,
 
380
                "\n"
 
381
                "arb_ntree version " ARB_VERSION_DETAILED "\n"
 
382
                "(C) 1993-" ARB_BUILD_YEAR " Lehrstuhl fuer Mikrobiologie - TU Muenchen\n"
 
383
                "http://www.arb-home.de/\n"
 
384
                "(version build by: " ARB_BUILD_USER "@" ARB_BUILD_HOST ")\n"
 
385
                "\n"
 
386
                "Possible usage:\n"
 
387
                "  arb_ntree               => start ARB (intro)\n"
 
388
                "  arb_ntree DB            => start ARB with DB\n"
 
389
                "  arb_ntree DB1 DB2       => merge from DB1 into DB2\n"
 
390
                "  arb_ntree --import FILE => import FILE into new database (FILE may be a filemask)\n"
 
391
                "\n"
 
392
                "Additional arguments possible with command lines above:\n"
 
393
                "  --execute macroname     => execute macro 'macroname' after startup\n"
 
394
                "\n"
 
395
                "Each DB argument may be one of the following:\n"
 
396
                "  database.arb            -> use existing or new database\n"
 
397
                "  \":\"                     -> connect to database of a running instance of ARB\n"
 
398
                "  directory               -> prompt for databases inside directory\n"
 
399
                "  filemask                -> also prompt for DB, but more specific (e.g. \"prot*.arb\")\n"
 
400
                "\n"
 
401
            );
 
402
    }
 
403
 
 
404
    ARB_ERROR parse() {
 
405
        ARB_ERROR error;
 
406
 
 
407
        while (!error && arg_count>0 && args[0][0] == '-') {
 
408
            const char *opt = args[0]+1;
 
409
            if (opt[0] == '-') ++opt; // accept '-' or '--'
 
410
            if (strcmp(opt, "help") == 0 || strcmp(opt, "h") == 0) { help_requested = true; }
 
411
            else if (strcmp(opt, "execute") == 0) { shift(); macro_name = *args; }
 
412
            else if (strcmp(opt, "import") == 0) { do_import = true; }
 
413
 
 
414
            // bunch of test switches to provoke various ways to terminate (see also http://bugs.arb-home.de/ticket/538)
 
415
            else if (strcmp(opt, "crash") == 0) { GBK_terminate("crash requested"); }
 
416
            else if (strcmp(opt, "trap") == 0) { arb_assert(0); }
 
417
            else if (strcmp(opt, "sighup") == 0) { raise(SIGHUP); }
 
418
            else if (strcmp(opt, "sigsegv") == 0) { raise(SIGSEGV); }
 
419
            else if (strcmp(opt, "sigterm") == 0) { raise(SIGTERM); }
 
420
            else if (strcmp(opt, "fail") == 0) { exit(EXIT_FAILURE); }
 
421
            else if (strcmp(opt, "exit") == 0) { exit(EXIT_SUCCESS); }
 
422
            // end of test switches ----------------------------------------
 
423
 
 
424
            else error = GBS_global_string("Unknown switch '%s'", args[0]);
 
425
            shift();
 
426
        }
 
427
        // non-switch arguments remain in arg_count/args
 
428
        if (!error) {
 
429
            if (do_import && arg_count != 1) error = "expected exactly one file-name or file-mask behind --import";
 
430
            else if (arg_count>2)            error = "too many stray arguments given (max. 2 accepted)";
 
431
        }
 
432
        return error;
 
433
    }
 
434
};
 
435
 
 
436
enum ArgType { // args that might be specified on command line (for DB or FILE; see above)
 
437
    RUNNING_DB,
 
438
    DIRECTORY,
 
439
    EXISTING_DB,
 
440
    NEW_DB,
 
441
    FILEMASK,
 
442
    EXISTING_FILE,
 
443
    UNKNOWN_ARG,
 
444
};
 
445
 
 
446
inline bool has_arb_suffix(const char *arg) {
 
447
    const char *suffix = strstr(arg, ".arb");
 
448
    if (suffix) {
 
449
        return strcmp(suffix, ".arb") == 0;
 
450
    }
 
451
    return false;
 
452
}
 
453
 
 
454
static ArgType detectArgType(const char *arg) {
 
455
    if (strcmp(arg, ":") == 0) return RUNNING_DB;
 
456
    if (GB_is_directory(arg)) return DIRECTORY;
 
457
    if (strpbrk(arg, "*?") != 0) return FILEMASK;
 
458
    if (has_arb_suffix(arg)) {
 
459
        return GB_is_regularfile(arg) ? EXISTING_DB : NEW_DB;
 
460
    }
 
461
 
 
462
    GB_ERROR load_file_err = GBT_check_arb_file(arg);
 
463
    if (!load_file_err) return EXISTING_DB;
 
464
 
 
465
    return GB_is_regularfile(arg) ? EXISTING_FILE : UNKNOWN_ARG;
 
466
}
 
467
 
 
468
enum RunMode { NORMAL, IMPORT, MERGE, BROWSE };
 
469
 
 
470
#define ABORTED_BY_USER "aborted by user"
 
471
 
 
472
static ARB_ERROR check_argument_for_mode(const char *database, char *&browser_startdir, RunMode& mode) {
 
473
    // Check whether 'database' is a
 
474
    // - ARB database
 
475
    // - directory name
 
476
    // - file to import
 
477
    //
 
478
    // Modify 'mode' occordingly.
 
479
    // Set 'browser_startdir'
 
480
 
 
481
    ARB_ERROR error;
 
482
    if (mode != IMPORT) {
 
483
        if (!database) mode = BROWSE;
 
484
        else {
 
485
            GB_ERROR load_file_err = GBT_check_arb_file(database);
 
486
            if (load_file_err) {
 
487
                char *full_path = AW_unfold_path("PWD", database);
 
488
 
 
489
                enum Action { LOAD_DB, CONVERT_DB, BROWSE_DB, EXIT, NOIDEA };
 
490
                Action action = NOIDEA;
 
491
                if (GB_is_directory(full_path)) {
 
492
                    action = BROWSE_DB;
 
493
                }
 
494
                else {
 
495
                    if (!GB_is_regularfile(full_path)) {
 
496
                        const char *msg = GBS_global_string("'%s' is neither a known option nor a legal file- or directory-name.\n(Error: %s)",
 
497
                                                            full_path, load_file_err);
 
498
 
 
499
                        int ans = aw_question(NULL, msg, "Browser,Exit");
 
500
                        action  = ans ? EXIT : BROWSE_DB;
 
501
                    }
 
502
                    else {
 
503
                        const char *msg = GBS_global_string("Your file is not an original arb file\n(%s)", load_file_err);
 
504
                        action          = (Action)aw_question(NULL, msg, "Continue (dangerous),Start Converter,Browser,Exit");
 
505
                    }
 
506
                }
 
507
 
 
508
                switch (action) {
 
509
                    case CONVERT_DB:    mode = IMPORT; break;
 
510
                    case LOAD_DB:       break;
 
511
                    case NOIDEA:        nt_assert(0);
 
512
                    case EXIT:          error = ABORTED_BY_USER; break;
 
513
                    case BROWSE_DB: {
 
514
                        char *dir = nulldup(full_path);
 
515
                        while (dir && !GB_is_directory(dir)) freeset(dir, AW_extract_directory(dir));
 
516
 
 
517
                        if (dir) {
 
518
                            nt_assert(GB_is_directory(dir));
 
519
                            reassign(browser_startdir, dir);
 
520
                            mode = BROWSE;
 
521
                        }
 
522
                        free(dir);
 
523
                        break;
 
524
                    }
 
525
                
 
526
                }
 
527
                free(full_path);
 
528
            }
 
529
        }
 
530
    }
 
531
    
 
532
    return error;
 
533
}
 
534
 
 
535
class SelectedDatabase : virtual Noncopyable {
 
536
    GBDATA*&  gb_main;
 
537
    char     *name;
 
538
    ArgType   type;
 
539
    char     *role;
 
540
 
 
541
    void fix_name() {
 
542
        if (type != RUNNING_DB && name[0]) {
 
543
            const char *changed;
 
544
 
 
545
            if (type == NEW_DB) {
 
546
                changed = GB_unfold_in_directory(GB_getcwd(), name);
 
547
            }
 
548
            else {
 
549
                changed = GB_canonical_path(name);
 
550
            }
 
551
 
 
552
            if (strcmp(name, changed) != 0) {
 
553
                reselect_file(changed);
 
554
            }
 
555
        }
 
556
    }
 
557
 
 
558
public:
 
559
    SelectedDatabase(GBDATA*& gb_main_, const char *name_, const char *role_)
 
560
        : gb_main(gb_main_),
 
561
          name(strdup(name_)),
 
562
          type(detectArgType(name)),
 
563
          role(strdup(role_))
 
564
    {
 
565
        fix_name();
 
566
    }
 
567
    ~SelectedDatabase() {
 
568
        free(role);
 
569
        free(name);
 
570
    }
 
571
 
 
572
    ArgType arg_type() const { return type; }
 
573
 
 
574
    bool needs_to_prompt() const {
 
575
        return type == DIRECTORY || type == FILEMASK || type == UNKNOWN_ARG;
 
576
    }
 
577
 
 
578
    const char *get_fullname() const { return name; }
 
579
    const char *get_nameonly() const {
 
580
        const char *slash = strrchr(name, '/');
 
581
        return slash ? slash+1 : name;
 
582
    }
 
583
    const char *get_role() const { return role; }
 
584
    const char *get_description() const { return GBS_global_string("%s (%s)", get_role(), get_nameonly()); }
 
585
 
 
586
    ArgType get_type() const { return type; }
 
587
 
 
588
    const char *get_dir() const {
 
589
        const char *dir = NULL;
 
590
        switch (type) {
 
591
            case DIRECTORY:
 
592
                dir = get_fullname();
 
593
                break;
 
594
 
 
595
            case NEW_DB:
 
596
            case FILEMASK:
 
597
            case EXISTING_FILE:
 
598
            case EXISTING_DB: {
 
599
                char *dir_copy;
 
600
                GB_split_full_path(name, &dir_copy, NULL, NULL, NULL);
 
601
 
 
602
                static SmartCharPtr dir_store;
 
603
                dir_store = dir_copy;
 
604
 
 
605
                dir = dir_copy;
 
606
                break;
 
607
            }
 
608
            case UNKNOWN_ARG:
 
609
            case RUNNING_DB:
 
610
                dir = ".";
 
611
                break;
 
612
        }
 
613
        return dir;
 
614
    }
 
615
 
 
616
    const char *get_mask() const {
 
617
        const char *mask;
 
618
        switch (type) {
 
619
            case FILEMASK: {
 
620
                char *mask_copy;
 
621
                GB_split_full_path(name, NULL, &mask_copy, NULL, NULL);
 
622
 
 
623
                static SmartCharPtr mask_store;
 
624
                mask_store = mask_copy;
 
625
 
 
626
                mask = mask_copy;
 
627
                break;
 
628
            }
 
629
            default:
 
630
                mask = ".arb";
 
631
                break;
 
632
        }
 
633
        return mask;
 
634
    }
 
635
 
 
636
    void reselect_file(const char *file) {
 
637
        freedup(name, file);
 
638
        type = detectArgType(name);
 
639
        fix_name();
 
640
    }
 
641
    void reselect_from_awar(AW_root *aw_root, const char *awar_name) {
 
642
        if (awar_name) {
 
643
            const char *file = aw_root->awar(awar_name)->read_char_pntr();
 
644
            if (file) reselect_file(file);
 
645
        }
 
646
    }
 
647
 
 
648
    GB_ERROR open_db_for_merge(bool is_source_db);
 
649
    void close_db() { if (gb_main) GB_close(gb_main); }
 
650
};
 
651
 
 
652
GB_ERROR SelectedDatabase::open_db_for_merge(bool is_source_db) {
 
653
    GB_ERROR    error    = NULL;
 
654
    const char *openMode = "rw";
 
655
 
 
656
    switch (get_type()) {
 
657
        case DIRECTORY:
 
658
        case FILEMASK:
 
659
            GBK_terminate("Program logic error (should have been prompted for explicit DB name)");
 
660
            break;
 
661
 
 
662
        case UNKNOWN_ARG:
 
663
        case EXISTING_FILE:
 
664
            error = GBS_global_string("'%s' is no arb-database", get_fullname());
 
665
            break;
 
666
 
 
667
        case NEW_DB:
 
668
            if (is_source_db) {
 
669
                error = GBS_global_string("'%s' has to exist", get_fullname());
 
670
                break;
 
671
            }
 
672
            openMode = "crw"; // allow to create DB
 
673
            break;
 
674
 
 
675
        case EXISTING_DB:
 
676
        case RUNNING_DB:
 
677
            break;
 
678
    }
 
679
 
 
680
    if (!error) {
 
681
        gb_main             = GBT_open(get_fullname(), openMode);
 
682
        if (!gb_main) error = GB_await_error();
 
683
        else {
 
684
            IF_DEBUG(AWT_announce_db_to_browser(gb_main, get_description()));
 
685
        }
 
686
    }
 
687
 
 
688
    return error;
 
689
}
 
690
 
 
691
struct merge_scheme : virtual Noncopyable {
 
692
    SelectedDatabase *src;
 
693
    SelectedDatabase *dst;
 
694
 
 
695
    char *awar_src;
 
696
    char *awar_dst;
 
697
 
 
698
    GB_ERROR error;
 
699
 
 
700
    merge_scheme(SelectedDatabase *src_, SelectedDatabase *dst_)
 
701
        : src(src_),
 
702
          dst(dst_),
 
703
          awar_src(NULL),
 
704
          awar_dst(NULL),
 
705
          error(NULL)
 
706
    {}
 
707
    ~merge_scheme() {
 
708
        if (error) {
 
709
            src->close_db();
 
710
            dst->close_db();
 
711
        }
 
712
        delete src;
 
713
        delete dst;
 
714
        free(awar_src);
 
715
        free(awar_dst);
 
716
    }
 
717
 
 
718
 
 
719
    void open_dbs() {
 
720
        if (!error) error = src->open_db_for_merge(true);
 
721
        if (!error) error = dst->open_db_for_merge(false);
 
722
    }
 
723
 
 
724
    void fix_dst(AW_root *aw_root) { dst->reselect_from_awar(aw_root, awar_dst); }
 
725
    void fix_src(AW_root *aw_root) { src->reselect_from_awar(aw_root, awar_src); }
 
726
 
 
727
    bool knows_dbs() const { return !src->needs_to_prompt() && !dst->needs_to_prompt(); }
 
728
};
 
729
 
 
730
static bool merge_tool_running_as_client = true; // default to safe state (true avoids call of 'arb_clean' at exit)
 
731
static void exit_from_merge(const char *restart_args) {
 
732
    if (merge_tool_running_as_client) { // there is a main ARB running
 
733
        if (restart_args) nt_start(restart_args, true);
 
734
        exit(EXIT_SUCCESS); // exit w/o killing clients (as nt_exit() does)
 
735
    }
 
736
    else {
 
737
        nt_restart(AW_root::SINGLETON, restart_args ? restart_args : "");
 
738
        nt_assert(0);
 
739
    }
 
740
}
 
741
 
 
742
static void merge_startup_abort_cb(AW_window*) {
 
743
    fputs("Error: merge aborted by user\n", stderr);
 
744
    exit_from_merge(NULL);
 
745
}
 
746
 
 
747
static AW_window *merge_startup_error_window(AW_root *aw_root, GB_ERROR error) {
 
748
    AW_window_simple *aw_msg = new AW_window_simple;
 
749
 
 
750
    aw_msg->init(aw_root, "arb_merge_error", "ARB merge error");
 
751
    aw_msg->recalc_size_atShow(AW_RESIZE_DEFAULT); // force size recalc (ignores user size)
 
752
 
 
753
    aw_msg->at(10, 10);
 
754
    aw_msg->auto_space(10, 10);
 
755
 
 
756
    aw_msg->create_autosize_button(NULL, error, "", 2);
 
757
    aw_msg->at_newline();
 
758
 
 
759
    aw_msg->callback(merge_startup_abort_cb);
 
760
    aw_msg->create_autosize_button("OK", "Ok", "O", 2);
 
761
 
 
762
    aw_msg->window_fit();
 
763
 
 
764
    return aw_msg;
 
765
}
 
766
static AW_window *startup_merge_main_window(AW_root *aw_root, merge_scheme *ms) {
 
767
    ms->fix_src(aw_root);
 
768
    ms->fix_dst(aw_root);
 
769
 
 
770
    if (ms->knows_dbs()) {
 
771
        ms->open_dbs();
 
772
    }
 
773
    else {
 
774
        ms->error = "Need two database to merge";
 
775
    }
 
776
 
 
777
    AW_window *aw_result;
 
778
    if (!ms->error) {
 
779
        MERGE_create_db_file_awars(aw_root, AW_ROOT_DEFAULT, ms->src->get_fullname(), ms->dst->get_fullname());
 
780
        bool dst_is_new = ms->dst->arg_type() == NEW_DB;
 
781
        aw_result       = MERGE_create_main_window(aw_root, dst_is_new, exit_from_merge);
 
782
 
 
783
        nt_assert(got_macro_ability(aw_root));
 
784
    }
 
785
    else {
 
786
        aw_result = merge_startup_error_window(aw_root, ms->error);
 
787
    }
 
788
    delete ms; // was allocated in startup_gui()
 
789
    return aw_result;
 
790
}
 
791
 
 
792
static AW_window *startup_merge_prompting_for_nonexplicit_dst_db(AW_root *aw_root, merge_scheme *ms) {
 
793
    AW_window *aw_result;
 
794
    if (ms->dst->needs_to_prompt()) {
 
795
        aw_result = awt_create_load_box(aw_root, "Select", ms->dst->get_role(),
 
796
                                        ms->dst->get_dir(), ms->dst->get_mask(),
 
797
                                        &(ms->awar_dst),
 
798
                                        AW_window::makeWindowReplacer(makeCreateWindowCallback(startup_merge_main_window, ms)),
 
799
                                        makeWindowCallback(merge_startup_abort_cb), "Cancel");
 
800
    }
 
801
    else {
 
802
        aw_result = startup_merge_main_window(aw_root, ms);
 
803
    }
 
804
    return aw_result;
 
805
}
 
806
 
 
807
static AW_window *startup_merge_prompting_for_nonexplicit_dbs(AW_root *aw_root, merge_scheme *ms) {
 
808
    // if src_spec or dst_spec needs to be prompted for -> startup prompters with callbacks bound to continue
 
809
    // otherwise just startup merge
 
810
 
 
811
    AW_window *aw_result;
 
812
    if (ms->src->needs_to_prompt()) {
 
813
        aw_result = awt_create_load_box(aw_root, "Select", ms->src->get_role(),
 
814
                                        ms->src->get_dir(), ms->src->get_mask(),
 
815
                                        &(ms->awar_src),
 
816
                                        AW_window::makeWindowReplacer(makeCreateWindowCallback(startup_merge_prompting_for_nonexplicit_dst_db, ms)),
 
817
                                        makeWindowCallback(merge_startup_abort_cb), "Cancel");
 
818
    }
 
819
    else {
 
820
        aw_result = startup_merge_prompting_for_nonexplicit_dst_db(aw_root, ms);
 
821
    }
 
822
    return aw_result;
 
823
}
 
824
 
 
825
static void startup_gui(NtreeCommandLine& cl, ARB_ERROR& error) {
 
826
    {
 
827
        char *message = strdup(GB_path_in_ARBLIB("message"));
 
828
        char *stamp   = strdup(GB_path_in_arbprop("msgtime"));
 
829
        if (GB_time_of_file(message)>GB_time_of_file(stamp)) {
 
830
            AW_edit(message);
 
831
            aw_message_if(GBK_system(GBS_global_string("touch %s", stamp)));
 
832
        }
 
833
        free(stamp);
 
834
        free(message);
 
835
    }
411
836
 
412
837
    // create some early awars
413
838
    // Note: normally you don't like to add your awar-init-function here, but into nt_create_all_awars()
414
839
 
415
 
    aw_create_selection_box_awars(aw_root, AWAR_DB, "", ".arb", "noname.arb", aw_default);
416
 
    aw_root->awar_string( AWAR_DB"type", "b", aw_default);
417
 
 
418
 
    aw_root->awar_int(AWAR_EXPERT, 0, aw_default);
419
 
 
420
 
    aw_root->awar_string(AWAR_DB_NAME, "noname.arb", aw_default);
 
840
    AW_root* aw_root = GLOBAL.aw_root;
 
841
 
 
842
    AW_create_fileselection_awars(aw_root, AWAR_DB, "", ".arb", "noname.arb");
 
843
    aw_root->awar_string(AWAR_DB_TYPE, "b");
 
844
    aw_root->awar_string(AWAR_DB_NAME, "noname.arb");
421
845
    aw_root->awar(AWAR_DB_PATH)->add_callback(AWAR_DB_PATH_changed_cb);
422
846
 
423
 
    init_Advisor(aw_root, aw_default);
424
 
 
425
 
    if (argc==3) {              // looks like merge
426
 
        if (argv[1][0] != '-') { // not if first argument is a switch 
427
 
            MG_create_all_awars(aw_root,aw_default,argv[1],argv[2]);
428
 
            nt_intro_start_merge(0,aw_root);
429
 
            aw_root->main_loop();
430
 
        }
431
 
    }
432
 
 
433
 
    bool  abort            = false;
434
 
    bool  start_db_browser = true;
435
 
    char *browser_startdir = strdup(".");
436
 
 
437
 
    if (argc>=2) {
438
 
        start_db_browser = false;
439
 
 
440
 
        if (strcmp(argv[1], "--help")==0 ||
441
 
            strcmp(argv[1], "-help")==0 ||
442
 
            strcmp(argv[1], "-h")==0)
443
 
        {
444
 
            fprintf(stderr,
445
 
                    "\n"
446
 
                    "arb_ntree version " ARB_VERSION "\n"
447
 
                    "(C) 1993-" ARB_BUILD_YEAR " Lehrstuhl fuer Mikrobiologie - TU Muenchen\n"
448
 
                    "http://www.arb-home.de/\n"
449
 
#if defined(SHOW_WHERE_BUILD)
450
 
                    "(version build by: " ARB_BUILD_USER "@" ARB_BUILD_HOST ")\n"
451
 
#endif // SHOW_WHERE_BUILD
452
 
                    "\n"
453
 
                    "Known command line arguments:\n"
454
 
                    "\n"
455
 
                    "db.arb             => start ARB_NTREE with database db.arb\n"
456
 
                    ":                  => start ARB_NTREE and connect to existing db_server\n"
457
 
                    "db1.arb db2.arb    => merge databases db1.arb and db2.arb\n"
458
 
                    "-export            => connect to existing ARB server and export database to noname.arb\n"
459
 
                    "-import file       => import 'file' into new database\n"
460
 
                    "w/o arguments      => start database browser\n"
461
 
                    "\n"
462
 
                    );
463
 
 
464
 
            exit(1);
465
 
        }
466
 
 
467
 
        if ( strcmp(argv[1],"-export")==0) {
468
 
            MG_create_all_awars(aw_root,aw_default,":","noname.arb");
469
 
            GLOBAL_gb_merge = GBT_open(":","rw",0);
470
 
            if (!GLOBAL_gb_merge) {
471
 
                aw_popup_ok(GB_await_error());
472
 
                exit(0);
473
 
            }
474
 
#if defined(DEBUG)
475
 
            AWT_announce_db_to_browser(GLOBAL_gb_merge, "Current database (:)");
476
 
#endif // DEBUG
477
 
 
478
 
            GLOBAL_gb_dest = GBT_open("noname.arb","cw",0);
479
 
#if defined(DEBUG)
480
 
            AWT_announce_db_to_browser(GLOBAL_gb_dest, "New database (noname.arb)");
481
 
#endif // DEBUG
482
 
 
483
 
            MG_start_cb2(NULL, aw_root, true, true);
484
 
            aw_root->main_loop();
485
 
        }
486
 
 
487
 
        bool run_importer = false;
488
 
        if (strcmp(argv[1], "-import") == 0) {
489
 
            argv++;
490
 
            run_importer = true;
491
 
        }
492
 
 
493
 
        db_server              = argv[1];
494
 
        GB_ERROR load_file_err = 0;
495
 
        if (!run_importer) load_file_err = GBT_check_arb_file(db_server);
496
 
 
497
 
        if (load_file_err) {
498
 
            int   answer    = -1;
499
 
            char *full_path = AWT_unfold_path(db_server);
500
 
 
501
 
            printf("load_file_err='%s'\n", load_file_err);
502
 
 
503
 
            if (AWT_is_dir(full_path)) answer = 2; // autoselect browser
504
 
 
505
 
            if (answer == -1) {
506
 
                if (!AWT_is_file(full_path)) {
507
 
                    const char *msg = GBS_global_string("'%s' is neither a known option nor a legal file- or directory-name.\n(Error: %s)",
508
 
                                                        full_path, load_file_err);
509
 
                    answer          = aw_question(msg, "Browser,Exit");
510
 
 
511
 
                    switch (answer) { // map answer to codes used by aw_message below
512
 
                        case 0: answer = 2; break; // Browse
513
 
                        case 1: answer = 3; break; // Exit
514
 
                        default : nt_assert(0);
515
 
                    }
516
 
                }
517
 
                else {
518
 
                    const char *msg = GBS_global_string("Your file is not an original arb file\n(%s)", load_file_err);
519
 
                    answer          = aw_question(msg, "Continue (dangerous),Start Converter,Browser,Exit");
520
 
                }
521
 
            }
522
 
 
523
 
            switch (answer) {
524
 
                case 0: {        // Continue
525
 
                    break;
526
 
                }
527
 
                case 1: {        // Start converter
528
 
                    run_importer =  true;
529
 
                    break;
530
 
                }
531
 
                case 2: {        // Browse
532
 
                    char *dir = nulldup(full_path);
533
 
                    while (dir && !AWT_is_dir(dir)) freeset(dir, AWT_extract_directory(dir));
534
 
 
535
 
                    if (dir) {
536
 
                        nt_assert(AWT_is_dir(dir));
537
 
                        reassign(browser_startdir, dir);
538
 
                        start_db_browser = true;
539
 
                    }
540
 
                    free(dir);
541
 
                    break;
542
 
                }
543
 
                case 3: {        // Exit
544
 
                    abort = true;
545
 
                    break;
546
 
                }
547
 
                default: {
548
 
                    break;
549
 
                }
550
 
            }
551
 
            free(full_path);
552
 
        }
553
 
 
554
 
        if (run_importer) {
555
 
            aw_root->awar_int(AWAR_READ_GENOM_DB, IMP_PLAIN_SEQUENCE);
556
 
            GLOBAL_gb_main = open_AWTC_import_window(aw_root, db_server, true, 0, (AW_RCB)main3, 0, 0);
557
 
            aw_root->main_loop();
558
 
        }
559
 
    }
560
 
 
561
 
 
562
 
    if (start_db_browser) {
563
 
        aw_root->awar(AWAR_DB"directory")->write_string(browser_startdir);
564
 
        char *latest = GB_find_latest_file(browser_startdir, "/\\.(arb|a[0-9]{2})$/");
565
 
        if (latest){
566
 
            int l = strlen(latest);
567
 
            latest[l-1] = 'b';
568
 
            latest[l-2] = 'r';
569
 
            latest[l-3] = 'a';
570
 
            aw_root->awar(AWAR_DB_PATH)->write_string(latest);
571
 
            free(latest);
572
 
        }
573
 
        AW_window *iws;
574
 
        if (GLOBAL_NT.window_creator){
575
 
            iws = GLOBAL_NT.window_creator(aw_root,0);
576
 
        }else{
577
 
            iws = nt_create_intro_window(aw_root);
578
 
        }
579
 
        iws->show();
580
 
        aw_root->main_loop();
581
 
    }
582
 
 
583
 
    if (abort) {
584
 
        printf("Aborting.\n");
 
847
    aw_root->awar_int(AWAR_EXPERT, 0);
 
848
 
 
849
    AWT_install_cb_guards();
 
850
 
 
851
    ARB_declare_global_awars(aw_root, AW_ROOT_DEFAULT);
 
852
 
 
853
    aw_root->setUserActionTracker(new NullTracker); // no macro recording inside prompters that may popup
 
854
    if (!error) {
 
855
        nt_assert(!cl.wants_help());
 
856
                
 
857
        RunMode mode = NORMAL;
 
858
 
 
859
        if      (cl.wants_merge())  mode = MERGE;
 
860
        else if (cl.wants_import()) mode = IMPORT;
 
861
 
 
862
        if (mode == MERGE) {
 
863
            MERGE_create_all_awars(aw_root, AW_ROOT_DEFAULT);
 
864
 
 
865
            merge_scheme *ms = new merge_scheme( // freed in startup_merge_main_window()
 
866
                new SelectedDatabase(GLOBAL_gb_src, cl.get_arg(0), "Source DB for merge"),
 
867
                new SelectedDatabase(GLOBAL_gb_dst, cl.get_arg(1), "Destination DB for merge"));
 
868
 
 
869
            merge_tool_running_as_client = ms->src->arg_type() == RUNNING_DB || ms->dst->arg_type() == RUNNING_DB;
 
870
 
 
871
            if (ms->src->arg_type() == RUNNING_DB && ms->dst->arg_type() == RUNNING_DB) {
 
872
                error = "You cannot merge from running to running DB";
 
873
            }
 
874
            else {
 
875
                aw_root->setUserActionTracker(new NullTracker); // no macro recording during startup of merge tool (file prompts)
 
876
                AW_window *aww = startup_merge_prompting_for_nonexplicit_dbs(aw_root, ms);
 
877
 
 
878
                nt_assert(contradicted(aww, error));
 
879
 
 
880
                if (!error) {
 
881
                    aww->show();
 
882
                    aw_root->main_loop();
 
883
                    nt_assert(0);
 
884
                }
 
885
            }
 
886
        }
 
887
        else {
 
888
            const char *database         = NULL;
 
889
            char       *browser_startdir = strdup(".");
 
890
 
 
891
            if (cl.free_args() > 0) database = cl.get_arg(0);
 
892
 
 
893
            error = check_argument_for_mode(database, browser_startdir, mode);
 
894
            if (!error) {
 
895
                if (mode == IMPORT) {
 
896
                    aw_root->awar_int(AWAR_READ_GENOM_DB, IMP_PLAIN_SEQUENCE);
 
897
 
 
898
                    AWTI_open_import_window(aw_root, database, true, 0, makeRootCallback(start_main_window_after_import));
 
899
                    nt_assert(!GLOBAL.gb_main);
 
900
                    GLOBAL.gb_main = AWTI_peek_imported_DB();
 
901
 
 
902
                    nt_assert(got_macro_ability(aw_root));
 
903
                    aw_root->main_loop();
 
904
                }
 
905
                else if (mode == NORMAL) {
 
906
                    aw_root->awar(AWAR_DB_PATH)->write_string(database);
 
907
                    error = load_and_startup_main_window(aw_root, cl.autorun_macro());
 
908
                    if (!error) {
 
909
                        nt_assert(got_macro_ability(aw_root));
 
910
                        aw_root->main_loop();
 
911
                    }
 
912
                }
 
913
                else if (mode == BROWSE) {
 
914
                    aw_root->awar(AWAR_DB"directory")->write_string(browser_startdir);
 
915
                    char *latest = GB_find_latest_file(browser_startdir, "/\\.(arb|a[0-9]{2})$/");
 
916
                    if (latest) {
 
917
                        int l = strlen(latest);
 
918
                        strcpy(latest+l-3, "arb");
 
919
                        aw_root->awar(AWAR_DB_PATH)->write_string(latest);
 
920
                        free(latest);
 
921
                    }
 
922
                    nt_create_intro_window(aw_root)->show();
 
923
                    aw_root->setUserActionTracker(new NullTracker); // no macro recording inside intro window
 
924
                    aw_root->main_loop();
 
925
                }
 
926
            }
 
927
            free(browser_startdir);
 
928
        }
 
929
    }
 
930
 
 
931
    if (error) {
 
932
        const char *msg = error.preserve();
 
933
        if (strcmp(msg, ABORTED_BY_USER) != 0) aw_popup_ok(msg);
 
934
    }
 
935
}
 
936
 
 
937
int ARB_main(int argc, char *argv[]) {
 
938
    {
 
939
        // i really dont want 'arb_ntree --help' to startup the GUI
 
940
        // hack: parse CL twice
 
941
        NtreeCommandLine cl(argc, argv);
 
942
        bool             cl_ok = !cl.parse().deliver();
 
943
        if (cl_ok) {
 
944
            if (cl.wants_help()) {
 
945
                cl.print_help(stderr);
 
946
                return EXIT_SUCCESS;
 
947
            }
 
948
        }
 
949
    }
 
950
 
 
951
    aw_initstatus();
 
952
    GB_set_verbose();
 
953
 
 
954
    GB_shell shell;
 
955
    AW_root *aw_root = AWT_create_root("ntree.arb", "ARB_NT", need_macro_ability(), &argc, &argv);
 
956
 
 
957
    GLOBAL.aw_root = aw_root;
 
958
 
 
959
    NtreeCommandLine cl(argc, argv);
 
960
    ARB_ERROR        error = cl.parse();
 
961
 
 
962
    if (!error) {
 
963
        if (cl.wants_help()) {
 
964
            cl.print_help(stderr);
 
965
        }
 
966
        else {
 
967
            startup_gui(cl, error);
 
968
        }
 
969
    }
 
970
 
 
971
    int exitcode = EXIT_SUCCESS;
 
972
    if (error) {
 
973
        exitcode = EXIT_FAILURE;
 
974
        fprintf(stderr, "arb_ntree: Error: %s\n", error.deliver());
585
975
    }
586
976
    else {
587
 
        aw_root->awar(AWAR_DB_PATH)->write_string(db_server);
588
 
        if (main_load_and_startup_main_window(aw_root)) return -1;
589
 
        aw_root->main_loop();
 
977
        error.expect_no_error();
590
978
    }
591
979
 
592
 
    return 0;
 
980
    delete aw_root;
 
981
 
 
982
    return exitcode;
593
983
}
 
984