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

Last change on this file was 6149, 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: 112.3 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <iostream>
4#include <memory.h>
5#include <Xm/Xm.h>
6#include <Xm/Frame.h>
7#include <Xm/MenuShell.h>
8#include <Xm/RowColumn.h>
9#include <Xm/ToggleB.h>
10#include <Xm/Label.h>
11#include <Xm/List.h>
12#include <Xm/PushB.h>
13#include <Xm/Text.h>
14#include <Xm/TextF.h>
15#include <Xm/ScrolledW.h>
16
17#include <arbdb.h>
18#include <arbdbt.h>
19#include "aw_root.hxx"
20#include "aw_at.hxx"
21#include "aw_device.hxx"
22#include "aw_Xm.hxx"
23#include "aw_click.hxx"
24#include "aw_print.hxx"
25#include "aw_size.hxx"
26#include "aw_window.hxx"
27#include "aw_awar.hxx"
28#include "aw_window_Xm.hxx"
29
30#include <inline.h>
31
32#if defined(DEBUG)
33// #define DUMP_BUTTON_CREATION
34#endif // DEBUG
35
36/*********************************************************************************************************************/
37/*********************************************************************************************************************/
38/*********************************************************************************************************************/
39static void aw_cp_awar_2_widget_cb(AW_root *root, AW_widget_list_for_variable *widgetlist){
40    if (widgetlist->widget == (int *)root->changer_of_variable){
41        root->changer_of_variable = 0;
42        root->value_changed = false;
43        return;
44    }
45
46    {
47        char *var_value;
48        var_value = widgetlist->awar->read_as_string();
49
50        // und benachrichtigen der anderen
51        switch(widgetlist->widget_type) {
52
53            case AW_WIDGET_INPUT_FIELD:
54                widgetlist->aw->update_input_field(widgetlist->widget, var_value );
55                break;
56            case AW_WIDGET_TEXT_FIELD:
57                widgetlist->aw->update_text_field(widgetlist->widget, var_value );
58                break;
59            case AW_WIDGET_TOGGLE:
60                widgetlist->aw->update_toggle(widgetlist->widget, var_value, widgetlist->cd );
61                break;
62            case AW_WIDGET_LABEL_FIELD:
63                widgetlist->aw->update_label( widgetlist->widget, var_value );
64                break;
65            case AW_WIDGET_CHOICE_MENU:
66                widgetlist->aw->update_option_menu( (AW_option_menu_struct*)widgetlist->cd );
67                break;
68            case AW_WIDGET_TOGGLE_FIELD:
69                widgetlist->aw->update_toggle_field( (int)widgetlist->cd );
70                break;
71            case AW_WIDGET_SELECTION_LIST:
72                widgetlist->aw->update_selection_list_intern( (AW_selection_list *)widgetlist->cd );
73            default:
74                break;
75        }
76        free(var_value);
77    }
78    root->value_changed = false;     // Maybe value changed is set because Motif calls me
79}
80
81
82AW_widget_list_for_variable::AW_widget_list_for_variable( AW_awar *vs, AW_CL cd1, int *widgeti, AW_widget_type type, AW_window *awi ) {
83    cd          = cd1;
84    widget      = widgeti;
85    widget_type = type;
86    awar        = vs;
87    aw          = awi;
88    next        = 0;
89    awar->add_callback((AW_RCB1)aw_cp_awar_2_widget_cb, (AW_CL)this);
90}
91
92/********************************* Used for single items in lists ****************************************/
93
94struct AW_variable_update_struct {
95    AW_variable_update_struct( Widget widgeti, AW_widget_type widget_typei, AW_awar *awari, const char *var_s_i, int var_i_i, float var_f_i, AW_cb_struct *cbsi );
96    AW_awar        *awar;
97    Widget          widget;
98    AW_widget_type  widget_type;
99    char           *variable_value;
100    long            variable_int_value;
101    float           variable_float_value;
102    AW_cb_struct   *cbs;
103    void           *id;         // selection id etc ...
104};
105
106AW_variable_update_struct::AW_variable_update_struct(Widget widgeti,
107        AW_widget_type widget_typei, AW_awar *awari, const char *var_s_i,
108        int var_i_i, float var_f_i, AW_cb_struct *cbsi) {
109
110    widget = widgeti;
111    widget_type = widget_typei;
112    awar = awari;
113    if (var_s_i) {
114        variable_value = strdup(var_s_i);
115    } else {
116        variable_value = 0;
117    }
118    variable_int_value = var_i_i; // used for toggles and selection menus
119    variable_float_value = var_f_i;
120    cbs = cbsi;
121
122}
123
124
125void AW_variable_update_callback( Widget wgt, XtPointer variable_update_struct, XtPointer call_data ) {
126    AWUSE(wgt);AWUSE(call_data);
127    AW_variable_update_struct *vus   = (AW_variable_update_struct *) variable_update_struct;
128
129    aw_assert(vus);
130
131    char                      *tmp   = 0;
132    long                       h_int;
133    float                      h_float;
134    GB_ERROR                   error = 0;
135    XmListCallbackStruct      *xml;
136    AW_root                   *root  = vus->awar->root;
137
138    if (root->value_changed){
139        root->changer_of_variable = (long)vus->widget;
140    }
141
142    switch (vus->widget_type) {
143
144        case AW_WIDGET_INPUT_FIELD:
145        case AW_WIDGET_TEXT_FIELD:
146            if (!root->value_changed) return;
147            tmp = XmTextGetString( (vus->widget) );
148
149            switch ( vus->awar->variable_type ) {
150                case AW_STRING:
151                    error   = vus->awar->write_string( tmp );
152                    break;
153                case AW_INT:
154                    h_int   = atoi(tmp);
155                    error   = vus->awar->write_int( h_int );
156                    break;
157                case AW_FLOAT:
158                    h_float = atof(tmp);
159                    error   = vus->awar->write_float( h_float );
160                    break;
161                default:
162                    gb_assert(0);
163                    error = GB_export_error("Unknown or incompatible AWAR type");
164            }
165            XtFree( tmp );
166            break;
167
168        case AW_WIDGET_TOGGLE:
169            root->changer_of_variable = 0;
170            error = vus->awar->toggle_toggle();
171            break;
172
173        case AW_WIDGET_TOGGLE_FIELD:
174            int state;
175            state = XmToggleButtonGetState(vus->widget);
176            if (state != True) break;
177            // fall-through
178
179        case AW_WIDGET_CHOICE_MENU:
180            switch ( vus->awar->variable_type ) {
181                case AW_STRING: error = vus->awar->write_string( vus->variable_value );      break;
182                case AW_INT:    error = vus->awar->write_int(vus->variable_int_value );      break;
183                case AW_FLOAT:  error = vus->awar->write_float( vus->variable_float_value ); break;
184#if defined(DEVEL_RALF)
185#warning missing implementation for AW_POINTER                     
186#endif // DEVEL_RALF
187                default:
188                    gb_assert(0);
189                    GB_warning("Unknown AWAR type");
190                    break;
191            }
192            break;
193
194
195        case AW_WIDGET_SELECTION_LIST: {
196            char                   *ptr;
197            AW_selection_list      *selection_list;
198            AW_select_table_struct *list_table;
199            bool                    found;
200            found = false;
201            xml   = (XmListCallbackStruct*)call_data;
202
203            XmStringGetLtoR( xml->item, XmSTRING_DEFAULT_CHARSET, &tmp );
204
205
206            selection_list = ((AW_selection_list *)(vus->id));
207
208            for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) {
209                ptr = list_table->displayed;
210                if ( strcmp( tmp, ptr ) == 0 ) {
211                    break;
212                }
213            }
214            if ( !list_table ) { // test if default selection exists
215                list_table = selection_list->default_select;
216                if (!list_table) {
217                    AW_ERROR("no default for selection list specified");
218                    return;
219                }
220            }
221            switch ( vus->awar->variable_type ) {
222                case AW_STRING:
223                    error = vus->awar->write_string( list_table->char_value );
224                    break;
225                case AW_INT:
226                    error = vus->awar->write_int( list_table->int_value );
227                    break;
228                case AW_FLOAT:
229                    error = vus->awar->write_float( list_table->float_value );
230                    break;
231                case AW_POINTER:
232                    error = vus->awar->write_pointer( list_table->pointer_value );
233                    break;
234                default:
235                    gb_assert(0);
236                    error = GB_export_error("Unknown AWAR type");
237                    break;
238            }
239            XtFree( tmp );
240            break;
241        }
242        case AW_WIDGET_LABEL_FIELD:
243            break;
244        default:
245            gb_assert(0);
246            GB_warning("Unknown Widget Type");
247            break;
248    }
249
250    if (error) {
251        root->changer_of_variable = 0;
252        vus->awar->update();
253        aw_message(error);
254    }
255    else {
256        if (root->prvt->recording_macro_file) {
257            fprintf(root->prvt->recording_macro_file,"BIO::remote_awar($gb_main,\"%s\",",root->prvt->application_name_for_macros);
258            GBS_fwrite_string(vus->awar->awar_name,root->prvt->recording_macro_file);
259            fprintf(root->prvt->recording_macro_file,",");
260            char *value = vus->awar->read_as_string();
261            GBS_fwrite_string(value,root->prvt->recording_macro_file);
262            free(value);
263            fprintf(root->prvt->recording_macro_file,");\n");
264        }
265        if (vus->cbs) vus->cbs->run_callback();
266        root->value_changed = false;
267    }
268}
269
270
271void AW_value_changed_callback( Widget wgt, XtPointer rooti, XtPointer call_data ) {
272    AWUSE(wgt);AWUSE(call_data);
273    AW_root *root = (AW_root *)rooti;
274    root->value_changed = true;
275}
276
277
278
279/****************************************************************************************************************************/
280/****************************************************************************************************************************/
281
282void     aw_attach_widget(Widget scrolledWindowText,AW_at *_at,int default_width = -1){
283    short height = 0;
284    short width = 0;
285    if (!_at->to_position_exists){
286        XtVaGetValues( scrolledWindowText, XmNheight, &height, XmNwidth, &width,NULL );
287        if (default_width >0) width = default_width;
288
289        switch (_at->correct_for_at_center) {
290            case 0:             // left justified
291                _at->to_position_x      = _at->x_for_next_button + width;
292                break;
293            case 1:             // centered
294                _at->to_position_x      = _at->x_for_next_button + width/2;
295                _at->x_for_next_button -= width/2;
296                break;
297            case 2:             // right justified
298                _at->to_position_x      = _at->x_for_next_button;
299                _at->x_for_next_button -= width;
300                break;
301        }
302        _at->to_position_y = _at->y_for_next_button + height;
303        _at->attach_x      = _at->attach_lx;
304        _at->attach_y      = _at->attach_ly;
305    }
306
307#define MIN_RIGHT_OFFSET  10
308#define MIN_BOTTOM_OFFSET 10
309
310    if (_at->attach_x) {
311        int right_offset = _at->max_x_size - _at->to_position_x;
312        if (right_offset<MIN_RIGHT_OFFSET) {
313            right_offset    = MIN_RIGHT_OFFSET;
314            _at->max_x_size = _at->to_position_x+right_offset;
315        }
316
317        XtVaSetValues(  scrolledWindowText,
318                        XmNrightAttachment,     XmATTACH_FORM,
319                        XmNrightOffset,         right_offset,
320                        NULL );
321    }else{
322        XtVaSetValues(  scrolledWindowText,
323                        XmNrightAttachment,     XmATTACH_OPPOSITE_FORM,
324                        XmNrightOffset,         -_at->to_position_x,
325                        NULL );
326    }
327    if (_at->attach_lx) {
328        XtVaSetValues(  scrolledWindowText,
329                        XmNwidth,               _at->to_position_x - _at->x_for_next_button,
330                        XmNleftAttachment,      XmATTACH_NONE,
331                        NULL );
332    }else{
333        XtVaSetValues(  scrolledWindowText,
334                        XmNleftAttachment,      XmATTACH_FORM,
335                        XmNleftOffset,          _at->x_for_next_button,
336                        NULL );
337    }
338
339    if (_at->attach_y) {
340        int bottom_offset = _at->max_y_size - _at->to_position_y;
341        if (bottom_offset<MIN_BOTTOM_OFFSET) {
342            bottom_offset   = MIN_BOTTOM_OFFSET;
343            _at->max_y_size = _at->to_position_y+bottom_offset;
344        }
345
346        XtVaSetValues(  scrolledWindowText,
347                        XmNbottomAttachment,    XmATTACH_FORM,
348                        XmNbottomOffset,        bottom_offset,
349                        NULL );
350    }else{
351        XtVaSetValues(  scrolledWindowText,
352                        XmNbottomAttachment,    XmATTACH_OPPOSITE_FORM,
353                        XmNbottomOffset,        - _at->to_position_y,
354                        NULL );
355    }
356    if (_at->attach_ly){
357        XtVaSetValues(  scrolledWindowText,
358                        XmNheight,              _at->to_position_y - _at->y_for_next_button,
359                        XmNtopAttachment,       XmATTACH_NONE,
360                        NULL );
361
362    }else{
363        XtVaSetValues(  scrolledWindowText,
364                        XmNtopAttachment,       XmATTACH_FORM,
365                        XmNtopOffset,           _at->y_for_next_button,
366                        NULL );
367    }
368}
369/****************************************************************************************************************************/
370
371static char *pixmapPath(const char *pixmapName) {
372    return nulldup(GB_path_in_ARBLIB("pixmaps", pixmapName));
373}
374
375
376#define MAX_LINE_LENGTH 200
377static GB_ERROR detect_bitmap_size(const char *pixmapname, int *width, int *height) {
378    GB_ERROR err = 0;
379
380    *width  = 0;
381    *height = 0;
382
383    char *path = pixmapPath(pixmapname);
384    FILE *in   = fopen(path, "rt");
385    if (in) {
386        const char *subdir = strrchr(pixmapname, '/');
387        char       *name   = strdup(subdir ? subdir+1 : pixmapname);
388        {
389            char *dot       = strrchr(name, '.');
390            if (dot) dot[0] = 0;
391            else  err       = "'.' expected";
392        }
393        int  namelen = strlen(name);
394        char buffer[MAX_LINE_LENGTH];
395        bool done    = false;
396
397        while (!done && !err) {
398            fgets(buffer, MAX_LINE_LENGTH, in);
399            if (strchr(buffer, 0)[-1] != '\n') {
400                err = GBS_global_string("Line too long ('%s')", buffer); // increase MAX_LINE_LENGTH above
401            }
402            else if (strncmp(buffer, "#define", 7) != 0) {
403                done = true;
404            }
405            else {
406                char *name_pos = strstr(buffer+7, name);
407                if (name_pos) {
408                    char *behind = name_pos+namelen;
409                    if (strncmp(behind, "_width ", 7) == 0) *width = atoi(behind+7);
410                    else if (strncmp(behind, "_height ", 8) == 0) *height = atoi(behind+8);
411                }
412            }
413        }
414
415        if (done && ((*width == 0) || (*height == 0))) {
416            if (strstr(buffer, "XPM") != NULL) {
417                fgets(buffer, MAX_LINE_LENGTH, in);
418                fgets(buffer, MAX_LINE_LENGTH, in);
419                char *temp = strtok(buffer+1, " ");
420                *width = atoi(temp);
421                temp = strtok(NULL,  " ");
422                *height = atoi(temp);
423            }
424            else {
425                err = "can't detect size";
426            }
427        }
428
429        free(name);
430        fclose(in);
431    }
432    else {
433        err = "no such file";
434    }
435
436    if (err) {
437        err = GBS_global_string("%s: %s", pixmapname, err);
438    }
439
440#if defined(DUMP_BUTTON_CREATION)
441    printf("Bitmap '%s' has size %i/%i\n", pixmapname, *width, *height);
442#endif // DUMP_BUTTON_CREATION
443
444    free(path);
445    return err;
446}
447#undef MAX_LINE_LENGTH
448
449inline void calculate_textsize(const char *str, int *width, int *height) {
450    int textwidth  = 0;
451    int textheight = 1;
452    int linewidth  = 0;
453
454    for (int p = 0; str[p]; ++p) {
455        if (str[p] == '\n') {
456            if (linewidth>textwidth) textwidth = linewidth;
457
458            linewidth = 0;
459            textheight++;
460        }
461        else {
462            linewidth++;
463        }
464    }
465
466    if (linewidth>textwidth) textwidth = linewidth;
467
468    *width  = textwidth;
469    *height = textheight;
470}
471
472
473/****************************************************************************************************************************/
474
475static void calculate_label_size(AW_window *aww, int *width, int *height, bool in_pixel, const char *non_at_label) {
476    // in_pixel == true -> calculate size in pixels
477    // in_pixel == false -> calculate size in characters
478
479    const char *label = non_at_label ? non_at_label : aww->_at->label_for_inputfield;
480    if (label) {
481        calculate_textsize(label, width, height);
482        if (aww->_at->length_of_label_for_inputfield) {
483            *width = aww->_at->length_of_label_for_inputfield;
484        }
485        if (in_pixel) {
486            *width  = aww->calculate_string_width(*width);
487            *height = aww->calculate_string_height(*height, 0);
488        }
489    }
490    else {
491        *width  = 0;
492        *height = 0;
493    }
494
495    // if (_at->length_of_label_for_inputfield) return _at->length_of_label_for_inputfield;
496    // if (_at->label_for_inputfield) return strlen(_at->label_for_inputfield);
497    // return 0;
498}
499
500
501/****************************************************************************************************************************/
502
503Widget AW_window::get_last_widget() const {
504    return p_global->get_last_widget();
505}
506
507void aw_detect_text_size(const char *text, size_t& width, size_t& height) {
508    size_t text_width = strcspn(text, "\n");
509
510    if (text[text_width]) {
511        aw_assert(text[text_width] == '\n');
512
513        aw_detect_text_size(text+text_width+1, width, height);
514        if (text_width>width) width = text_width;
515        height++;
516    }
517    else { // EOS
518        width  = text_width;
519        height = 1;
520    }
521}
522
523void AW_window::create_autosize_button(const char *macro_name, AW_label buttonlabel, const  char *mnemonic, unsigned xtraSpace) {
524    aw_assert(buttonlabel[0] != '#');               // use create_button() for graphical buttons!
525
526    AW_awar *is_awar = get_root()->label_is_awar(buttonlabel);
527    size_t   width, height;
528    if (is_awar) {
529        char *content = is_awar->read_as_string();
530        aw_assert(content[0]); /* you need to fill the awar before calling create_autosize_button,
531                                * otherwise size cannot be detected */
532        aw_detect_text_size(content, width, height);
533    }
534    else {
535        aw_detect_text_size(buttonlabel, width, height);
536    }
537
538    int   len               = width+(xtraSpace*2);
539    short length_of_buttons = _at->length_of_buttons;
540    short height_of_buttons = _at->height_of_buttons;
541
542    _at->length_of_buttons = len+1;
543    _at->height_of_buttons = height;
544    create_button(macro_name, buttonlabel, mnemonic);
545    _at->length_of_buttons = length_of_buttons;
546    _at->height_of_buttons = height_of_buttons;
547}
548
549void AW_window::create_button(const char *macro_name, AW_label buttonlabel, const  char *mnemonic, const char *color) {
550    // Create a button or text display.
551    //
552    // If a callback is bound via at->callback(), a button is created.
553    // Otherwise a text display is created.
554    //
555    // if buttonlabel starts with '#' the rest of buttonlabel is used as name of bitmap file used for button
556    // if buttonlabel contains a '/' it's interpreted as AWAR name and the button displays the content of the awar
557    // otherwise buttonlabel is interpreted as button label (may contain '\n').
558    //
559    // Note 1: Button width 0 does not work together with labels!
560
561    // Note 2: "color" may be specified for the button background (see TuneOrSetBackground for details)
562
563    TuneOrSetBackground(_at->attach_any ? INFO_FORM : INFO_WIDGET, // set background for buttons / text displays
564                        color,
565                        _callback ? TUNE_BUTTON : 0); 
566
567    AWUSE(mnemonic);
568
569#if defined(DUMP_BUTTON_CREATION)
570    printf("------------------------------ Button '%s'\n", buttonlabel);
571    printf("x_for_next_button=%i y_for_next_button=%i\n", _at->x_for_next_button, _at->y_for_next_button);
572#endif // DUMP_BUTTON_CREATION
573
574    check_at_pos();
575
576    if (_callback && ((long)_callback!= 1) )
577    {
578        if (macro_name){
579            _callback->id = GBS_global_string_copy("%s/%s",this->window_defaults_name,macro_name);
580            get_root()->define_remote_command(_callback);
581        }
582        else {
583            _callback->id = 0;
584        }
585    }
586
587#define SPACE_BEHIND_LABEL  10
588#define SPACE_BEHIND_BUTTON 3
589
590#define BUTTON_TEXT_X_PADDING 4
591#define BUTTON_TEXT_Y_PADDING 10
592   
593#define BUTTON_GRAPHIC_PADDING 12
594#define FLAT_GRAPHIC_PADDING   4 // for buttons w/o callback
595
596    bool is_graphical_button = buttonlabel[0] == '#';
597   
598#if defined(DEBUG)
599    AW_awar *is_awar = is_graphical_button ? NULL : get_root()->label_is_awar(buttonlabel);
600#endif // DEBUG
601
602    int width_of_button = -1, height_of_button = -1;
603
604    int width_of_label, height_of_label;
605    calculate_label_size(this, &width_of_label, &height_of_label, true, 0);
606    int width_of_label_and_spacer = _at->label_for_inputfield ? width_of_label+SPACE_BEHIND_LABEL : 0;
607
608    bool let_motif_choose_size  = false;
609
610    if (_at->to_position_exists) { // size has explicitly been specified in xfig -> calculate
611        width_of_button  = _at->to_position_x - _at->x_for_next_button - width_of_label_and_spacer;
612        height_of_button = _at->to_position_y - _at->y_for_next_button;
613    }
614    else if (_at->length_of_buttons) { // button width specified from client code
615        width_of_button  = BUTTON_TEXT_X_PADDING + calculate_string_width(_at->length_of_buttons+1);
616
617        if (!is_graphical_button) {
618            if (_at->height_of_buttons) { // button height specified from client code
619                height_of_button = BUTTON_TEXT_Y_PADDING + calculate_string_height(_at->height_of_buttons, 0);
620            }
621            else {
622                int textwidth, textheight;
623                calculate_textsize(buttonlabel, &textwidth, &textheight);
624                height_of_button = BUTTON_TEXT_Y_PADDING + calculate_string_height(textheight, 0);
625            }
626        }
627        else {
628            height_of_button = BUTTON_TEXT_Y_PADDING + calculate_string_height(1, 0);
629        }
630    }
631    else { // no button_length() specified
632        aw_assert(!is_awar); // please specify button_length() for AWAR button!
633
634        if (is_graphical_button) {
635            int      width, height;
636            GB_ERROR err = detect_bitmap_size(buttonlabel+1, &width, &height);
637
638            if (!err) {
639                int gpadding = _callback ? BUTTON_GRAPHIC_PADDING : FLAT_GRAPHIC_PADDING;
640
641                width_of_button  = width+gpadding;
642                height_of_button = height+gpadding;
643            }
644            else {
645                aw_assert(0);   // oops - failed to detect bitmap size
646                let_motif_choose_size = true;
647            }
648        }
649        else {
650            int textwidth, textheight;
651            calculate_textsize(buttonlabel, &textwidth, &textheight);
652
653            width_of_button  = BUTTON_TEXT_X_PADDING + calculate_string_width(textwidth+1);
654            height_of_button = BUTTON_TEXT_Y_PADDING + calculate_string_height(textheight, 0);
655        }
656    }
657
658    if (!let_motif_choose_size) {
659        if (height_of_button<height_of_label) height_of_button = height_of_label;
660        aw_assert(width_of_button && height_of_button);
661    }
662
663    int x_label  = _at->x_for_next_button;
664    int y_label  = _at->y_for_next_button;
665    int x_button = x_label + width_of_label_and_spacer;
666    int y_button = y_label;
667
668    int org_correct_for_at_center = _at->correct_for_at_center; // store original justification
669    int org_y_for_next_button     = _at->y_for_next_button; // store original y pos (modified while creating label)
670
671    if (!let_motif_choose_size) { // don't correct position of button w/o known size
672        // calculate justification manually
673
674        int width_of_button_and_highlight = width_of_button + (_at->highlight ? 2*(_at->shadow_thickness+1)+1 : 0);
675        int width_of_label_and_button     = width_of_label_and_spacer+width_of_button_and_highlight;
676
677        if (_at->correct_for_at_center) { // not if left justified
678            int shiftback = width_of_label_and_button; // shiftback for right justification
679            if (_at->correct_for_at_center == 1) { // center justification
680                shiftback /= 2;
681            }
682            x_label  -= shiftback;
683            x_button -= shiftback;
684        }
685
686        // we already did the justification by calculating all positions manually, so..
687        _at->correct_for_at_center = 0; // ..from now on act like "left justified"!
688    }
689
690    // correct label Y position
691    if (_callback) {            // only if button is a real 3D-button
692        y_label += (height_of_button-height_of_label)/2;
693    }
694
695    Widget parent_widget = (_at->attach_any) ? INFO_FORM : INFO_WIDGET;
696    Widget tmp_label         = 0;
697
698    if (_at->label_for_inputfield) {
699        _at->x_for_next_button = x_label;
700        _at->y_for_next_button = y_label;
701
702        tmp_label = XtVaCreateManagedWidget( "label",
703                                         xmLabelWidgetClass,
704                                         parent_widget,
705                                         XmNwidth, (int)(width_of_label + 2),
706                                         RES_LABEL_CONVERT(_at->label_for_inputfield),
707                                         XmNrecomputeSize, false,
708                                         XmNalignment, XmALIGNMENT_BEGINNING,
709                                         XmNfontList, p_global->fontlist,
710                                         XmNx, (int)(x_label),
711                                         XmNy, (int)(y_label),
712                                         NULL );
713
714        if (_at->attach_any) aw_attach_widget(tmp_label,_at);
715        AW_label_in_awar_list(this,tmp_label,_at->label_for_inputfield);
716    }
717
718    _at->x_for_next_button = x_button;
719    _at->y_for_next_button = y_button;
720
721    Widget fatherwidget = parent_widget; // used as father for button below
722    if ( _at->highlight ) {
723        if (_at->attach_any) {
724#if defined(DEBUG)
725            printf("Attaching highlighted buttons does not work - "
726                   "highlight ignored for button '%s'!\n", buttonlabel);
727#endif // DEBUG
728            _at->highlight = false;
729        }
730        else {
731            int shadow_offset = _at->shadow_thickness;
732            int x_shadow      = x_button - shadow_offset;
733            int y_shadow      = y_button - shadow_offset;
734
735            // x_button += shadow_offset;
736
737            fatherwidget = XtVaCreateManagedWidget( "draw_area",
738                                                    xmFrameWidgetClass,
739                                                    INFO_WIDGET,
740                                                    XmNx, (int)(x_shadow),
741                                                    XmNy, (int)(y_shadow),
742                                                    // XmNmarginWidth, 3,
743                                                    // XmNmarginHeight,3,
744                                                    XmNshadowType, XmSHADOW_IN,
745                                                    XmNshadowThickness, _at->shadow_thickness,
746                                                    NULL);
747        }
748    }
749
750    Widget  button       = 0;
751    char   *mwidth       = let_motif_choose_size ? 0 : XmNwidth; // 0 means autodetect by motif
752    char   *mheight      = let_motif_choose_size ? 0 : XmNheight;
753   
754    if (_callback) {
755        if (_at->attach_any) { // attached button with callback
756            button = XtVaCreateManagedWidget( "button",
757                                              xmPushButtonWidgetClass,
758                                              fatherwidget,
759                                              RES_LABEL_CONVERT(buttonlabel),
760                                              XmNx, (int)(x_button),
761                                              XmNy, (int)(y_button),
762                                              XmNshadowThickness, _at->shadow_thickness,
763                                              XmNalignment, XmALIGNMENT_CENTER,
764                                              XmNfontList, p_global->fontlist,
765                                              XmNbackground, _at->background_color,
766                                              mwidth, (int)width_of_button, // may terminate the list
767                                              mheight, (int)height_of_button, // may terminate the list
768                                              NULL );
769            aw_attach_widget(button,_at);
770        }
771        else { // unattached button with callback
772            button = XtVaCreateManagedWidget( "label",
773                                              xmPushButtonWidgetClass,
774                                              fatherwidget,
775                                              RES_LABEL_CONVERT(buttonlabel),
776                                              XmNx, (int)(x_button),
777                                              XmNy, (int)(y_button),
778                                              XmNrecomputeSize, false,
779                                              XmNshadowThickness, _at->shadow_thickness,
780                                              XmNalignment, XmALIGNMENT_CENTER,
781                                              XmNfontList, p_global->fontlist,
782                                              XmNbackground, _at->background_color,
783                                              mwidth, (int)width_of_button, // may terminate the list
784                                              mheight, (int)height_of_button, // may terminate the list
785                                              NULL );
786        }
787        AW_label_in_awar_list(this,button,buttonlabel);
788        root->make_sensitive(button, _at->widget_mask);
789    }
790    else { // button w/o callback (flat, not clickable)
791        long alignment = (org_correct_for_at_center == 1) ? XmALIGNMENT_CENTER : XmALIGNMENT_BEGINNING;
792
793        button = XtVaCreateManagedWidget( "label",
794                                          xmLabelWidgetClass,
795                                          parent_widget,
796                                          XmNrecomputeSize, false,
797                                          XmNx, (int)(x_button),
798                                          XmNy, (int)(y_button),
799                                          XmNalignment, alignment, // alignment of text inside button
800                                          // XmNalignment, XmALIGNMENT_BEGINNING, // alignment of text inside button
801                                          RES_LABEL_CONVERT(buttonlabel),
802                                          XmNfontList, p_global->fontlist,
803                                          XmNbackground, _at->background_color,
804                                          mwidth, (int)width_of_button, // may terminate the list
805                                          mheight, (int)height_of_button, // may terminate the list
806                                          NULL );
807
808        if (_at->attach_any) aw_attach_widget(button,_at);
809        AW_JUSTIFY_LABEL(button,_at->correct_for_at_center);
810        AW_label_in_awar_list(this,button,buttonlabel);
811    }
812
813    short height = 0;
814    short width  = 0;
815
816    if (_at->to_position_exists) {
817        // size has explicitly been specified in xfig -> calculate
818        height = _at->to_position_y - _at->y_for_next_button;
819        width  = _at->to_position_x - _at->x_for_next_button;
820    }
821
822    {
823        Widget  toRecenter   = 0;
824        int     recenterSize = 0;
825
826        if (!height || !width) {
827            // ask motif for real button size
828            Widget ButOrHigh = _at->highlight ? fatherwidget : button;
829            XtVaGetValues(ButOrHigh, XmNheight, &height, XmNwidth, &width, NULL);
830
831            if (let_motif_choose_size) {
832                if (_at->correct_for_at_center) {
833                    toRecenter   = ButOrHigh;
834                    recenterSize = width;
835                }
836                width = 0;          // ignore the used size (because it may use more than the window size)
837            }
838        }
839
840        if (toRecenter) {
841            int shiftback = 0;
842            switch (_at->correct_for_at_center) {
843                case 1: shiftback = recenterSize/2; break;
844                case 2: shiftback = recenterSize; break;
845            }
846            if (shiftback) {
847                XtVaSetValues(toRecenter, XmNx, x_button-shiftback, NULL);
848            }
849        }
850    }
851
852    _at->correct_for_at_center = org_correct_for_at_center; // restore original justification
853    _at->y_for_next_button     = org_y_for_next_button;
854
855    p_w->toggle_field = button;
856    this->_set_activate_callback((void *)button);
857    this->unset_at_commands();
858    this->increment_at_commands(width+SPACE_BEHIND_BUTTON, height);
859}
860
861void AW_window::dump_at_position(const char *tmp_label) const {
862    printf("%s at x = %i / y = %i\n", tmp_label, _at->x_for_next_button, _at->y_for_next_button);
863}
864
865void AW_window::update_label( int *widget, const char *var_value ) {
866    Widget w = (Widget) widget;
867
868    if ( get_root()->changer_of_variable != (long)widget ) {
869        XtVaSetValues( w, RES_CONVERT( XmNlabelString, var_value ), NULL );
870    }
871    else {
872        get_root()->changer_of_variable = 0;
873    }
874}
875
876/******************************************************************************************/
877/***********************    0/1 toggle          ***************************/
878/******************************************************************************************/
879
880struct aw_toggle_data {
881    bool  isTextToggle;
882    char *bitmapOrText[2];
883    int   buttonWidth; // wanted width in characters
884};
885
886void AW_window::update_toggle(int *wgt, const char *var, AW_CL cd_toggle_data)
887{
888    aw_toggle_data *tdata = (aw_toggle_data*)cd_toggle_data;
889    const char     *text  = tdata->bitmapOrText[(var[0] == '0' || var[0] == 'n') ? 0 : 1];
890   
891    if (tdata->isTextToggle) {
892        XtVaSetValues( (Widget)wgt, RES_CONVERT( XmNlabelString, text ), NULL );
893    }
894    else {
895        char *path = pixmapPath(text+1);;
896        XtVaSetValues( (Widget)wgt, RES_CONVERT( XmNlabelPixmap, path ), NULL );
897        free(path);
898    }
899}
900
901void AW_window::create_toggle(const char *var_name, aw_toggle_data *tdata) {
902    AW_cb_struct *cbs = _callback;
903    _callback         = (AW_cb_struct *)1;
904
905    {
906        int old_length_of_buttons = _at->length_of_buttons;
907
908        if (tdata->buttonWidth == 0) {
909            if (tdata->isTextToggle) {
910                int l1 = strlen(tdata->bitmapOrText[0]);
911                int l2 = strlen(tdata->bitmapOrText[1]);
912
913                _at->length_of_buttons = l1>l2 ? l1 : l2; // use longer text for button size
914            }
915            else {
916                _at->length_of_buttons = 0;
917            }
918        }
919        else {
920            _at->length_of_buttons = tdata->buttonWidth;
921        }
922       
923        create_button(0, tdata->bitmapOrText[0], 0);
924
925        _at->length_of_buttons = old_length_of_buttons;
926    }
927
928    AW_awar *vs = this->get_root()->awar(var_name);
929    {
930        char *var_value = vs->read_as_string();
931
932        this->update_toggle((int*)p_w->toggle_field, var_value, (AW_CL)tdata);
933        free(var_value);
934    }
935
936    AW_variable_update_struct *vus;
937    vus = new AW_variable_update_struct( p_w->toggle_field, AW_WIDGET_TOGGLE, vs, 0, 0, 0, cbs );
938
939    XtAddCallback(p_w->toggle_field, XmNactivateCallback,
940                  (XtCallbackProc) AW_variable_update_callback,
941                  (XtPointer) vus );
942
943    AW_INSERT_BUTTON_IN_AWAR_LIST( vs, (AW_CL)tdata, p_w->toggle_field, AW_WIDGET_TOGGLE, this);
944}
945
946
947void AW_window::create_toggle(const char *var_name,const char *no, const char *yes, int buttonWidth) {
948    aw_toggle_data *tdata  = new aw_toggle_data;
949    tdata->isTextToggle    = false;
950
951    aw_assert(no[0] == '#');
952    aw_assert(yes[0] == '#');
953
954    tdata->bitmapOrText[0] = strdup(no);
955    tdata->bitmapOrText[1] = strdup(yes);
956
957    tdata->buttonWidth = buttonWidth;
958
959    create_toggle(var_name, tdata);
960}
961
962void AW_window::create_text_toggle(const char *var_name, const char *noText, const char *yesText, int buttonWidth) {
963    aw_toggle_data *tdata  = new aw_toggle_data;
964    tdata->isTextToggle    = true;
965    tdata->bitmapOrText[0] = strdup(noText);
966    tdata->bitmapOrText[1] = strdup(yesText);
967    tdata->buttonWidth     = buttonWidth;
968
969    create_toggle(var_name, tdata);
970}
971
972
973void AW_window::create_toggle( const char *var_name ) {
974    create_toggle(var_name,"#no.bitmap","#yes.bitmap");
975}
976
977void AW_window::create_inverse_toggle( const char *var_name ) {
978    // like create_toggle, but displays inverse value
979    // (i.e. it's checked if value is zero, and unchecked otherwise)
980    create_toggle(var_name,"#yes.bitmap","#no.bitmap");
981}
982
983/************************************************************************************************/
984/************************************************************************************************/
985/************************************************************************************************/
986
987
988
989void AW_window::create_input_field( const char *var_name,  int columns ) {
990    Widget                     textField              = 0;
991    Widget                     tmp_label              = 0;
992    AW_cb_struct              *cbs;
993    AW_variable_update_struct *vus;
994    char                      *String;
995    int                        x_correcting_for_label = 0;
996
997    check_at_pos();
998    if (!columns) columns = _at->length_of_buttons;
999
1000    AW_awar *vs = root->awar(var_name);
1001    String      = root->awar( var_name )->read_as_string();
1002
1003    int width_of_input_label, height_of_input_label;
1004    calculate_label_size(this, &width_of_input_label, &height_of_input_label, true, 0);
1005    // @@@ FIXME: use height_of_input_label for propper Y-adjusting of label
1006    // width_of_input_label = this->calculate_string_width( calculate_label_length() );
1007
1008    int width_of_input = this->calculate_string_width(columns+1) + 9;
1009    // calculate width for 1 additional character (input field is not completely used)
1010    // + 4 pixel for shadow + 4 unknown missing pixels + 1 add. pixel needed for visible text area
1011
1012    Widget parentWidget = _at->attach_any ? INFO_FORM : INFO_WIDGET;
1013
1014    if ( _at->label_for_inputfield ) {
1015        tmp_label = XtVaCreateManagedWidget( "label",
1016                                         xmLabelWidgetClass,
1017                                         parentWidget, 
1018                                         XmNwidth, (int)(width_of_input_label + 2),
1019                                         XmNhighlightThickness, 0,
1020                                         RES_CONVERT( XmNlabelString, _at->label_for_inputfield ),
1021                                         XmNrecomputeSize, false,
1022                                         XmNalignment, XmALIGNMENT_BEGINNING,
1023                                         XmNfontList, p_global->fontlist,
1024                                         (_at->attach_any) ? NULL:XmNx,(int)_at->x_for_next_button,
1025                                         XmNy, (int)(_at->y_for_next_button)+ root->y_correction_for_input_labels -1,
1026                                         NULL );
1027        if (_at->attach_any) aw_attach_widget(tmp_label,_at);
1028        x_correcting_for_label = width_of_input_label + 10;
1029    }
1030
1031
1032    int width_of_last_widget = x_correcting_for_label + width_of_input + 2;
1033
1034    if ( _at->to_position_exists ) {
1035        width_of_input = _at->to_position_x - _at->x_for_next_button - x_correcting_for_label + 2;
1036        width_of_last_widget = _at->to_position_x - _at->x_for_next_button;
1037    }
1038   
1039    {
1040        TuneBackground(parentWidget, TUNE_INPUT);
1041        textField = XtVaCreateManagedWidget( "textField",
1042                                             xmTextFieldWidgetClass,
1043                                             parentWidget, 
1044                                             XmNwidth, (int)width_of_input,
1045                                             XmNrows, 1,
1046                                             XmNvalue, String,
1047                                             XmNfontList, p_global->fontlist,
1048                                              XmNbackground, _at->background_color,
1049                                             (_at->attach_any) ? NULL:XmNx, (int)(_at->x_for_next_button + x_correcting_for_label ),
1050                                             XmNy, (int)(_at->y_for_next_button + 5) - 8,
1051                                             NULL );
1052        if (_at->attach_any) aw_attach_widget(textField,_at);
1053    }
1054   
1055    free(String);
1056
1057    // user-own callback
1058    cbs = _callback;
1059
1060    // callback for enter
1061    vus = new AW_variable_update_struct( textField, AW_WIDGET_INPUT_FIELD, vs, 0, 0, 0, cbs );
1062
1063    XtAddCallback(textField, XmNactivateCallback,
1064                  (XtCallbackProc) AW_variable_update_callback,
1065                  (XtPointer) vus );
1066    if (_d_callback) {
1067        XtAddCallback(textField, XmNactivateCallback,
1068                      (XtCallbackProc) AW_server_callback,
1069                      (XtPointer) _d_callback );
1070        _d_callback->id = GBS_global_string_copy("INPUT:%s",var_name);
1071        get_root()->define_remote_command(_d_callback);
1072    }
1073
1074    // callback for losing focus
1075    XtAddCallback(textField, XmNlosingFocusCallback,
1076                  (XtCallbackProc) AW_variable_update_callback,
1077                  (XtPointer) vus );
1078    // callback for value changed
1079    XtAddCallback(textField, XmNvalueChangedCallback,
1080                  (XtCallbackProc) AW_value_changed_callback,
1081                  (XtPointer) root );
1082
1083    AW_INSERT_BUTTON_IN_AWAR_LIST( vs,0, textField, AW_WIDGET_INPUT_FIELD, this);
1084    root->make_sensitive(textField, _at->widget_mask);
1085
1086    short height;
1087    XtVaGetValues( textField, XmNheight, &height, NULL);
1088    int height_of_last_widget = height;
1089
1090    if ( _at->correct_for_at_center == 1 ) { // middle centered
1091        XtVaSetValues( textField, XmNx, ((int)(_at->x_for_next_button + x_correcting_for_label) - (int)(width_of_last_widget/2) + 1 ), NULL );
1092        if ( tmp_label ) {
1093            XtVaSetValues( tmp_label, XmNx, ((int)(_at->x_for_next_button) - (int)(width_of_last_widget/2) + 1 ), NULL );
1094        }
1095        width_of_last_widget = width_of_last_widget / 2;
1096    }
1097    if ( _at->correct_for_at_center == 2 ) { // right centered
1098        XtVaSetValues( textField, XmNx, (int)(_at->x_for_next_button + x_correcting_for_label - width_of_last_widget + 3 ), NULL );
1099        if ( tmp_label ) {
1100            XtVaSetValues( tmp_label, XmNx, (int)(_at->x_for_next_button - width_of_last_widget + 3 ), NULL );
1101        }
1102        width_of_last_widget = 0;
1103    }
1104    width_of_last_widget -= 2;
1105
1106    this->unset_at_commands();
1107    this->increment_at_commands( width_of_last_widget, height_of_last_widget );
1108
1109}
1110
1111
1112void AW_window::update_input_field(int *widget, const char *var_value ) {
1113    Widget w = (Widget) widget;
1114
1115    XtVaSetValues( w, XmNvalue, var_value, NULL );
1116}
1117
1118
1119
1120
1121void AW_window::create_text_field( const char *var_name, int columns, int rows ) {
1122    Widget scrolledWindowText;
1123    Widget scrolledText;
1124    Widget tmp_label =0;
1125    AW_cb_struct *cbs;
1126    AW_variable_update_struct *vus;
1127    char *String = NULL;
1128    short width_of_last_widget = 0;
1129    short height_of_last_widget = 0;
1130    int width_of_text = 0;
1131    int height_of_text = 0;
1132    int x_correcting_for_label = 0;
1133
1134    AW_awar *vs = root->awar(var_name);
1135    String      = root->awar( var_name )->read_string();
1136
1137    int width_of_text_label, height_of_text_label;
1138    calculate_label_size(this, &width_of_text_label, &height_of_text_label, true, 0);
1139    // @@@ FIXME: use height_of_text_label for propper Y-adjusting of label
1140
1141    // width_of_text_label = this->calculate_string_width( calculate_label_length() );
1142    width_of_text = this->calculate_string_width( columns ) + 18;
1143    height_of_text = this->calculate_string_height( rows, rows*4 ) + 9;
1144
1145
1146    if ( _at->label_for_inputfield ) {
1147        tmp_label = XtVaCreateManagedWidget( "label",
1148                                         xmLabelWidgetClass,
1149                                         INFO_WIDGET,
1150                                         XmNx, (int)_at->x_for_next_button,
1151                                         XmNy, (int)(_at->y_for_next_button) + this->get_root()->y_correction_for_input_labels + 5 - 6,
1152                                         XmNwidth, (int)(width_of_text_label + 2),
1153                                         RES_CONVERT( XmNlabelString, _at->label_for_inputfield ),
1154                                         XmNrecomputeSize, false,
1155                                         XmNalignment, XmALIGNMENT_BEGINNING,
1156                                         XmNfontList, p_global->fontlist,
1157                                         NULL );
1158
1159        x_correcting_for_label = width_of_text_label + 10;
1160
1161    }
1162
1163
1164    if (_at->to_position_exists){
1165        scrolledWindowText = XtVaCreateManagedWidget( "scrolledWindowList1",
1166                                                      xmScrolledWindowWidgetClass,
1167                                                      INFO_FORM,
1168                                                      XmNscrollingPolicy, XmAPPLICATION_DEFINED,
1169                                                      XmNvisualPolicy, XmVARIABLE,
1170                                                      XmNscrollBarDisplayPolicy, XmSTATIC,
1171                                                      XmNfontList,          p_global->fontlist,
1172                                                      NULL );
1173        aw_attach_widget(scrolledWindowText,_at);
1174
1175        width_of_text = _at->to_position_x - _at->x_for_next_button - x_correcting_for_label - 18;
1176        if ( _at->y_for_next_button < _at->to_position_y - 18 ) {
1177            height_of_text = _at->to_position_y - _at->y_for_next_button - 18;
1178        }
1179    }else{
1180        scrolledWindowText = XtVaCreateManagedWidget( "scrolledWindowText",
1181                                                      xmScrolledWindowWidgetClass,
1182                                                      INFO_WIDGET,
1183                                                      XmNscrollingPolicy, XmAPPLICATION_DEFINED,
1184                                                      XmNvisualPolicy, XmVARIABLE,
1185                                                      XmNscrollBarDisplayPolicy, XmSTATIC,
1186                                                      XmNx, (int)10,
1187                                                      XmNy, (int)_at->y_for_next_button,
1188                                                      XmNfontList, p_global->fontlist,
1189                                                      NULL );
1190    }
1191
1192    TuneBackground(scrolledWindowText, TUNE_INPUT);
1193    scrolledText = XtVaCreateManagedWidget( "scrolledText1",
1194                                            xmTextWidgetClass,
1195                                            scrolledWindowText,
1196                                            XmNeditMode, XmMULTI_LINE_EDIT ,
1197                                            XmNvalue, String,
1198                                            XmNscrollLeftSide, false,
1199                                            XmNwidth, (int)width_of_text,
1200                                            XmNheight, (int)height_of_text,
1201                                            XmNfontList, p_global->fontlist,
1202                                            XmNbackground, _at->background_color,
1203                                            NULL );
1204    free(String);
1205
1206    if (!_at->to_position_exists){
1207        XtVaGetValues( scrolledWindowText,  XmNheight, &height_of_last_widget,
1208                       XmNwidth, &width_of_last_widget, NULL);
1209
1210        width_of_last_widget += (short)x_correcting_for_label;
1211
1212        switch(_at->correct_for_at_center){
1213            case 0: // left centered
1214                XtVaSetValues( scrolledWindowText, XmNx, (int)(_at->x_for_next_button + x_correcting_for_label), NULL);
1215                break;
1216
1217            case 1: // middle centered
1218                XtVaSetValues( scrolledWindowText, XmNx, (int)( _at->x_for_next_button + x_correcting_for_label - (width_of_last_widget/2) ), NULL);
1219                if ( _at->label_for_inputfield ) {
1220                    XtVaSetValues( tmp_label, XmNx, (int)( _at->x_for_next_button - (width_of_last_widget/2) ), NULL );
1221                }
1222                width_of_last_widget = width_of_last_widget / 2;
1223                break;
1224
1225            case 2: // right centered
1226                XtVaSetValues( scrolledWindowText, XmNx, (int)( _at->x_for_next_button + x_correcting_for_label - width_of_last_widget ) , NULL);
1227                if ( _at->label_for_inputfield ) {
1228                    XtVaSetValues( tmp_label, XmNx, (int)( _at->x_for_next_button - width_of_last_widget ), NULL );
1229                }
1230                width_of_last_widget = 0;
1231                break;
1232        }
1233    }
1234
1235    // user-own callback
1236    cbs = _callback;
1237
1238    // callback for enter
1239    vus = new AW_variable_update_struct( scrolledText, AW_WIDGET_TEXT_FIELD, vs, 0, 0, 0, cbs );
1240    XtAddCallback(scrolledText, XmNactivateCallback, (XtCallbackProc) AW_variable_update_callback, (XtPointer) vus );
1241    // callback for losing focus
1242    XtAddCallback(scrolledText, XmNlosingFocusCallback, (XtCallbackProc) AW_variable_update_callback, (XtPointer) vus );
1243    // callback for value changed
1244    XtAddCallback(scrolledText, XmNvalueChangedCallback, (XtCallbackProc) AW_value_changed_callback, (XtPointer) root );
1245
1246    AW_INSERT_BUTTON_IN_AWAR_LIST( vs,0, scrolledText, AW_WIDGET_TEXT_FIELD, this);
1247    root->make_sensitive(scrolledText, _at->widget_mask);
1248
1249    this->unset_at_commands();
1250    this->increment_at_commands( width_of_last_widget, height_of_last_widget );
1251}
1252
1253
1254void AW_window::update_text_field( int *widget, const char *var_value ) {
1255    Widget w = (Widget ) widget;
1256
1257    XtVaSetValues( w, XmNvalue, var_value, NULL );
1258}
1259
1260
1261/****************************************************************************************************************************/
1262/****************************************************************************************************************************/
1263/****************************************************************************************************************************/
1264
1265
1266AW_selection_list* AW_window::create_selection_list( const char *var_name, const char *tmp_label, const char *mnemonic, int columns, int rows  ) {
1267    AWUSE(mnemonic);
1268    Widget                     scrolledWindowList;
1269    Widget                     scrolledList;
1270    Widget                     l                     = 0;
1271    AW_variable_update_struct *vus;
1272    AW_cb_struct              *cbs;
1273    int                        width_of_label        = 0, height_of_label = 0;
1274    int                        width_of_list;
1275    int                        height_of_list;
1276    int                        width_of_last_widget  = 0;
1277    int                        height_of_last_widget = 0;
1278
1279    if ( _at->label_for_inputfield ) {
1280        tmp_label = _at->label_for_inputfield;
1281    }
1282
1283    check_at_pos();
1284
1285    AW_awar *vs = 0;
1286    if (var_name) vs = root->awar(var_name);
1287
1288    if ( tmp_label ) {
1289        calculate_label_size(this, &width_of_label, &height_of_label, true, tmp_label);
1290        // @@@ FIXME: use height_of_label for propper Y-adjusting of label
1291        // width_of_label = this->calculate_string_width( calculate_label_length() );
1292
1293        l = XtVaCreateManagedWidget( "label",
1294                                     xmLabelWidgetClass,
1295                                     INFO_WIDGET,
1296                                     XmNx, (int)10,
1297                                     XmNy, (int)(_at->y_for_next_button) + this->get_root()->y_correction_for_input_labels - 1,
1298                                     XmNwidth, (int)(width_of_label + 2),
1299                                     RES_CONVERT( XmNlabelString, tmp_label ),
1300                                     XmNrecomputeSize, false,
1301                                     XmNalignment, XmALIGNMENT_BEGINNING,
1302                                     NULL );
1303        width_of_label += 10;
1304    }
1305
1306
1307    width_of_list = this->calculate_string_width( columns ) + 9;
1308    height_of_list = this->calculate_string_height( rows, 4*rows ) + 9;
1309
1310
1311    if (_at->to_position_exists){
1312        width_of_list = _at->to_position_x - _at->x_for_next_button - width_of_label - 18;
1313        if ( _at->y_for_next_button  < _at->to_position_y - 18 ) {
1314            height_of_list = _at->to_position_y - _at->y_for_next_button - 18;
1315        }
1316        scrolledWindowList = XtVaCreateManagedWidget( "scrolledWindowList1",
1317                                                      xmScrolledWindowWidgetClass,
1318                                                      INFO_FORM,
1319                                                      XmNvisualPolicy, XmVARIABLE,
1320                                                      XmNscrollBarDisplayPolicy, XmSTATIC,
1321                                                      XmNshadowThickness, 0,
1322                                                      XmNfontList,          p_global->fontlist,
1323                                                      NULL );
1324        aw_attach_widget(scrolledWindowList,_at);
1325
1326        width_of_last_widget = _at->to_position_x - _at->x_for_next_button;
1327        height_of_last_widget = _at->to_position_y - _at->y_for_next_button;
1328    }else{
1329        scrolledWindowList = XtVaCreateManagedWidget( "scrolledWindowList1",
1330                                                      xmScrolledWindowWidgetClass,
1331                                                      INFO_WIDGET,
1332                                                      XmNscrollingPolicy, XmAPPLICATION_DEFINED,
1333                                                      XmNvisualPolicy, XmVARIABLE,
1334                                                      XmNscrollBarDisplayPolicy, XmSTATIC,
1335                                                      XmNshadowThickness, 0,
1336                                                      XmNx, (int)10,
1337                                                      XmNy, (int)(_at->y_for_next_button),
1338                                                      XmNfontList, p_global->fontlist,
1339                                                      NULL );
1340    }
1341
1342    {
1343        int select_type = XmMULTIPLE_SELECT;
1344        if (vs) select_type = XmSINGLE_SELECT;
1345
1346        TuneBackground(scrolledWindowList, TUNE_INPUT);
1347        scrolledList = XtVaCreateManagedWidget( "scrolledList1",
1348                                                xmListWidgetClass,
1349                                                scrolledWindowList,
1350                                                XmNwidth, (int)width_of_list,
1351                                                XmNheight, (int) height_of_list,
1352                                                XmNscrollBarDisplayPolicy, XmSTATIC,
1353                                                XmNselectionPolicy, select_type,
1354                                                XmNlistSizePolicy, XmCONSTANT,
1355                                                XmNfontList, p_global->fontlist,
1356                                                XmNbackground, _at->background_color, 
1357                                                NULL );
1358    }
1359
1360    if (!_at->to_position_exists){
1361        short height;
1362        XtVaGetValues( scrolledList, XmNheight, &height, NULL);
1363        height_of_last_widget = height + 20;
1364        width_of_last_widget = width_of_label + width_of_list + 20;
1365
1366        switch(_at->correct_for_at_center){
1367            case 3: break;
1368            case 0: // left centered
1369                XtVaSetValues(  scrolledWindowList, XmNx, (int)(_at->x_for_next_button + width_of_label), NULL );
1370                if ( tmp_label ) {
1371                    XtVaSetValues(  l, XmNx, (int)(_at->x_for_next_button), NULL );
1372                }
1373                break;
1374
1375            case 1: // middle centered
1376                XtVaSetValues( scrolledWindowList, XmNx, (int)( _at->x_for_next_button - (width_of_last_widget/2) + width_of_label), NULL );
1377                if ( tmp_label ) {
1378                    XtVaSetValues( l, XmNx, (int)(_at->x_for_next_button - (width_of_last_widget/2) ), NULL );
1379                }
1380                width_of_last_widget = width_of_last_widget / 2;
1381                break;
1382
1383            case 2: // right centered
1384                XtVaSetValues( scrolledWindowList, XmNx, (int)(_at->x_for_next_button - width_of_list - 18), NULL );
1385                if ( tmp_label ) {
1386                    XtVaSetValues( l, XmNx, (int)(_at->x_for_next_button - width_of_last_widget - 18), NULL );
1387                }
1388                width_of_last_widget = 0;
1389        }
1390
1391    }
1392
1393    {
1394        int type = GB_STRING;
1395        if (vs)  type = vs->variable_type;
1396
1397        if ( p_global->selection_list ) {
1398            p_global->last_selection_list->next = new AW_selection_list( var_name, type, scrolledList );
1399            p_global->last_selection_list = p_global->last_selection_list->next;
1400        }else {
1401            p_global->last_selection_list = p_global->selection_list = new AW_selection_list( var_name, type, scrolledList );
1402        }
1403    }
1404
1405
1406    // user-own callback
1407    cbs = _callback;
1408
1409    // callback for enter
1410    if (vs){
1411        vus = new AW_variable_update_struct( scrolledList, AW_WIDGET_SELECTION_LIST, vs, 0, 0, 0, cbs );
1412        vus->id = (void*)p_global->last_selection_list;
1413
1414        XtAddCallback(scrolledList, XmNsingleSelectionCallback,
1415                      (XtCallbackProc) AW_variable_update_callback,
1416                      (XtPointer) vus );
1417
1418        if ( _d_callback) {
1419            XtAddCallback(scrolledList, XmNdefaultActionCallback,
1420                          (XtCallbackProc) AW_server_callback,
1421                          (XtPointer) _d_callback );
1422        }
1423        AW_INSERT_BUTTON_IN_AWAR_LIST( vs,(AW_CL)p_global->last_selection_list, scrolledList, AW_WIDGET_SELECTION_LIST, this);
1424        root->make_sensitive(scrolledList, _at->widget_mask);
1425    }
1426
1427    this->unset_at_commands();
1428    this->increment_at_commands( width_of_last_widget, height_of_last_widget );
1429    return p_global->last_selection_list;
1430}
1431
1432AW_selection_list *AW_window::create_multi_selection_list(const char *tmp_label, const char *mnemonic, int columns, int rows){
1433    return create_selection_list(0,tmp_label,mnemonic,columns,rows);
1434}
1435
1436void AW_window::conc_list(AW_selection_list *from_list,AW_selection_list *to_list)
1437{
1438    AW_select_table_struct *from_list_table;
1439
1440    from_list_table = from_list->list_table;
1441    while (from_list_table)
1442    {
1443        if (from_list->default_select != from_list_table)
1444        {
1445            if (! to_list->list_table)
1446                to_list->last_of_list_table = to_list->list_table = new AW_select_table_struct( from_list_table->displayed, from_list_table->char_value );
1447            else
1448            {
1449                to_list->last_of_list_table->next = new AW_select_table_struct( from_list_table->displayed, from_list_table->char_value );
1450                to_list->last_of_list_table = to_list->last_of_list_table->next;
1451                to_list->last_of_list_table->next = NULL;
1452            }
1453        }
1454
1455        from_list_table = from_list_table->next;
1456    }
1457
1458    clear_selection_list( from_list );
1459    insert_default_selection( from_list, "", "");
1460}
1461
1462// --------------------------------------------------
1463// iterator through selection list:
1464// --------------------------------------------------
1465
1466static AW_select_table_struct *current_list_table = 0;
1467
1468void AW_window::init_list_entry_iterator(AW_selection_list *selection_list) {
1469    current_list_table = selection_list->list_table;
1470}
1471
1472void AW_window::iterate_list_entry(int offset) {
1473    while (offset--) {
1474        if (!current_list_table) break;
1475        current_list_table = current_list_table->next;
1476    }
1477}
1478
1479const char *AW_window::get_list_entry_char_value() {
1480    return current_list_table ? current_list_table->char_value : 0;
1481}
1482
1483const char *AW_window::get_list_entry_displayed() {
1484    return current_list_table ? current_list_table->displayed : 0;
1485}
1486
1487void AW_window::set_list_entry_char_value(const char *new_char_value) {
1488    if (!current_list_table) AW_ERROR("No Selection List Iterator");
1489    freeset(current_list_table->char_value, AW_select_table_struct::copy_string(new_char_value));
1490}
1491
1492void AW_window::set_list_entry_displayed(const char *new_displayed) {
1493    if (!current_list_table) AW_ERROR("No Selection List Iterator");
1494    freeset(current_list_table->displayed, AW_select_table_struct::copy_string(new_displayed));
1495}
1496
1497/*
1498const char *AW_window::get_list_entry(AW_selection_list *selection_list, int val)   //val = 1 initialisiert das Ganze, val=0 holt naechsten Eintrag
1499{
1500    static int              last        = 0;
1501    char                *result;
1502
1503    if (last == 1 && !val)
1504    {
1505    last = 2;
1506    if (!list_table)
1507        return NULL;
1508    else
1509        return list_table->char_value;;
1510    }
1511
1512    if (last == 2 && !val)
1513    return NULL;
1514
1515    if (val)
1516    {
1517    last = 0;
1518    list_table = NULL;
1519    return NULL;
1520    }
1521
1522    if (!list_table)
1523    list_table = selection_list->list_table;
1524
1525    if (!list_table)
1526    {
1527    last = 2;
1528    return NULL;
1529    }
1530
1531    result = list_table->char_value;
1532    list_table = list_table->next;
1533    if (!list_table || list_table == selection_list->last_of_list_table)
1534    last = 1;
1535    return result;
1536    }
1537*/
1538
1539void AW_window::set_selection_list_suffix(AW_selection_list *selection_list, const char *suffix){
1540    char filter[200];
1541    sprintf(filter,"tmp/save_box_sel_%li/filter",(long)selection_list);
1542    get_root()->awar_string(filter,suffix);
1543    sprintf(filter,"tmp/load_box_sel_%li/filter",(long)selection_list);
1544    get_root()->awar_string(filter,suffix);}
1545
1546int AW_window::get_no_of_entries( AW_selection_list *selection_list )
1547{
1548    AW_select_table_struct *list_table;
1549    int     count = 0;
1550    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) count++;
1551    if( selection_list->default_select )    count++;
1552
1553    return count;
1554}
1555
1556int AW_window::get_index_of_current_element(AW_selection_list *selection_list, const char *awar_name) {
1557    // returns -1 if no entry is selected
1558    AW_root *aw_root    = get_root();
1559    char    *curr_value = aw_root->awar(awar_name)->read_string();
1560    int      index      = get_index_of_element(selection_list, curr_value);
1561
1562#if defined(DEBUG) && 0
1563    printf("get_index_of_current_element: curr_value='%s' index=%i\n", curr_value, index);
1564#endif // DEBUG
1565
1566    free(curr_value);
1567    return index;
1568}
1569
1570void AW_window::select_index(AW_selection_list *selection_list, const char *awar_name, int wanted_index) {
1571    AW_root *aw_root      = get_root();
1572    char    *wanted_value = get_element_of_index(selection_list, wanted_index);
1573
1574#if defined(DEBUG) && 0
1575    printf("select_index : wanted_index=%i wanted_value='%s'\n", wanted_index, wanted_value);
1576#endif // DEBUG
1577
1578    if (wanted_value) {
1579        aw_root->awar(awar_name)->write_string(wanted_value);
1580        free(wanted_value);
1581    }
1582    else {
1583        aw_root->awar(awar_name)->write_string("");
1584    }
1585}
1586
1587void AW_window::move_selection(AW_selection_list *selection_list, const char *awar_name, int offset) {
1588    int index = get_index_of_current_element(selection_list, awar_name);
1589    select_index(selection_list, awar_name, index+offset);
1590
1591    //     int curr_idx;
1592    //     {
1593    //         char *curr_value = list_awar->read_string();
1594
1595    //         curr_idx = get_index_of_element(selection_list, curr_value);
1596    //         free(curr_value);
1597    //     }
1598
1599    //     if (curr_idx == -1) {
1600    //         curr_idx = 0;
1601    //     }
1602    //     else {
1603    //         curr_idx += offset;
1604    //     }
1605
1606    //     const char *new_value = get_element_of_index(selection_list, curr_idx);
1607    //     if (new_value) {
1608    //         list_awar->write_string(new_value);
1609    //     }
1610    //     return 0;
1611}
1612
1613/*-------------------- function to get index of an entry in the selection lists -------------------- */
1614int AW_window::get_index_of_element(AW_selection_list *selection_list, const char *searched_value){
1615
1616    int         element_index = 0;
1617    int         found_index   = -1;
1618    const char *listEntry     = selection_list->first_element();
1619
1620    while (listEntry) {
1621        if (strcmp(listEntry, searched_value) == 0) {
1622            found_index = element_index;
1623            break;              // found
1624        }
1625        ++element_index;
1626        listEntry = selection_list->next_element();
1627    }
1628
1629    return element_index;
1630}
1631
1632/*-------------------- function to get value of entry in the selection list for the index passed  -------------------- */
1633char *AW_window::get_element_of_index(AW_selection_list *selection_list, int index) {
1634    char *element = 0;
1635
1636    if (index >= 0) {
1637        int         element_index = 0;
1638        const char *listEntry     = selection_list->first_element();
1639
1640        while (listEntry) {
1641            if (element_index == index) {
1642                element = strdup(listEntry);
1643                break;
1644            }
1645            ++element_index;
1646            listEntry = selection_list->next_element();
1647        }
1648    }
1649
1650    return element;
1651}
1652
1653void AW_window::delete_selection_from_list( AW_selection_list *selection_list, const char *disp_string )
1654{
1655    AW_select_table_struct *list_table,
1656        *next = NULL,
1657        *prev = NULL;
1658    char    *ptr;
1659    int     count = 0;
1660
1661    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) count++;
1662    if( selection_list->default_select )    count++;
1663
1664    if (count == 2) {   //Letzter Eintrag + default selection
1665        clear_selection_list( selection_list );
1666    }
1667
1668    for ( list_table = selection_list->list_table, next = selection_list->list_table;
1669          list_table;
1670          prev = next, list_table = list_table->next, next = list_table)
1671    {
1672        ptr = list_table->displayed;
1673        if ( strcmp( disp_string, ptr ) == 0 ) {
1674            next = list_table->next;
1675
1676            if (prev) prev->next = next;
1677            else selection_list->list_table = next;
1678
1679            if (!list_table->next && prev) selection_list->last_of_list_table = prev;
1680
1681            if ( selection_list->default_select == list_table ) {
1682                selection_list->default_select = NULL;
1683                insert_default_selection( selection_list, "", "");
1684            }
1685
1686            delete list_table;
1687            return;
1688        }
1689    }
1690}
1691
1692static void type_mismatch(const char *triedType, const char *intoWhat) {
1693    AW_ERROR("Cannot insert %s into %s which uses a non-%s AWAR", triedType, intoWhat, triedType);
1694}
1695
1696inline void selection_type_mismatch(const char *triedType) { type_mismatch(triedType, "selection-list"); }
1697inline void option_type_mismatch(const char *triedType) { type_mismatch(triedType, "option-menu"); }
1698inline void toggle_type_mismatch(const char *triedType) { type_mismatch(triedType, "toggle"); }
1699
1700void AW_window::insert_selection(AW_selection_list *selection_list, const char *displayed, const char *value) {
1701    if (selection_list->variable_type != AW_STRING) {
1702        selection_type_mismatch("string");
1703        return;
1704    }
1705
1706    if (selection_list->list_table) {
1707        selection_list->last_of_list_table->next = new AW_select_table_struct(displayed, value);
1708        selection_list->last_of_list_table = selection_list->last_of_list_table->next;
1709        selection_list->last_of_list_table->next = NULL;
1710    }else {
1711        selection_list->last_of_list_table = selection_list->list_table = new AW_select_table_struct(displayed, value);
1712    }
1713}
1714
1715
1716void AW_window::insert_default_selection(AW_selection_list *selection_list, const char *displayed, const char *value) {
1717    if (selection_list->variable_type != AW_STRING) {
1718        selection_type_mismatch("string");
1719        return;
1720    }
1721    if (selection_list->default_select) {
1722        delete selection_list->default_select;
1723    }
1724    selection_list->default_select = new AW_select_table_struct(displayed, value);
1725}
1726
1727#if defined(DEVEL_RALF)
1728#warning parameter value must be int32_t
1729#endif // DEVEL_RALF
1730void AW_window::insert_selection(AW_selection_list *selection_list, const char *displayed, long value) {
1731
1732    if (selection_list->variable_type != AW_INT) {
1733        selection_type_mismatch("int");
1734        return;
1735    }
1736    if (selection_list->list_table) {
1737        selection_list->last_of_list_table->next = new AW_select_table_struct(displayed, value);
1738        selection_list->last_of_list_table = selection_list->last_of_list_table->next;
1739        selection_list->last_of_list_table->next = NULL;
1740    }else {
1741        selection_list->last_of_list_table = selection_list->list_table = new AW_select_table_struct(displayed, value);
1742    }
1743}
1744
1745#if defined(DEVEL_RALF)
1746#warning parameter value must be int32_t
1747#endif // DEVEL_RALF
1748void AW_window::insert_default_selection(AW_selection_list *selection_list, const char *displayed, long value) {
1749    if (selection_list->variable_type != AW_INT) {
1750        selection_type_mismatch("int");
1751        return;
1752    }
1753    if (selection_list->default_select) {
1754        delete selection_list->default_select;
1755    }
1756    selection_list->default_select = new AW_select_table_struct(displayed, value);
1757}
1758
1759void AW_window::insert_selection(AW_selection_list * selection_list, const char *displayed, void *pointer) {
1760    if (selection_list->variable_type != AW_POINTER) {
1761        selection_type_mismatch("pointer");
1762        return;
1763    }
1764    if (selection_list->list_table) {
1765        selection_list->last_of_list_table->next = new AW_select_table_struct(displayed, pointer);
1766        selection_list->last_of_list_table = selection_list->last_of_list_table->next;
1767        selection_list->last_of_list_table->next = NULL;
1768    }else {
1769        selection_list->last_of_list_table = selection_list->list_table = new AW_select_table_struct(displayed, pointer);
1770    }
1771}
1772
1773void AW_window::insert_default_selection(AW_selection_list * selection_list, const char *displayed, void *pointer) {
1774    if (selection_list->variable_type != AW_POINTER) {
1775        selection_type_mismatch("pointer");
1776        return;
1777    }
1778    if (selection_list->default_select) {
1779        delete selection_list->default_select;
1780    }
1781    selection_list->default_select = new AW_select_table_struct(displayed, pointer);
1782}
1783
1784void AW_window::clear_selection_list(AW_selection_list *selection_list) {
1785    AW_select_table_struct *list_table;
1786    AW_select_table_struct *help;
1787
1788
1789    for (help = selection_list->list_table; help; ) {
1790        list_table = help;
1791        help = list_table->next;
1792        delete list_table;
1793    }
1794    if (selection_list->default_select) {
1795        delete selection_list->default_select;
1796    }
1797
1798    selection_list->list_table         = NULL;
1799    selection_list->last_of_list_table = NULL;
1800    selection_list->default_select     = NULL;
1801
1802
1803}
1804
1805inline XmString XmStringCreateSimple_wrapper(const char *text) {
1806    return XmStringCreateSimple((char*)text);
1807}
1808
1809void AW_window::update_selection_list( AW_selection_list * selection_list ) {
1810
1811    AW_select_table_struct *list_table;
1812    int count = 0;
1813
1814
1815    count = 0;
1816    int i;
1817    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) count++;
1818    if( selection_list->default_select )    count++;
1819
1820    XmString *strtab = new XmString[count];
1821
1822    count = 0;
1823    const char *s2;
1824    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ){
1825        s2 = list_table->displayed;
1826        if (!strlen(s2)) s2 = "  ";
1827        strtab[count] = XmStringCreateSimple_wrapper(s2);
1828        count++;
1829    }
1830    if( selection_list->default_select ) {
1831        s2 = selection_list->default_select->displayed;
1832        if (!strlen(s2)) s2 = "  ";
1833        strtab[count] = XmStringCreateSimple_wrapper(s2);
1834        count++;
1835    }
1836    if (!count){
1837        strtab[count] = XmStringCreateSimple_wrapper("   ");
1838        count ++;
1839    }
1840
1841    XtVaSetValues(  selection_list->select_list_widget, XmNitemCount, count, XmNitems, strtab , NULL );
1842
1843    update_selection_list_intern( selection_list );
1844
1845    for (i=0; i<count; i++) XmStringFree(strtab[i]);
1846    delete [] strtab;
1847
1848}
1849
1850
1851void AW_window::update_selection_list_intern( AW_selection_list *selection_list ) {
1852    AW_select_table_struct *list_table;
1853
1854    int pos = 0;
1855
1856    if (!selection_list->variable_name) return; // not connected to awar
1857    bool found = false;
1858    pos = 0;
1859    switch ( selection_list->variable_type ) {
1860        case AW_STRING: {
1861            char *var_value = root->awar( selection_list->variable_name )->read_string();
1862            for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) {
1863                if ( strcmp( var_value, list_table->char_value ) == 0 ) {
1864                    found = true;
1865                    break;
1866                }
1867                pos++;
1868            }
1869            free(var_value);
1870            break;
1871        }
1872        case AW_INT: {
1873            int var_value = root->awar( selection_list->variable_name )->read_int();
1874            for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) {
1875                if ( var_value == list_table->int_value ) {
1876                    found = true;
1877                    break;
1878                }
1879                pos++;
1880            }
1881            break;
1882        }
1883        case AW_FLOAT: {
1884            float var_value = root->awar( selection_list->variable_name )->read_float();
1885            for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) {
1886                if ( var_value == list_table->float_value ) {
1887                    found = true;
1888                    break;
1889                }
1890                pos++;
1891            }
1892            break;
1893        }
1894        case AW_POINTER: {
1895            void *var_value = root->awar( selection_list->variable_name )->read_pointer();
1896            for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) {
1897                if ( var_value == list_table->pointer_value ) {
1898                    found = true;
1899                    break;
1900                }
1901                pos++;
1902            }
1903            break;
1904        }
1905        default:
1906            gb_assert(0);
1907            GB_warning("Unknown AWAR type");
1908            break;
1909    }
1910
1911    if (found || selection_list->default_select) {
1912        pos++;
1913        int top;
1914        int vis;
1915        XtVaGetValues(selection_list->select_list_widget,
1916                      XmNvisibleItemCount, &vis,
1917                      XmNtopItemPosition, &top,
1918                      NULL);
1919        XmListSelectPos(selection_list->select_list_widget,pos,False);
1920
1921        if (pos < top) {
1922            if (pos > 1) pos --;
1923            XmListSetPos(selection_list->select_list_widget,pos);
1924        }
1925        if (pos >= top + vis) {
1926            XmListSetBottomPos(selection_list->select_list_widget,pos + 1 );
1927        }
1928
1929    }
1930    else {
1931        AW_ERROR("Selection list '%s' has no default selection", selection_list->variable_name);
1932    }
1933}
1934
1935void AW_selection_list::selectAll(){
1936    int i;
1937    AW_select_table_struct *lt;
1938    for (i=0,lt = list_table; lt; i++,lt = lt->next){
1939        XmListSelectPos(select_list_widget,i,False);
1940    }
1941    if (default_select){
1942        XmListSelectPos(select_list_widget,i,False);
1943    }
1944}
1945
1946void AW_selection_list::deselectAll(){
1947    XmListDeselectAllItems(select_list_widget);
1948}
1949
1950const char *AW_selection_list::first_element(){
1951    AW_select_table_struct *lt;
1952    for (lt = list_table; lt; lt = lt->next){
1953        lt->is_selected = 1;
1954    }
1955    loop_pntr = list_table;
1956    if (!loop_pntr) return 0;
1957    return loop_pntr->char_value;
1958}
1959
1960const char *AW_selection_list::next_element(){
1961    if (!loop_pntr) return 0;
1962    loop_pntr = loop_pntr->next;
1963    if (!loop_pntr) return 0;
1964    while (loop_pntr && !loop_pntr->is_selected) loop_pntr=loop_pntr->next;
1965    if (!loop_pntr) return 0;
1966    return loop_pntr->char_value;
1967}
1968
1969const char *AW_selection_list::first_selected(){
1970    int i;
1971    AW_select_table_struct *lt;
1972    loop_pntr = 0;
1973    for (i=1,lt = list_table; lt; i++,lt = lt->next){
1974        lt->is_selected = XmListPosSelected(select_list_widget,i);
1975        if (lt->is_selected && !loop_pntr) loop_pntr = lt;
1976    }
1977    if (default_select){
1978        default_select->is_selected = XmListPosSelected(select_list_widget,i);
1979        if (default_select->is_selected && !loop_pntr) loop_pntr = lt;
1980    }
1981    if (!loop_pntr) return 0;
1982    return loop_pntr->char_value;
1983}
1984
1985char *AW_window::get_selection_list_contents( AW_selection_list * selection_list, long number_of_lines) {
1986    // number_of_lines == 0     -> print all
1987
1988    AW_select_table_struct *list_table;
1989    GBS_strstruct          *fd = GBS_stropen(10000);
1990
1991    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next ) {
1992        number_of_lines--;
1993        GBS_strcat(fd,list_table->displayed);
1994        GBS_chrcat(fd,'\n');
1995        if (!number_of_lines) break;
1996    }
1997    return GBS_strclose(fd);
1998}
1999
2000GB_HASH *AW_window::selection_list_to_hash(AW_selection_list *sel_list, bool case_sens) {
2001    // creates a hash (key = value of selection list, value = display string from selection list)
2002
2003    int                     counter = 0;
2004    AW_select_table_struct *list_table;
2005
2006    for ( list_table = sel_list->list_table; list_table; list_table = list_table->next ) {
2007        counter ++;
2008    }
2009
2010    GB_HASH *hash = GBS_create_hash(2*counter, case_sens ? GB_MIND_CASE : GB_IGNORE_CASE);
2011
2012    for ( list_table = sel_list->list_table; list_table; list_table = list_table->next ) {
2013        GBS_write_hash(hash, list_table->char_value, (long)list_table->displayed);
2014    }
2015
2016    return hash;
2017}
2018
2019extern "C" {
2020    int AW_sort_AW_select_table_struct(const void *t1, const void *t2, void *) {
2021        return strcmp(static_cast<const AW_select_table_struct*>(t1)->displayed,
2022                      static_cast<const AW_select_table_struct*>(t2)->displayed);
2023    }
2024    int AW_sort_AW_select_table_struct_backward(const void *t1, const void *t2, void *) {
2025        return strcmp(static_cast<const AW_select_table_struct*>(t2)->displayed,
2026                      static_cast<const AW_select_table_struct*>(t1)->displayed);
2027    }
2028    int AW_isort_AW_select_table_struct(const void *t1, const void *t2, void *) {
2029        return ARB_stricmp(static_cast<const AW_select_table_struct*>(t1)->displayed,
2030                           static_cast<const AW_select_table_struct*>(t2)->displayed);
2031    }
2032    int AW_isort_AW_select_table_struct_backward(const void *t1, const void *t2, void *) {
2033        return ARB_stricmp(static_cast<const AW_select_table_struct*>(t2)->displayed,
2034                           static_cast<const AW_select_table_struct*>(t1)->displayed);
2035    }
2036}
2037
2038
2039AW_selection_list* AW_window::copySelectionList(AW_selection_list *sourceList, AW_selection_list *destinationList){
2040
2041    if (destinationList) clear_selection_list(destinationList);
2042    else {
2043        printf(" Destination list not initialized!!\n");
2044        return 0;
2045    }
2046
2047    const char *readListItem = sourceList->first_element();
2048
2049    while (readListItem) {
2050        insert_selection(destinationList,readListItem,readListItem);
2051        readListItem = sourceList->next_element();
2052    }
2053
2054    insert_default_selection(destinationList,"END of List", "");
2055    update_selection_list(destinationList);
2056
2057    return destinationList;
2058}
2059
2060
2061void AW_window::sort_selection_list( AW_selection_list * selection_list, int backward, int case_sensitive) {
2062
2063    AW_select_table_struct *list_table;
2064
2065    long count = 0;
2066    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next){
2067        count ++;
2068    }
2069    if (!count) return;
2070
2071    AW_select_table_struct **tables = new AW_select_table_struct *[count];
2072    count = 0;
2073    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next){
2074        tables[count] = list_table;
2075        count ++;
2076    }
2077
2078    gb_compare_function comparator;
2079    if (backward) {
2080        if (case_sensitive) comparator = AW_sort_AW_select_table_struct_backward;
2081        else comparator                = AW_isort_AW_select_table_struct_backward;
2082    }
2083    else {
2084        if (case_sensitive) comparator = AW_sort_AW_select_table_struct;
2085        else comparator                = AW_isort_AW_select_table_struct;
2086    }
2087
2088    GB_sort((void**)tables, 0, count, comparator, 0);
2089
2090    long i;
2091    for (i=0;i<count-1;i++) {
2092        tables[i]->next = tables[i+1];
2093    }
2094    tables[i]->next = 0;
2095    selection_list->list_table = tables[0];
2096    selection_list->last_of_list_table = tables[i];
2097
2098    delete [] tables;
2099    return;
2100}
2101
2102GB_ERROR AW_window::save_selection_list( AW_selection_list * selection_list, const char *filename, long number_of_lines) {
2103    // number_of_lines == 0     -> print all
2104
2105    AW_select_table_struct *list_table;
2106    FILE                   *fd;
2107
2108    fd = fopen( filename, "w");
2109    if (!fd) {
2110        return GB_export_IO_error("writing", filename);
2111    }
2112    for ( list_table = selection_list->list_table; list_table; list_table = list_table->next) {
2113        char *sep = 0;
2114
2115        if (selection_list->value_equal_display == false) {
2116            sep = strstr(list_table->displayed,"#"); // interpret displayed as 'value#displayed' (old general behavior)
2117        }
2118
2119        int res;
2120        if (sep) { // replace first '#' with ','  (that's loaded different)
2121            *sep = 0;
2122            fprintf( fd, "%s,",list_table->displayed );
2123            *sep++ = '#';
2124            res  = fprintf( fd, "%s\n",sep );
2125        }
2126        else {
2127            res = fprintf( fd, "%s\n", list_table->displayed ); // save plain (no interpretation)
2128        }
2129
2130        if (res<0) {
2131            aw_message("Disc Full");
2132            break;
2133        }
2134
2135        if (--number_of_lines == 0) break; // number_of_lines == 0 -> write all lines; otherwise write number_of_lines lines
2136    }
2137    fclose( fd );
2138    return 0;
2139}
2140
2141GB_ERROR AW_window::load_selection_list( AW_selection_list *selection_list, const char *filename) {
2142    char *nl;
2143    char *ko;
2144    char *pl;
2145
2146    this->clear_selection_list(selection_list);
2147    char **fnames = GBS_read_dir(filename, NULL);
2148    char **fname;
2149
2150    for (fname = fnames; *fname; fname++){
2151        char *data = GB_read_file(*fname);
2152        if (!data){
2153            GB_print_error();
2154            continue;
2155        }
2156
2157        int correct_old_format = -1;
2158
2159        for (pl = data; pl; pl = nl) {
2160            ko = strchr(pl,','); // look for ','
2161
2162            if (ko) {
2163                if (selection_list->value_equal_display) { // here no comma should occur
2164                    if (correct_old_format == -1) {
2165                        correct_old_format = aw_ask_sure(GBS_global_string("'%s' seems to be in old selection-list-format. Try to correct?", *fname));
2166                    }
2167
2168                    if (correct_old_format == 1) {
2169                        *ko = '#'; // restore (was converted by old-version save)
2170                        ko  = 0; // ignore comma
2171                    }
2172                }
2173            }
2174
2175            if (ko) *(ko++) = 0;
2176            else ko         = pl; // if no comma -> display same as value
2177
2178            while (*ko == ' ' || *ko == '\t') ko++;
2179
2180            nl              = strchr(ko,'\n');
2181            if (nl) *(nl++) = 0;
2182
2183            if (ko[0] && pl[0] != '#') this->insert_selection(selection_list,pl,ko);
2184        }
2185        free(data);
2186    }
2187    GBT_free_names(fnames);
2188
2189    this->insert_default_selection(selection_list,"","");
2190    this->update_selection_list(selection_list);
2191    return 0;
2192}
2193
2194// --------------------------------------------------------------------------------
2195//  Options-Menu
2196// --------------------------------------------------------------------------------
2197
2198AW_option_menu_struct *AW_window::create_option_menu( const char *var_name, AW_label tmp_label, const char *mnemonic ) {
2199    Widget optionMenu_shell;
2200    Widget optionMenu;
2201    Widget optionMenu1;
2202    int x_for_position_of_menu;
2203
2204    if ( _at->label_for_inputfield ) {
2205        tmp_label = _at->label_for_inputfield;
2206    }
2207
2208    check_at_pos();
2209
2210    if ( _at->correct_for_at_center ) {
2211//         _at->correct_for_at_center_intern = _at->correct_for_at_center;
2212        if ( tmp_label ) {
2213            _at->saved_x = _at->x_for_next_button;
2214            x_for_position_of_menu = 10;
2215        }
2216        else {
2217            _at->saved_x = _at->x_for_next_button;
2218            x_for_position_of_menu = 10;
2219        }
2220    }
2221    else {
2222        if ( tmp_label ) {
2223            x_for_position_of_menu = _at->x_for_next_button - 3;
2224        }
2225        else {
2226            x_for_position_of_menu = _at->x_for_next_button - 3 - 7;
2227        }
2228    }
2229
2230    optionMenu_shell = XtVaCreatePopupShell ("optionMenu shell",
2231                                             xmMenuShellWidgetClass,
2232                                             INFO_WIDGET,
2233                                             XmNwidth, 1,
2234                                             XmNheight, 1,
2235                                             XmNallowShellResize, true,
2236                                             XmNoverrideRedirect, true,
2237                                             XmNfontList, p_global->fontlist,
2238                                             NULL );
2239   
2240    optionMenu = XtVaCreateWidget( "optionMenu_p1",
2241                                   xmRowColumnWidgetClass,
2242                                   optionMenu_shell,
2243                                   XmNrowColumnType, XmMENU_PULLDOWN,
2244                                   XmNfontList, p_global->fontlist,
2245                                   NULL );
2246
2247    if ( tmp_label ) {
2248        char *help_label;
2249        int   width_help_label, height_help_label;
2250        calculate_label_size(this, &width_help_label, &height_help_label, false, tmp_label);
2251        // @@@ FIXME: use height_help_label for Y-alignment
2252
2253#if defined(DUMP_BUTTON_CREATION)
2254        printf("width_help_label=%i label='%s'\n", width_help_label, tmp_label);
2255#endif // DUMP_BUTTON_CREATION
2256
2257        help_label = this->align_string( tmp_label, width_help_label);
2258        // help_label = this->align_string( tmp_label, calculate_label_length() );
2259        if (mnemonic && mnemonic[0] && strchr(tmp_label,mnemonic[0])){
2260            optionMenu1 = XtVaCreateManagedWidget( "optionMenu1",
2261                                                   xmRowColumnWidgetClass,
2262                                                   INFO_WIDGET,
2263                                                   XmNrowColumnType, XmMENU_OPTION,
2264                                                   XmNsubMenuId, optionMenu,
2265                                                   XmNfontList, p_global->fontlist,
2266                                                   XmNx, (int)x_for_position_of_menu,
2267                                                   XmNy, (int)(_at->y_for_next_button - 5),
2268                                                   RES_CONVERT( XmNlabelString, help_label ),
2269                                                   RES_CONVERT( XmNmnemonic, mnemonic ),
2270                                                   NULL );
2271        }else{
2272            optionMenu1 = XtVaCreateManagedWidget( "optionMenu1",
2273                                                   xmRowColumnWidgetClass,
2274                                                   INFO_WIDGET,
2275                                                   XmNrowColumnType, XmMENU_OPTION,
2276                                                   XmNsubMenuId, optionMenu,
2277                                                   XmNfontList, p_global->fontlist,
2278                                                   XmNx, (int)x_for_position_of_menu,
2279                                                   XmNy, (int)(_at->y_for_next_button - 5),
2280                                                   RES_CONVERT( XmNlabelString, help_label ),
2281                                                   NULL );
2282        }
2283        free(help_label);
2284    }
2285    else {
2286        optionMenu1 = XtVaCreateManagedWidget( "optionMenu1",
2287                                               xmRowColumnWidgetClass,
2288                                               (_at->attach_any)?INFO_FORM:INFO_WIDGET,
2289                                               XmNrowColumnType, XmMENU_OPTION,
2290                                               XmNsubMenuId, optionMenu,
2291                                               XmNfontList, p_global->fontlist,
2292                                               XmNx, (int)x_for_position_of_menu,
2293                                               XmNy, (int)(_at->y_for_next_button - 5),
2294                                               RES_CONVERT( XmNlabelString, "" ),
2295                                               NULL );
2296        if (_at->attach_any){
2297            aw_attach_widget(optionMenu1,_at);
2298        }
2299    }
2300
2301#if 0
2302    // setting background color for radio button only does not work.
2303    // works only for label and button together, that's not what we want.
2304    //
2305    TuneBackground(optionMenu_shell, TUNE_BUTTON); // set background color for radio button
2306    XtVaSetValues(optionMenu1, // colorizes background and label
2307                  XmNbackground, _at->background_color,
2308                  NULL);
2309#endif
2310
2311    get_root()->number_of_option_menues++;
2312
2313    AW_awar *vs = root->awar(var_name);
2314    {
2315        AW_option_menu_struct *next =
2316            new AW_option_menu_struct(get_root()->number_of_option_menues,
2317                                      var_name,
2318                                      vs->variable_type,
2319                                      optionMenu1,
2320                                      optionMenu,
2321                                      _at->x_for_next_button - 7,
2322                                      _at->y_for_next_button,
2323                                      _at->correct_for_at_center);
2324
2325        if ( p_global->option_menu_list ) {
2326            p_global->last_option_menu->next = next;
2327            p_global->last_option_menu = p_global->last_option_menu->next;
2328        }
2329        else {
2330            p_global->last_option_menu = p_global->option_menu_list = next;
2331        }
2332    }
2333
2334    p_global->current_option_menu = p_global->last_option_menu;
2335
2336    AW_INSERT_BUTTON_IN_AWAR_LIST( vs,(AW_CL)p_global->current_option_menu, optionMenu, AW_WIDGET_CHOICE_MENU, this);
2337    root->make_sensitive(optionMenu1, _at->widget_mask);
2338   
2339    return p_global->current_option_menu;
2340}
2341
2342static void remove_option_from_option_menu(AW_root *aw_root, AW_option_struct *os) {
2343    AW_remove_button_from_sens_list(aw_root, os->choice_widget);
2344    XtDestroyWidget(os->choice_widget);
2345}
2346
2347void AW_window::clear_option_menu(AW_option_menu_struct *oms) {
2348    p_global->current_option_menu = oms; // define as current (for subsequent inserts)
2349
2350    AW_option_struct *next_os;
2351    for (AW_option_struct *os = oms->first_choice; os; os = next_os) {
2352        next_os  = os->next;
2353        os->next = 0;
2354        remove_option_from_option_menu(root, os);
2355        delete os;
2356    }
2357
2358    if (oms->default_choice) {
2359        remove_option_from_option_menu(root, oms->default_choice);
2360        oms->default_choice = 0;
2361    }
2362
2363    oms->first_choice   = 0;
2364    oms->last_choice    = 0;
2365}
2366
2367void *AW_window::_create_option_entry(AW_VARIABLE_TYPE type, const char *name, const char *mnemonic,const char *name_of_color) {
2368
2369    AWUSE(mnemonic);
2370    Widget                 entry;
2371    AW_option_menu_struct *oms = p_global->current_option_menu;
2372
2373    if ( oms->variable_type != type ) {
2374        AW_ERROR("Option menu not defined for this type");
2375    }
2376
2377    TuneOrSetBackground(oms->menu_widget, name_of_color, TUNE_BUTTON); // set background color for radio button entries
2378    entry = XtVaCreateManagedWidget( "optionMenu_entry",
2379                                     xmPushButtonWidgetClass,
2380                                     oms->menu_widget,
2381                                     RES_LABEL_CONVERT(((char *)name)),
2382                                     XmNfontList, p_global->fontlist,
2383                                     XmNbackground, _at->background_color, 
2384                                     NULL );
2385    AW_label_in_awar_list(this,entry,name);
2386    return (void *)entry;
2387}
2388
2389inline void option_menu_add_option(AW_option_menu_struct *oms, AW_option_struct *os, bool default_option) {
2390    if (default_option) {
2391        oms->default_choice = os;
2392    }
2393    else {
2394        if ( oms->first_choice ) {
2395            oms->last_choice->next = os;
2396            oms->last_choice       = oms->last_choice->next;
2397        }
2398        else {
2399            oms->last_choice = oms->first_choice = os;
2400        }
2401    }
2402}
2403
2404// for string :
2405
2406void AW_window::insert_option_internal(AW_label option_name, const char *mnemonic, const char *var_value, const char *name_of_color, bool default_option) {
2407    AW_option_menu_struct *oms = p_global->current_option_menu;
2408    if (oms->variable_type != AW_STRING){
2409        option_type_mismatch("string");
2410    }
2411    else {
2412        Widget        entry = (Widget)_create_option_entry(AW_STRING, option_name, mnemonic, name_of_color);
2413        AW_cb_struct *cbs   = _callback; // user-own callback
2414
2415        // callback for new choice
2416        XtAddCallback(entry, XmNactivateCallback,
2417                      (XtCallbackProc) AW_variable_update_callback,
2418                      (XtPointer) new AW_variable_update_struct(NULL, AW_WIDGET_CHOICE_MENU, root->awar(oms->variable_name), var_value, 0, 0, cbs));
2419
2420        option_menu_add_option(p_global->current_option_menu, new AW_option_struct(var_value, entry), default_option);
2421        root->make_sensitive(entry, _at->widget_mask);
2422        this->unset_at_commands();
2423    }
2424}
2425void AW_window::insert_option_internal(AW_label option_name, const char *mnemonic, int var_value, const char *name_of_color, bool default_option) {
2426    AW_option_menu_struct *oms = p_global->current_option_menu;
2427
2428    if (oms->variable_type != AW_INT){
2429        option_type_mismatch("int");
2430    }
2431    else {
2432        Widget        entry = (Widget)_create_option_entry(AW_INT, option_name, mnemonic, name_of_color);
2433        AW_cb_struct *cbs   = _callback; // user-own callback
2434
2435        // callback for new choice
2436        XtAddCallback(entry, XmNactivateCallback,
2437                      (XtCallbackProc) AW_variable_update_callback,
2438                      (XtPointer) new AW_variable_update_struct(NULL, AW_WIDGET_CHOICE_MENU, root->awar(oms->variable_name), 0, var_value, 0, cbs));
2439
2440        option_menu_add_option(p_global->current_option_menu, new AW_option_struct(var_value, entry), default_option);
2441        root->make_sensitive(entry, _at->widget_mask);
2442        this->unset_at_commands();
2443    }
2444}
2445void AW_window::insert_option_internal(AW_label option_name, const char *mnemonic, float var_value, const char *name_of_color, bool default_option) {
2446    AW_option_menu_struct *oms = p_global->current_option_menu;
2447
2448    if (oms->variable_type != AW_FLOAT){
2449        option_type_mismatch("float");
2450    }
2451    else {
2452        Widget        entry = (Widget)_create_option_entry(AW_FLOAT, option_name, mnemonic, name_of_color);
2453        AW_cb_struct *cbs   = _callback; // user-own callback
2454
2455        // callback for new choice
2456        XtAddCallback(entry, XmNactivateCallback,
2457                      (XtCallbackProc) AW_variable_update_callback,
2458                      (XtPointer) new AW_variable_update_struct(NULL, AW_WIDGET_CHOICE_MENU, root->awar(oms->variable_name), 0, 0, var_value, cbs));
2459
2460        option_menu_add_option(p_global->current_option_menu, new AW_option_struct(var_value, entry), default_option);
2461        root->make_sensitive(entry, _at->widget_mask);
2462        this->unset_at_commands();
2463    }
2464}
2465
2466void AW_window::insert_option        (AW_label on, const char *mn, const char *vv, const char *noc ) { insert_option_internal(on, mn, vv, noc, false); }
2467void AW_window::insert_default_option(AW_label on, const char *mn, const char *vv, const char *noc ) { insert_option_internal(on, mn, vv, noc, true); }
2468void AW_window::insert_option        (AW_label on, const char *mn, int vv,         const char *noc ) { insert_option_internal(on, mn, vv, noc, false); }
2469void AW_window::insert_default_option(AW_label on, const char *mn, int vv,         const char *noc ) { insert_option_internal(on, mn, vv, noc, true); }
2470void AW_window::insert_option        (AW_label on, const char *mn, float vv,       const char *noc ) { insert_option_internal(on, mn, vv, noc, false); }
2471void AW_window::insert_default_option(AW_label on, const char *mn, float vv,       const char *noc ) { insert_option_internal(on, mn, vv, noc, true); }
2472// (see insert_option_internal for longer parameter names)
2473
2474void AW_window::update_option_menu( void ) {
2475    this->update_option_menu( p_global->current_option_menu );
2476}
2477
2478void AW_window::update_option_menu(AW_option_menu_struct *oms) {
2479    if ( get_root()->changer_of_variable != (long)oms->label_widget ) {
2480        AW_option_struct *active_choice = oms->first_choice;
2481        {
2482            char  *global_var_value       = NULL;
2483            long   global_var_int_value   = 0;
2484            float  global_var_float_value = 0;
2485            char  *var_name               = oms->variable_name;
2486
2487#if defined(DEVEL_RALF)
2488#warning missing implementation for AW_POINTER
2489#endif // DEVEL_RALF
2490           
2491            switch ( oms->variable_type ) {
2492                case AW_STRING: global_var_value       = root->awar( var_name )->read_string(); break;
2493                case AW_INT:    global_var_int_value   = root->awar( var_name )->read_int(); break;
2494                case AW_FLOAT:  global_var_float_value = root->awar( var_name )->read_float(); break;
2495                default: break;
2496            }
2497
2498            bool found_choice = false;
2499            while (active_choice) {
2500                switch ( oms->variable_type ) {
2501                    case AW_STRING: found_choice = ((strcmp( global_var_value, active_choice->variable_value ) == 0) ); break;
2502                    case AW_INT:    found_choice = (global_var_int_value   == active_choice->variable_int_value );      break;
2503                    case AW_FLOAT:  found_choice = (global_var_float_value == active_choice->variable_float_value );    break;
2504                    default:
2505                        gb_assert(0);
2506                        GB_warning("Unknown AWAR type");
2507                        break;
2508                }
2509                if (found_choice) break;
2510                active_choice = active_choice->next;
2511            }
2512            free(global_var_value);
2513        }
2514
2515        if (!active_choice) active_choice = oms->default_choice;
2516        if (active_choice) XtVaSetValues( oms->label_widget, XmNmenuHistory, active_choice->choice_widget, NULL);
2517
2518        {
2519            short length;
2520            short height;
2521            XtVaGetValues( oms->label_widget ,XmNwidth ,&length ,XmNheight, &height, NULL );
2522            int   width_of_last_widget  = length;
2523            int   height_of_last_widget = height;
2524
2525            if ( oms->correct_for_at_center_intern ) {
2526                if ( oms->correct_for_at_center_intern == 1 ) { // middle centered
2527                    XtVaSetValues( oms->label_widget, XmNx,(short)((short)_at->saved_x - (short)(length/2)), NULL );
2528                    width_of_last_widget = width_of_last_widget / 2;
2529                }
2530                if ( oms->correct_for_at_center_intern == 2 ) { // right centered
2531                    XtVaSetValues( oms->label_widget, XmNx,(short)((short)_at->saved_x - length) + 7, NULL );
2532                    width_of_last_widget = 0;
2533                }
2534            }
2535            width_of_last_widget -= 4;
2536           
2537            this->unset_at_commands();
2538            this->increment_at_commands( width_of_last_widget, height_of_last_widget );
2539        }
2540    }
2541}
2542
2543
2544/*********************************************************************************************************************************/
2545/*********************************************************************************************************************************/
2546/*********************************************************************************************************************************/
2547
2548void AW_window::create_toggle_field( const char *var_name, AW_label labeli, const char *mnemonic ) {
2549    AWUSE(mnemonic);
2550    if (labeli) this->label(labeli);
2551    this->create_toggle_field(var_name);
2552}
2553
2554
2555void AW_window::create_toggle_field( const char *var_name, int orientation ) {
2556    /* orientation = 0 -> vertical else horizontal layout */
2557
2558    Widget label_for_toggle;
2559    Widget toggle_field;
2560    int x_correcting_for_label = 0;
2561    int width_of_label = 0;
2562    int x_for_position_of_option = 0;
2563    const char *tmp_label ="";
2564    if ( _at->label_for_inputfield ) {
2565        tmp_label = _at->label_for_inputfield;
2566    }
2567
2568    check_at_pos();
2569
2570    if ( _at->correct_for_at_center ) {
2571//         _at->correct_for_at_center_intern = _at->correct_for_at_center;
2572        _at->saved_x = _at->x_for_next_button;
2573        x_for_position_of_option = 10;
2574    }else {
2575        x_for_position_of_option = _at->x_for_next_button;
2576    }
2577
2578
2579    if ( tmp_label ) {
2580        int height_of_label;
2581        calculate_label_size(this, &width_of_label, &height_of_label, true, tmp_label);
2582        // @@@ FIXME: use height_of_label for Y-alignment
2583        // width_of_label = this->calculate_string_width( this->calculate_label_length() );
2584        label_for_toggle = XtVaCreateManagedWidget( "label",
2585                                                    xmLabelWidgetClass,
2586                                                    INFO_WIDGET,
2587                                                    XmNx, (int)_at->x_for_next_button,
2588                                                    XmNy, (int)(_at->y_for_next_button) + this->get_root()->y_correction_for_input_labels,
2589                                                    XmNwidth, (int)(width_of_label + 2),
2590                                                    RES_CONVERT( XmNlabelString, tmp_label ),
2591                                                    XmNrecomputeSize, false,
2592                                                    XmNalignment, XmALIGNMENT_BEGINNING,
2593                                                    XmNfontList, p_global->fontlist,
2594                                                    NULL );
2595
2596        _at->saved_x_correction_for_label = x_correcting_for_label = width_of_label + 10;
2597
2598        p_w->toggle_label = label_for_toggle;
2599    } else {
2600        p_w->toggle_label = NULL;
2601        _at->saved_x_correction_for_label = 0;
2602    }
2603
2604    if (orientation) {
2605        toggle_field = XtVaCreateManagedWidget( "rowColumn for toggle field",
2606                                                xmRowColumnWidgetClass,
2607                                                (_at->attach_any)?INFO_FORM:INFO_WIDGET,
2608                                                XmNorientation,XmHORIZONTAL,
2609                                                XmNx, (int)(x_for_position_of_option + x_correcting_for_label),
2610                                                XmNy, (int)(_at->y_for_next_button - 2),
2611                                                XmNradioBehavior, True,
2612                                                XmNradioAlwaysOne, True,
2613                                                XmNfontList, p_global->fontlist,
2614                                                NULL );
2615    }else{
2616        toggle_field = XtVaCreateManagedWidget( "rowColumn for toggle field",
2617                                                xmRowColumnWidgetClass,
2618                                                (_at->attach_any)?INFO_FORM:INFO_WIDGET,
2619                                                XmNx, (int)(x_for_position_of_option + x_correcting_for_label),
2620                                                XmNy, (int)(_at->y_for_next_button - 2),
2621                                                XmNradioBehavior, True,
2622                                                XmNradioAlwaysOne, True,
2623                                                XmNfontList, p_global->fontlist,
2624                                                NULL );
2625    }
2626    if (_at->attach_any){
2627        aw_attach_widget(toggle_field,_at,300);
2628    }
2629
2630    AW_awar *vs = root->awar(var_name);
2631   
2632    p_w->toggle_field = toggle_field;
2633    free((p_w->toggle_field_var_name));
2634    p_w->toggle_field_var_name = strdup(var_name );
2635    p_w->toggle_field_var_type = vs->variable_type;
2636
2637    get_root()->number_of_toggle_fields++;
2638
2639    if ( p_global->toggle_field_list ) {
2640        p_global->last_toggle_field->next = new AW_toggle_field_struct( get_root()->number_of_toggle_fields, var_name, vs->variable_type, toggle_field, _at->correct_for_at_center);
2641        p_global->last_toggle_field = p_global->last_toggle_field->next;
2642    }else {
2643        p_global->last_toggle_field = p_global->toggle_field_list = new AW_toggle_field_struct( get_root()->number_of_toggle_fields, var_name, vs->variable_type, toggle_field, _at->correct_for_at_center);
2644    }
2645
2646    AW_INSERT_BUTTON_IN_AWAR_LIST( vs,get_root()->number_of_toggle_fields, toggle_field, AW_WIDGET_TOGGLE_FIELD, this);
2647    root->make_sensitive(toggle_field, _at->widget_mask);
2648}
2649
2650static Widget _aw_create_toggle_entry(AW_window *aww, Widget toggle_field,
2651                                      const char *label,const char *mnemonic,
2652                                      AW_variable_update_struct *awus,
2653                                      AW_toggle_struct *awts, bool default_toggle) {
2654    AW_root *root = aww->get_root();
2655
2656    Widget          toggleButton;
2657
2658    toggleButton = XtVaCreateManagedWidget( "toggleButton",
2659                                            xmToggleButtonWidgetClass,
2660                                            toggle_field,
2661                                            RES_LABEL_CONVERT2(label,aww),
2662                                            RES_CONVERT( XmNmnemonic, mnemonic ),
2663                                            XmNindicatorSize, 16,
2664                                            XmNfontList, p_global->fontlist,
2665
2666                                            NULL );
2667    awts->toggle_widget = toggleButton;
2668    awus->widget = toggleButton;
2669    XtAddCallback( toggleButton, XmNvalueChangedCallback,
2670                   (XtCallbackProc) AW_variable_update_callback,
2671                   (XtPointer) awus );
2672    if (default_toggle) {
2673        delete p_global->last_toggle_field->default_toggle;
2674        p_global->last_toggle_field->default_toggle = awts;
2675    }else {
2676        if ( p_global->last_toggle_field->first_toggle ) {
2677            p_global->last_toggle_field->last_toggle->next = awts;
2678            p_global->last_toggle_field->last_toggle = awts;
2679        }else {
2680            p_global->last_toggle_field->last_toggle = awts;
2681            p_global->last_toggle_field->first_toggle = awts;
2682        }
2683    }
2684    root->make_sensitive(toggleButton, aww->_at->widget_mask);
2685   
2686    aww->unset_at_commands();
2687    return  toggleButton;
2688}
2689
2690
2691void AW_window::insert_toggle_internal(AW_label toggle_label, const char *mnemonic, const char *var_value, bool default_toggle) {
2692    if ( p_w->toggle_field_var_type != AW_STRING ) {
2693        toggle_type_mismatch("string");
2694    }
2695    else {
2696        _aw_create_toggle_entry(this,p_w->toggle_field,toggle_label,mnemonic,
2697                                new AW_variable_update_struct( NULL, AW_WIDGET_TOGGLE_FIELD, root->awar(p_w->toggle_field_var_name), var_value, 0, 0, _callback ),
2698                                new AW_toggle_struct( var_value, 0 ),
2699                                default_toggle ? true : false);
2700    }
2701}
2702void AW_window::insert_toggle_internal( AW_label toggle_label, const char *mnemonic, int var_value, bool default_toggle) {
2703    if ( p_w->toggle_field_var_type != AW_INT ) {
2704        toggle_type_mismatch("int");
2705    }
2706    else {
2707        _aw_create_toggle_entry(this, p_w->toggle_field, toggle_label,mnemonic,
2708                                new AW_variable_update_struct( NULL, AW_WIDGET_TOGGLE_FIELD, root->awar(p_w->toggle_field_var_name), 0, var_value, 0, _callback ),
2709                                new AW_toggle_struct( var_value, 0 ),
2710                                default_toggle ? true : false);
2711    }
2712}
2713void AW_window::insert_toggle_internal( AW_label toggle_label, const char *mnemonic, float var_value, bool default_toggle) {
2714    if ( p_w->toggle_field_var_type != AW_FLOAT ) {
2715        toggle_type_mismatch("float");
2716    }
2717    else {
2718        _aw_create_toggle_entry(this, p_w->toggle_field,toggle_label, mnemonic,
2719                                new AW_variable_update_struct( NULL, AW_WIDGET_TOGGLE_FIELD, root->awar(p_w->toggle_field_var_name), 0, 0, var_value, _callback ),
2720                                new AW_toggle_struct( var_value, 0 ),
2721                                default_toggle ? true : false);
2722    }
2723}
2724
2725void AW_window::insert_toggle        ( AW_label toggle_label, const char *mnemonic, const char *var_value ) { insert_toggle_internal(toggle_label, mnemonic, var_value, false); }
2726void AW_window::insert_default_toggle( AW_label toggle_label, const char *mnemonic, const char *var_value ) { insert_toggle_internal(toggle_label, mnemonic, var_value, true);  }
2727void AW_window::insert_toggle        ( AW_label toggle_label, const char *mnemonic, int var_value )         { insert_toggle_internal(toggle_label, mnemonic, var_value, false); }
2728void AW_window::insert_default_toggle( AW_label toggle_label, const char *mnemonic, int var_value )         { insert_toggle_internal(toggle_label, mnemonic, var_value, true);  }
2729void AW_window::insert_toggle        ( AW_label toggle_label, const char *mnemonic, float var_value )       { insert_toggle_internal(toggle_label, mnemonic, var_value, false); }
2730void AW_window::insert_default_toggle( AW_label toggle_label, const char *mnemonic, float var_value )       { insert_toggle_internal(toggle_label, mnemonic, var_value, true);  }
2731
2732void AW_window::update_toggle_field( void ) {
2733    this->update_toggle_field( get_root()->number_of_toggle_fields );
2734}
2735
2736
2737void AW_window::update_toggle_field( int toggle_field_number ) {
2738#if defined(DEBUG)
2739    static int inside_here = 0;
2740    aw_assert(!inside_here);
2741    inside_here++;
2742#endif // DEBUG
2743
2744    AW_toggle_field_struct *toggle_field_list = p_global->toggle_field_list;
2745    {
2746        while (toggle_field_list) {
2747            if (toggle_field_number == toggle_field_list->toggle_field_number) {
2748                break;
2749            }
2750            toggle_field_list = toggle_field_list->next;
2751        }
2752    }
2753
2754    if (toggle_field_list) {
2755        AW_toggle_struct *active_toggle = toggle_field_list->first_toggle;
2756        {
2757            char  *global_var_value       = NULL;
2758            long   global_var_int_value   = 0;
2759            float  global_var_float_value = 0;
2760
2761#if defined(DEVEL_RALF)
2762#warning missing implementation for AW_POINTER
2763#endif // DEVEL_RALF
2764           
2765            switch ( toggle_field_list->variable_type ) {
2766                case AW_STRING: global_var_value       = root->awar( toggle_field_list->variable_name )->read_string(); break;
2767                case AW_INT:    global_var_int_value   = root->awar( toggle_field_list->variable_name )->read_int();    break;
2768                case AW_FLOAT:  global_var_float_value = root->awar( toggle_field_list->variable_name )->read_float();  break;
2769                default:
2770                    gb_assert(0);
2771                    GB_warning("Unknown AWAR type");
2772                    break;
2773            }
2774
2775            bool found_toggle = false;
2776            while (active_toggle) {
2777                switch (toggle_field_list->variable_type) {
2778                    case AW_STRING: found_toggle = (strcmp( global_var_value, active_toggle->variable_value ) == 0);  break;
2779                    case AW_INT:    found_toggle = (global_var_int_value == active_toggle->variable_int_value);       break;
2780                    case AW_FLOAT:  found_toggle = (global_var_float_value == active_toggle->variable_float_value);   break;
2781                    default:
2782                        gb_assert(0);
2783                        GB_warning("Unknown AWAR type");
2784                        break;
2785                }
2786                if (found_toggle) break;
2787                active_toggle = active_toggle->next;
2788            }
2789            if (!found_toggle) active_toggle = toggle_field_list->default_toggle;
2790            free(global_var_value);
2791        }
2792
2793        // iterate over all toggles including default_toggle and set their state
2794        for (AW_toggle_struct *toggle = toggle_field_list->first_toggle; toggle; ) {
2795            XmToggleButtonSetState(toggle->toggle_widget, toggle == active_toggle, False);
2796
2797            if (toggle->next)                                     toggle = toggle->next;
2798            else if (toggle != toggle_field_list->default_toggle) toggle = toggle_field_list->default_toggle;
2799            else                                                  toggle = 0;
2800        }
2801
2802        {
2803            short length;
2804            short height;
2805            XtVaGetValues( p_w->toggle_field ,XmNwidth ,&length ,XmNheight, &height, NULL );
2806            length                += (short)_at->saved_x_correction_for_label;
2807
2808            int width_of_last_widget  = length;
2809            int height_of_last_widget = height;
2810
2811            if ( toggle_field_list->correct_for_at_center_intern ) {
2812                if ( toggle_field_list->correct_for_at_center_intern == 1 ) { // middle centered
2813                    XtVaSetValues( p_w->toggle_field, XmNx,(short)((short)_at->saved_x - (short)(length/2) + (short)_at->saved_x_correction_for_label ), NULL );
2814                    if ( p_w->toggle_label ) {
2815                        XtVaSetValues( p_w->toggle_label, XmNx,(short)((short)_at->saved_x - (short)(length/2) ), NULL );
2816                    }
2817                    width_of_last_widget = width_of_last_widget / 2;
2818                }
2819                if ( toggle_field_list->correct_for_at_center_intern == 2 ) { // right centered
2820                    XtVaSetValues( p_w->toggle_field, XmNx,(short)((short)_at->saved_x - length + (short)_at->saved_x_correction_for_label ), NULL );
2821                    if ( p_w->toggle_label ) {
2822                        XtVaSetValues( p_w->toggle_label, XmNx,(short)( (short)_at->saved_x - length ) , NULL );
2823                    }
2824                    width_of_last_widget = 0;
2825                }
2826            }
2827
2828            this->unset_at_commands();
2829            this->increment_at_commands( width_of_last_widget, height_of_last_widget );
2830        }
2831    }
2832    else {
2833        AW_ERROR("update_toggle_field: toggle field %i does not exist", toggle_field_number );
2834    }
2835
2836#if defined(DEBUG)
2837    inside_here--;
2838#endif // DEBUG
2839}
Note: See TracBrowser for help on using the repository browser.