source: tags/arb_5.2/WINDOW/AW_nawar.cxx

Last change on this file was 6159, checked in by westram, 15 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.3 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/stat.h>
5// #include <fcntl.h>
6
7#include <arbdb.h>
8#include "aw_root.hxx"
9#include "aw_nawar.hxx"
10#include "awt.hxx"
11#define AWAR_EPS 0.00000001
12
13#if defined(DEBUG)
14// uncomment next line to dump all awar-changes to stderr
15// #define DUMP_AWAR_CHANGES
16#endif // DEBUG
17
18AW_var_target::AW_var_target(void* pntr, AW_var_target *nexti){
19    next    = nexti;
20    pointer = pntr;
21}
22
23AW_var_callback::AW_var_callback( void (*vc_cb)(AW_root*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2, AW_var_callback *nexti ) {
24    value_changed_cb     = vc_cb;
25    value_changed_cb_cd1 = cd1;
26    value_changed_cb_cd2 = cd2;
27    next                 = nexti;
28}
29
30
31void AW_var_callback::run_callback(AW_root *root) {
32    if (this->next) this->next->run_callback(root);     // callback the whole list
33    if (!this->value_changed_cb) return;
34    this->value_changed_cb(root,this->value_changed_cb_cd1,this->value_changed_cb_cd2);
35}
36
37void AW_var_gbdata_callback_delete_intern(GBDATA *, int *cl) {
38    AW_awar *awar = (AW_awar *)cl;
39    awar->gb_var = 0;
40    awar->update();
41}
42
43extern "C"
44void AW_var_gbdata_callback(GBDATA *, int *cl, GB_CB_TYPE) {
45    AW_awar *awar = (AW_awar *)cl;
46    awar->update();
47}
48
49extern "C"
50void AW_var_gbdata_callback_delete(GBDATA *gbd, int *cl, GB_CB_TYPE) {
51    AW_var_gbdata_callback_delete_intern(gbd, cl);
52}
53
54GB_ERROR AW_MSG_UNMAPPED_AWAR = "Error (unmapped AWAR):\n"
55    "You cannot write to this field because it is either deleted or\n"
56    "unmapped. Try to select a different item, reselect this and retry.";
57
58char *AW_awar::read_as_string( void ) {
59    if (!gb_var) return strdup("");
60    GB_transaction ta(gb_var);
61    return GB_read_as_string(gb_var);
62}
63
64char *AW_awar::read_string(){
65    aw_assert(variable_type == AW_STRING);
66
67    if (!gb_var) return strdup("");
68    GB_transaction ta(gb_var);
69    return GB_read_string(gb_var);
70}
71
72const char *AW_awar::read_char_pntr(){
73    aw_assert(variable_type == AW_STRING);
74
75    if (!gb_var) return "";
76    GB_transaction ta(gb_var);
77    return GB_read_char_pntr(gb_var);
78}
79
80long AW_awar::read_int() {
81    if (!gb_var) return 0;
82    GB_transaction ta(gb_var);
83    return (long)GB_read_int( gb_var );
84}
85double AW_awar::read_float() {
86    if (!gb_var) return 0.0;
87    GB_transaction ta(gb_var);
88    return GB_read_float(gb_var);
89}
90
91void *AW_awar::read_pointer() {
92    if (!gb_var) return NULL;
93    GB_transaction ta(gb_var);
94    return GB_read_pointer(gb_var);
95}
96
97
98#if defined(DUMP_AWAR_CHANGES)
99#define AWAR_CHANGE_DUMP(name, where, format) fprintf(stderr, "change awar '%s' " where "(" format ")\n", name, para)
100#else
101#define AWAR_CHANGE_DUMP(name, where, format)
102#endif // DEBUG
103
104#define concat(x, y) x##y
105
106#define WRITE_SKELETON(self, type, format, func)        \
107    GB_ERROR AW_awar::self(type para) {                 \
108        if (!gb_var) return AW_MSG_UNMAPPED_AWAR;       \
109        GB_transaction ta(gb_var);                      \
110        AWAR_CHANGE_DUMP(awar_name, #self, format);     \
111        return func(gb_var, para);                      \
112    }                                                   \
113    GB_ERROR AW_awar::concat(re, self)(type para) {     \
114        if (!gb_var) return AW_MSG_UNMAPPED_AWAR;       \
115        GB_transaction ta(gb_var);                      \
116        AWAR_CHANGE_DUMP(awar_name, #self, format);     \
117        GB_ERROR       error = func(gb_var, para);      \
118        GB_touch(gb_var);                               \
119        return error;                                   \
120    }
121
122WRITE_SKELETON(write_string, const char*, "%s", GB_write_string) // defines rewrite_string
123    WRITE_SKELETON(write_int, long, "%li", GB_write_int) // defines rewrite_int
124    WRITE_SKELETON(write_float, double, "%f", GB_write_float) // defines rewrite_float
125    WRITE_SKELETON(write_as_string, const char*, "%s", GB_write_as_string) // defines rewrite_as_string
126    WRITE_SKELETON(write_pointer, void*, "%p", GB_write_pointer) // defines rewrite_pointer
127
128#undef WRITE_SKELETON
129#undef concat
130#undef AWAR_CHANGE_DUMP
131
132
133    void AW_awar::touch( void ) {
134    if (!gb_var) {
135        return;
136    }
137    GB_transaction dummy(gb_var);
138    GB_touch( gb_var );
139}
140
141AW_default aw_main_root_default = (AW_default) "this is a dummy text asfasf asfd";
142
143AW_default aw_check_default_file(AW_default root_default, AW_default default_file,const char *varname)
144{
145    if (default_file == aw_main_root_default)  return root_default;
146    if (default_file == NULL) {
147        AW_ERROR("Creating variable '%s' with zero default file\n",varname);
148        return root_default;
149    }
150    return default_file;
151}
152
153
154// for string
155AW_awar *AW_root::awar_string( const char *var_name, const char *default_value, AW_default default_file ) {
156    AW_awar *vs = (AW_awar *)GBS_read_hash(hash_table_for_variables, (char *)var_name);
157    if (!vs) {
158        default_file = aw_check_default_file(this->application_database,default_file,var_name);
159        vs           = new AW_awar(AW_STRING, var_name, default_value, 0, default_file, this);
160        GBS_write_hash(hash_table_for_variables, (char *)var_name, (long)vs);
161    }
162    return vs;
163}
164
165
166// for int
167AW_awar *AW_root::awar_int(const char *var_name, long default_value, AW_default default_file) {
168    AW_awar *vs = (AW_awar *)GBS_read_hash(hash_table_for_variables, (char *)var_name);
169    if (!vs) {
170        default_file = aw_check_default_file(this->application_database,default_file,var_name);
171        vs           = new AW_awar(AW_INT, var_name, (char *)default_value, 0, default_file, this);
172        GBS_write_hash(hash_table_for_variables, (char *)var_name, (long)vs);
173    }
174    return vs;
175}
176
177
178// for float
179AW_awar *AW_root::awar_float(const char *var_name, float default_value, AW_default default_file) {
180    AW_awar *vs = (AW_awar *)GBS_read_hash(hash_table_for_variables, (char *)var_name);
181    if (!vs) {
182        default_file = aw_check_default_file(this->application_database,default_file,var_name);
183        vs           = new AW_awar(AW_FLOAT, var_name, "", (double)default_value, default_file, this);
184        GBS_write_hash(hash_table_for_variables, (char *)var_name, (long)vs);
185    }
186    return vs;
187}
188
189AW_awar *AW_root::awar_pointer(const char *var_name, void *default_value, AW_default default_file) {
190    AW_awar *vs = (AW_awar *)GBS_read_hash(hash_table_for_variables, (char *)var_name);
191    if (!vs) {
192        default_file = aw_check_default_file(this->application_database,default_file,var_name);
193        vs           = new AW_awar(AW_POINTER, var_name, (const char *)default_value, NULL, default_file, this);
194        GBS_write_hash(hash_table_for_variables, (char *)var_name, (long)vs);
195    }
196    return vs;
197}
198
199AW_awar *AW_root::awar_no_error(const char *var_name){
200    AW_awar *vs = (AW_awar *)GBS_read_hash(hash_table_for_variables, (char *)var_name);
201    return vs;
202}
203
204AW_awar *AW_root::awar(const char *var_name){
205    AW_awar *vs = (AW_awar *)GBS_read_hash(hash_table_for_variables, (char *)var_name);
206    if (vs) return vs;  /* already defined */
207    AW_ERROR("AWAR %s not defined",var_name);
208    return this->awar_string(var_name);
209}
210
211
212AW_awar *AW_awar::add_callback( void (*f)(class AW_root*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2 ) {
213    callback_list = new AW_var_callback(f,cd1,cd2,callback_list);
214    return this;
215}
216
217AW_awar *AW_awar::add_callback( void (*f)(AW_root*,AW_CL), AW_CL cd1 ) { return add_callback((AW_RCB)f,cd1,0); }
218AW_awar *AW_awar::add_callback( void (*f)(AW_root*)){ return add_callback((AW_RCB)f,0,0); }
219
220AW_awar *AW_awar::remove_callback( void (*f)(AW_root*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2 ){
221    // remove a callback, please set unused AW_CL to (AW_CL)0
222    AW_var_callback *prev = 0;
223    for (AW_var_callback *vc = callback_list; vc; vc = vc->next){
224        if (vc->value_changed_cb== f &&
225            vc->value_changed_cb_cd1 == cd1 &&
226            vc->value_changed_cb_cd2 == cd2){
227            if (prev) {
228                prev->next = vc->next;
229            }else{
230                callback_list = vc->next;
231            }
232            delete vc;
233            break;
234        }
235        prev = vc;
236    }
237    return this;
238}
239
240AW_awar *AW_awar::remove_callback(void (*f)(AW_root*, AW_CL), AW_CL cd1) { return remove_callback((AW_RCB) f, cd1, 0); }
241AW_awar *AW_awar::remove_callback(void (*f)(AW_root*)) { return remove_callback((AW_RCB) f, 0, 0); }
242
243void AW_awar::remove_all_callbacks() {
244    while (callback_list) {
245        AW_var_callback *del = callback_list;
246        callback_list        = del->next;
247        delete del;
248    }
249}
250
251
252// --------------------------------------------------------------------------------
253
254bool AW_awar::unlink_from_DB(GBDATA *gb_main) {
255    bool make_zombie = false;
256    if (gb_origin == gb_var) {                      // not mapped
257        if (gb_var) {                               // no zombie awar
258            if (GB_get_root(gb_var) == gb_main) {   // awar is in questionable DB
259                make_zombie = true;
260            }
261        }
262    }
263    else {
264        if (GB_get_root(gb_var) == gb_main) {
265            if (GB_get_root(gb_origin) == gb_main) {
266                // mapped and origin in DB
267                make_zombie = true;
268            }
269            else {
270                // origin is in other DB -> just unmap
271                unmap();
272            }
273        }
274        else {
275            if (GB_get_root(gb_origin) == gb_main) {
276                // origin is in DB, current mapping is not
277                // -> remap permanentely
278                gb_origin = gb_var;
279            }
280            // else both are in other DB -> nothing to do
281        }
282    }
283
284    if (make_zombie) {
285        remove_all_callbacks();
286        remove_all_target_vars();
287        map(AW_default(NULL));                      // map to nothing
288        gb_origin = NULL;                           // make zombie awar (will not unmap)
289    }
290
291    return make_zombie;
292}
293
294long AW_unlink_awar_from_DB(const char *key, long cl_awar, void *cl_gb_main) {
295    AW_awar *awar    = (AW_awar*)cl_awar;
296    GBDATA  *gb_main = (GBDATA*)cl_gb_main;
297
298#if defined(DEBUG) && 0
299    bool is_zombie = awar->unlink_from_DB(gb_main);
300    if (is_zombie) printf("Unlinked awar '%s' from DB\n", key);
301#else
302    AWUSE(key);
303    awar->unlink_from_DB(gb_main);
304#endif // DEBUG
305    return cl_awar;
306}
307
308void AW_root::unlink_awars_from_DB(AW_default database) {
309    GBDATA *gb_main = (GBDATA*)database;
310   
311    aw_assert(GB_get_root(gb_main) == gb_main);
312
313    GB_transaction ta(gb_main); // needed in awar-callbacks during unlink
314    GBS_hash_do_loop(hash_table_for_variables, AW_unlink_awar_from_DB, gb_main);
315}
316
317// --------------------------------------------------------------------------------
318
319GB_ERROR AW_awar::toggle_toggle(){
320    char *var = this->read_as_string();
321    GB_ERROR    error =0;
322    if (var[0] == '0' || var[0] == 'n') {
323        switch (this->variable_type) {
324            case AW_STRING:     error = this->write_string("yes");break;
325            case AW_INT:        error = this->write_int(1);break;
326            case AW_FLOAT:      error = this->write_float(1.0);break;
327            default: break;
328        }
329    }else{
330        switch (this->variable_type) {
331            case AW_STRING:     error = this->write_string("no");break;
332            case AW_INT:        error = this->write_int(0);break;
333            case AW_FLOAT:      error = this->write_float(0.0);break;
334            default: break;
335        }
336    }
337    free(var);
338    return error;
339}
340
341
342
343AW_awar *AW_awar::set_minmax(float min, float max){
344    if (min>max || variable_type == AW_STRING) {
345        AW_ERROR("ERROR: set MINMAX for AWAR '%s' invalid",awar_name);
346    }else{
347        pp.f.min = min;
348        pp.f.max = max;
349        update(); // corrects wrong default value
350    }
351    return this;
352}
353
354
355AW_awar *AW_awar::add_target_var( char **ppchr){
356    if (variable_type != AW_STRING) {
357        AW_ERROR("Cannot set target awar '%s', WRONG AWAR TYPE",awar_name);
358    }else{
359        target_list = new AW_var_target((void *)ppchr,target_list);
360        update_target(target_list);
361    }
362    return this;
363}
364
365AW_awar *AW_awar::add_target_var( float *pfloat){
366    if (variable_type != AW_FLOAT) {
367        AW_ERROR("Cannot set target awar '%s', WRONG AWAR TYPE",awar_name);
368    }else{
369        target_list = new AW_var_target((void *)pfloat,target_list);
370        update_target(target_list);
371    }
372    return this;
373}
374
375AW_awar *AW_awar::add_target_var( long *pint){
376    if (variable_type != AW_INT) {
377        AW_ERROR("Cannot set target awar '%s', WRONG AWAR TYPE",awar_name);
378    }else{
379        target_list = new AW_var_target((void *)pint,target_list);
380        update_target(target_list);
381    }
382    return this;
383}
384
385void AW_awar::remove_all_target_vars() {
386    while (target_list) {
387        AW_var_target *tar = target_list;
388        target_list        = tar->next;
389        delete tar;
390    }
391}
392
393
394AW_awar *AW_awar::set_srt(const char *srt)
395{
396    if (variable_type != AW_STRING) {
397        AW_ERROR("ERROR: set SRT for AWAR '%s' invalid",awar_name);
398    }else{
399        pp.srt = srt;
400    }
401    return this;
402}
403
404
405AW_awar *AW_awar::map(AW_default gbd) {
406    if (gbd) GB_push_transaction((GBDATA *)gbd);
407    if (gb_var) {               /* old map */
408        GB_remove_callback((GBDATA *)gb_var, GB_CB_CHANGED, (GB_CB)AW_var_gbdata_callback, (int *)this);
409        GB_remove_callback((GBDATA *)gb_var, GB_CB_DELETE, (GB_CB)AW_var_gbdata_callback_delete, (int *)this);
410    }
411    if (gbd){
412        GB_add_callback((GBDATA *) gbd, GB_CB_CHANGED, (GB_CB)AW_var_gbdata_callback, (int *)this );
413        GB_add_callback((GBDATA *) gbd, GB_CB_DELETE, (GB_CB)AW_var_gbdata_callback_delete, (int *)this );
414    }
415    gb_var = (GBDATA *)gbd;
416    this->update();
417    if (gbd) GB_pop_transaction((GBDATA *)gbd);
418    return this;
419}
420
421AW_awar *AW_awar::map( AW_awar *dest) {
422    return this->map(dest->gb_var);
423}
424
425AW_awar *AW_awar::unmap( ) {
426    return this->map(gb_origin);
427}
428
429AW_VARIABLE_TYPE AW_awar::get_type(){
430    return this->variable_type;
431}
432
433void AW_awar::update(void)
434{
435    bool out_of_range = false;
436    if (gb_var && ((pp.f.min != pp.f.max) || pp.srt) ) {
437        float fl;
438        char *str;
439        switch (variable_type) {
440            case AW_INT:{
441                long lo;
442
443                lo = this->read_int();
444                if (lo < pp.f.min -.5) {
445                    out_of_range = true;
446                    lo = (int)(pp.f.min + 0.5);
447                }
448                if (lo>pp.f.max + .5) {
449                    out_of_range = true;
450                    lo = (int)(pp.f.max + 0.5);
451                }
452                if (out_of_range) {
453                    if (root) root->changer_of_variable = 0;
454                    this->write_int(lo);
455                    return;             // returns update !!!!
456                }
457                break;
458            }
459            case AW_FLOAT:
460                fl = this->read_float();
461                if (fl < pp.f.min) {
462                    out_of_range = true;
463                    fl = pp.f.min+AWAR_EPS;
464                }
465                if (fl>pp.f.max) {
466                    out_of_range = true;
467                    fl = pp.f.max-AWAR_EPS;
468                }
469                if (out_of_range) {
470                    if (root) root->changer_of_variable = 0;
471                    this->write_float(fl);              // returns update !!!!
472                    return;
473                }
474                break;
475
476            case AW_STRING:
477                str = this->read_string();
478                char *n;
479                n = GBS_string_eval(str,pp.srt,0);
480                if (!n) AW_ERROR("SRT ERROR %s %s", pp.srt, GB_await_error());
481                else{
482                    if (strcmp(n,str)) {
483                        this->write_string(n);
484                        free(n);
485                        free(str);
486                        return;
487                    }
488                    free(n);
489                }
490                free(str);
491                break;
492            default:
493                break;
494        }
495    }
496    this->update_targets();
497    this->run_callbacks();
498}
499
500void AW_awar::run_callbacks(){
501    if (callback_list) callback_list->run_callback(root);
502
503}
504
505// send data to all variables
506void AW_awar::update_target(AW_var_target *pntr){
507    if (!pntr->pointer) return;
508    switch(variable_type) {
509        case AW_STRING: this->get((char **)pntr->pointer);break;
510        case AW_FLOAT:  this->get((float *)pntr->pointer);break;
511        case AW_INT:    this->get((long *)pntr->pointer);break;
512        default:
513            gb_assert(0);
514            GB_warning("Unknown awar type");
515            break;
516    }
517}
518
519// send data to all variables
520void AW_awar::update_targets(void){
521    AW_var_target*pntr;
522    for (pntr = target_list; pntr; pntr = pntr->next){
523        update_target(pntr);
524    }
525}
526
527AW_awar::AW_awar(AW_VARIABLE_TYPE var_type, const char *var_name, const char *var_value, double var_double_value, AW_default default_file, AW_root *rooti){
528    memset((char *)this,0,sizeof(AW_awar));
529    GB_transaction dummy((GBDATA *)default_file);
530
531    aw_assert(var_name && var_name[0] != 0);
532
533#if defined(DEBUG)
534    GB_ERROR err = GB_check_hkey(var_name);
535    aw_assert(!err);
536#endif // DEBUG
537
538    this->awar_name = strdup(var_name);
539    this->root      = rooti;
540    GBDATA *gb_def  = GB_search((GBDATA *)default_file, var_name,GB_FIND);
541
542    GB_TYPES wanted_gbtype = (GB_TYPES)var_type;
543
544    if ( gb_def ) {                                 // belege Variable mit Datenbankwert
545        GB_TYPES gbtype = GB_read_type(gb_def);
546
547        if (gbtype != wanted_gbtype) {
548            GB_warningf("Existing awar '%s' has wrong type (%i instead of %i) - recreating\n",
549                        var_name, int(gbtype), int(wanted_gbtype));
550            GB_delete(gb_def);
551            gb_def = 0;
552        }
553    }
554
555    if (!gb_def) {                                  // belege Variable mit Programmwert
556        gb_def = GB_search( (GBDATA *)default_file, var_name, wanted_gbtype);
557
558        switch (var_type) {
559            case AW_STRING:
560#if defined(DUMP_AWAR_CHANGES)
561                fprintf(stderr, "creating awar_string '%s' with default value '%s'\n", var_name, (char*)var_value);
562#endif // DUMP_AWAR_CHANGES
563                GB_write_string(gb_def, (char *)var_value);
564                break;
565               
566            case AW_INT:
567#if defined(DUMP_AWAR_CHANGES)
568                fprintf(stderr, "creating awar_int '%s' with default value '%li'\n", var_name, (long)var_value);
569#endif // DUMP_AWAR_CHANGES
570                GB_write_int(gb_def, (long)var_value);
571                break;
572               
573            case AW_FLOAT:
574#if defined(DUMP_AWAR_CHANGES)
575                fprintf(stderr, "creating awar_float '%s' with default value '%f'\n", var_name, (double)var_double_value);
576#endif // DUMP_AWAR_CHANGES
577                GB_write_float(gb_def, (double)var_double_value);
578                break;
579
580            case AW_POINTER: 
581#if defined(DUMP_AWAR_CHANGES)
582                fprintf(stderr, "creating awar_pointer '%s' with default value '%p'\n", var_name, (void*)var_value);
583#endif // DUMP_AWAR_CHANGES
584                GB_write_pointer(gb_def, (void*)var_value);
585                break;
586               
587            default:
588                GB_warningf("AWAR '%s' cannot be created because of disallowed type",var_name);
589                break;
590        }
591    }
592    variable_type               = var_type;
593    this->gb_origin = gb_def;
594    this->map(gb_def);
595}
596
597
598
599AW_default AW_root::open_default(const char *default_name, bool create_if_missing)
600{
601    if (!create_if_missing) { // used to check for existing specific properties
602        const char *home   = GB_getenvHOME();
603        char       *buffer = (char *)GB_calloc(sizeof(char),strlen(home)+ strlen(default_name) + 2);
604
605        sprintf(buffer,"%s/%s", home, default_name);
606
607        struct stat st;
608        bool        found = stat(buffer, &st) == 0;
609
610        free(buffer);
611
612        if (!found) return 0;
613    }
614
615#if defined(DEVEL_RALF)
616#warning gb_default is never closed
617    // close it somewhere and call AWT_browser_forget_db as well
618#endif // DEVEL_RALF
619
620    GBDATA *gb_default = GB_open(default_name, "rwcD");
621
622    if (gb_default) {
623        GB_no_transaction(gb_default);
624
625        GBDATA *gb_tmp = GB_search(gb_default, "tmp", GB_CREATE_CONTAINER);
626        GB_set_temporary(gb_tmp);
627#if defined(DEBUG)
628        AWT_announce_db_to_browser(gb_default, GBS_global_string("Properties (%s)", default_name));
629#endif // DEBUG
630    }
631    else {
632        GB_ERROR    error           = GB_await_error();
633        const char *shown_name      = strrchr(default_name, '/');
634        if (!shown_name) shown_name = default_name;
635
636        GBK_terminatef("Error loading properties '%s': %s", shown_name, error);
637    }
638    return (AW_default) gb_default;
639}
640
641
642AW_error *AW_root::save_default( const char *var_name ) {
643    return save_default(var_name, NULL);
644}
645
646AW_error *AW_root::save_default( const char *var_name, const char *file_name) {
647    AW_awar *vs;
648    if ( (vs = this->awar( var_name ))  ) {
649        AW_root::save_default((AW_default)vs->gb_var, file_name);
650        return 0;
651    }else {
652        AW_ERROR("AW_root::save_default: Variable %s not defined", var_name);
653    }
654    return 0;
655
656}
657
658AW_error *AW_root::save_default(AW_default aw_default, const char *file_name)
659{
660    GBDATA *gb_main = GB_get_root((GBDATA *)aw_default);
661    GB_push_transaction(gb_main);
662    aw_update_awar_window_geometry(this);
663    GB_pop_transaction(gb_main);
664    GB_save_in_home(gb_main,file_name,"a");
665    return 0;
666}
667
668AW_default AW_root::get_default(const char *varname) {
669    GBDATA      *gbd;
670    AW_awar *vs;
671    if ( (vs = this->awar( varname )) ) {
672        gbd = vs->gb_var;
673        return (AW_default)GB_get_root(gbd);
674    }else {
675        AW_ERROR("AW_root::get_default: Variable %s not defined", varname);
676    }
677    return 0;
678}
679
680AW_default AW_root::get_gbdata( const char *varname) {
681    GBDATA      *gbd;
682    AW_awar *vs;
683    if ( (vs = this->awar( varname )) ) {
684        gbd = vs->gb_var;
685        return (AW_default)gbd;
686    }else {
687        AW_ERROR("AW_root::get_gbdata: Variable %s not defined", varname);
688    }
689    return 0;
690}
691
692AW_awar *AW_root::label_is_awar(const char *label) {
693    AW_awar *awar_exists = NULL;
694    size_t   off         = strcspn(label, "/ ");
695
696    if (label[off] == '/') {                        // contains '/' and no space before first '/'
697        awar_exists = awar_no_error(label);
698    }
699    return awar_exists;
700}
701
702// ---------------------------
703//      Awar_Callback_Info
704// ---------------------------
705
706void Awar_Callback_Info::remap(const char *new_awar) {
707    if (strcmp(awar_name, new_awar) != 0) {
708        remove_callback();
709        freedup(awar_name, new_awar);
710        add_callback();
711    }
712}
713void Awar_Callback_Info::init(AW_root *awr_, const char *awar_name_, Awar_CB2 callback_, AW_CL cd1_, AW_CL cd2_) {
714    awr           = awr_;
715    callback      = callback_;
716    cd1           = cd1_;
717    cd2           = cd2_;
718    awar_name     = strdup(awar_name_);
719    org_awar_name = strdup(awar_name_);
720}
721
722void aw_create_selection_box_awars(AW_root *awr, const char *awar_base,
723                                   const char *directory, const char *filter, const char *file_name,
724                                   AW_default default_file, bool resetValues)
725{
726    int   base_len  = strlen(awar_base);
727    bool  has_slash = awar_base[base_len-1] == '/';
728    char *awar_name = new char[base_len+30]; // use private buffer, because caller will most likely use GBS_global_string for arguments
729
730    sprintf(awar_name, "%s%s", awar_base, "/directory"+int(has_slash));
731    AW_awar *awar_dir = awr->awar_string(awar_name, directory, default_file);
732
733    sprintf(awar_name, "%s%s", awar_base, "/filter"   +int(has_slash));
734    AW_awar *awar_filter = awr->awar_string(awar_name, filter, default_file);
735
736    sprintf(awar_name, "%s%s", awar_base, "/file_name"+int(has_slash));
737    AW_awar *awar_filename = awr->awar_string(awar_name, file_name, default_file);
738
739    if (resetValues) {
740        awar_dir->write_string(directory);
741        awar_filter->write_string(filter);
742        awar_filename->write_string(file_name);
743    }
744    else {
745        char *stored_directory = awar_dir->read_string();
746#if defined(DEBUG)
747        if (strncmp(awar_base, "tmp/", 4) == 0) { // non-saved awar
748            if (directory[0] != 0) { // accept empty dir (means : use current ? )
749                aw_assert(GB_is_directory(directory)); // default directory does not exist
750            }
751        }
752#endif // DEBUG
753
754        if (strcmp(stored_directory, directory) != 0) { // does not have default value
755#if defined(DEBUG)
756            const char *arbhome    = GB_getenvARBHOME();
757            int         arbhomelen = strlen(arbhome);
758
759            if (strncmp(directory, arbhome, arbhomelen) == 0) { // default points into $ARBHOME
760                aw_assert(resetValues); // should be called with resetValues == true
761                // otherwise it's possible, that locations from previously installed ARB versions are used
762            }
763#endif // DEBUG
764
765            if (!GB_is_directory(stored_directory)) {
766                awar_dir->write_string(directory);
767                fprintf(stderr,
768                        "Warning: Replaced reference to non-existing directory '%s'\n"
769                        "         by '%s'\n"
770                        "         (Save properties to make this change permanent)\n",
771                        stored_directory, directory);
772            }
773        }
774
775        free(stored_directory);
776    }
777
778    char *dir = awar_dir->read_string();
779    if (dir[0] && !GB_is_directory(dir)) {
780        if (aw_ask_sure(GBS_global_string("Directory '%s' does not exist. Create?", dir))) {
781            GB_ERROR error = GB_create_directory(dir);
782            if (error) aw_message(GBS_global_string("Failed to create directory '%s' (Reason: %s)", dir, error));
783        }
784    }
785    free(dir);
786
787    delete [] awar_name;
788}
Note: See TracBrowser for help on using the repository browser.