source: tags/cvs_2_svn/WINDOW/AW_window.cxx

Last change on this file was 5383, checked in by westram, 16 years ago
  • warnings fixed
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 136.8 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <memory.h>
4#include <stdarg.h>
5#include <ctype.h>
6
7#include <sys/types.h>
8#include <sys/uio.h>
9#include <unistd.h>
10
11#include <Xm/Xm.h>
12#include <X11/keysym.h>
13#include <X11/Xlib.h>
14#include <X11/Xutil.h>
15#include <X11/Shell.h>
16#include <X11/cursorfont.h>
17#include <Xm/AtomMgr.h>
18#include <Xm/Frame.h>
19#include <Xm/PushB.h>
20#include <Xm/Protocols.h>
21#include <Xm/RowColumn.h>
22#include <Xm/DrawingA.h>
23#include <Xm/Form.h>
24#include <Xm/Separator.h>
25#include <Xm/MainW.h>
26#include <Xm/CascadeB.h>
27#include <Xm/MenuShell.h>
28#include <Xm/ScrollBar.h>
29#include <Xm/MwmUtil.h>
30
31#include <arbdb.h>
32#include <arbdbt.h>
33
34/* Eigene Klassendefinition */
35#include "aw_root.hxx"
36#include "aw_device.hxx"
37#include "aw_commn.hxx"
38#include "aw_keysym.hxx"
39#include "aw_at.hxx"
40#include "aw_window.hxx"
41#include "aw_awar.hxx"
42#include "aw_xfig.hxx"
43#include "aw_xfigfont.hxx"
44/* hier die Motif abhaengigen Teile */
45#include "aw_Xm.hxx"
46#include "aw_click.hxx"
47#include "aw_size.hxx"
48#include "aw_print.hxx"
49#include "aw_window_Xm.hxx"
50#include "aw_xkey.hxx"
51
52#include "aw_global.hxx"
53
54#if defined(ARB_OPENGL)
55
56/** OpenGL header files */
57// #include <GL/glew.h>
58// #include <GL/GLwMDrawA.h>       /** Provides a special motif widget class */
59#define GLX_GLXEXT_PROTOTYPES
60// #include <GL/glx.h>
61// #include <GL/glut.h>
62
63#include "GLwMDrawA.h" /** Provides a special motif widget class */
64
65/* defined here by Yadhu inorder to make it more General */
66bool AW_alpha_Size_Supported = false;
67
68#endif // ARB_OPENGL
69
70AW_root *AW_root::THIS= NULL;
71
72AW_cb_struct::AW_cb_struct(AW_window *awi, void (*g)(AW_window*,AW_CL,AW_CL), AW_CL cd1i, AW_CL cd2i,
73        const char *help_texti, class AW_cb_struct *nexti) {
74    aw = awi;
75    f = g;
76    cd1 = cd1i;
77    cd2 = cd2i;
78    help_text = help_texti;
79    pop_up_window = NULL;
80    this->next = nexti;
81}
82
83AW_variable_update_struct::AW_variable_update_struct(Widget widgeti,
84        AW_widget_type widget_typei, AW_awar *awari, const char *var_s_i,
85        int var_i_i, float var_f_i, AW_cb_struct *cbsi) {
86
87    widget = widgeti;
88    widget_type = widget_typei;
89    awar = awari;
90    if (var_s_i) {
91        variable_value = strdup(var_s_i);
92    } else {
93        variable_value = 0;
94    }
95    variable_int_value = var_i_i; // used for toggles and selection menus
96    variable_float_value = var_f_i;
97    cbs = cbsi;
98
99}
100
101AW_timer_cb_struct::AW_timer_cb_struct(AW_root *ari, void (*g)(AW_root*,AW_CL,AW_CL), AW_CL cd1i, AW_CL cd2i) {
102    ar = ari;
103    f = g;
104    cd1 = cd1i;
105    cd2 = cd2i;
106}
107AW_timer_cb_struct::~AW_timer_cb_struct(void) {
108}
109
110AW_buttons_struct::AW_buttons_struct(AW_root *root, const char *idi,
111        AW_active maski, Widget w) {
112    if (idi) {
113        id = strdup(idi);
114    } else {
115        id = NULL;
116    }
117    mask = maski;
118    button = w;
119    next = 0;
120
121    if (p_global->button_list)
122        p_global->last_button->next = this;
123    else
124        p_global->button_list = this;
125
126    p_global->last_button = this;
127}
128
129AW_buttons_struct::~AW_buttons_struct() {
130    aw_assert(next == 0);
131    // has to be removed from global list before calling dtor
132    free(id);
133}
134
135bool AW_remove_button_from_sens_list(AW_root *root, Widget w) {
136    bool removed = false;
137    if (p_global->button_list) {
138        AW_buttons_struct *prev = 0;
139        AW_buttons_struct *bl= p_global->button_list;
140
141        while (bl) {
142            if (bl->button == w)
143                break; // found wanted widget
144            prev = bl;
145            bl = bl->next;
146        }
147
148        if (bl) {
149            // remove from list
150            if (prev)
151                prev->next = bl->next;
152            else
153                p_global->button_list = bl->next;
154
155            if (p_global->last_button == bl)
156                p_global->last_button = prev;
157
158            bl->next = 0;
159            removed = true;
160            delete bl;
161        }
162    }
163    return removed;
164}
165
166AW_config_struct::AW_config_struct(const char *idi, AW_active maski, Widget w,
167        const char *variable_namei, const char *variable_valuei,
168        AW_config_struct *nexti) {
169    id = strdup(idi);
170    mask = maski;
171    widget = w;
172    variable_name = strdup(variable_namei);
173    variable_value = strdup(variable_valuei);
174    next = nexti;
175}
176
177/*************************************************************************************************************/
178
179AW_option_struct::AW_option_struct(const char *variable_valuei,
180        Widget choice_widgeti) :
181    variable_value(strdup(variable_valuei)), choice_widget(choice_widgeti),
182            next(0) {
183}
184
185AW_option_struct::AW_option_struct(int variable_valuei, Widget choice_widgeti) :
186    variable_value(0), variable_int_value(variable_valuei),
187            choice_widget(choice_widgeti), next(0) {
188}
189
190AW_option_struct::AW_option_struct(float variable_valuei, Widget choice_widgeti) :
191    variable_value(0), variable_float_value(variable_valuei),
192            choice_widget(choice_widgeti), next(0) {
193}
194
195AW_option_struct::~AW_option_struct() {
196    aw_assert(next == 0);
197    // has to be unlinked from list BEFORE calling dtor
198    free(variable_value);
199}
200
201AW_option_menu_struct::AW_option_menu_struct(int numberi,
202        const char *unique_option_menu_namei, const char *variable_namei,
203        AW_VARIABLE_TYPE variable_typei, Widget label_widgeti,
204        Widget menu_widgeti, AW_pos xi, AW_pos yi, int correct) {
205    option_menu_number = numberi;
206    unique_option_menu_name
207            = unique_option_menu_namei ? strdup(unique_option_menu_namei) : 0;
208
209    variable_name = strdup(variable_namei);
210    variable_type = variable_typei;
211    label_widget = label_widgeti;
212    menu_widget = menu_widgeti;
213    first_choice = NULL;
214    last_choice = NULL;
215    default_choice = NULL;
216    next = NULL;
217    x = xi;
218    y = yi;
219
220    correct_for_at_center_intern = correct;
221}
222
223AW_toggle_field_struct::AW_toggle_field_struct(int toggle_field_numberi,
224        const char *variable_namei, AW_VARIABLE_TYPE variable_typei,
225        Widget label_widgeti, int correct) {
226
227    toggle_field_number = toggle_field_numberi;
228    variable_name = strdup(variable_namei);
229    variable_type = variable_typei;
230    label_widget = label_widgeti;
231    first_toggle = NULL;
232    last_toggle = NULL;
233    default_toggle = NULL;
234    next = NULL;
235    correct_for_at_center_intern = correct;
236}
237AW_toggle_struct::AW_toggle_struct(const char *variable_valuei,
238        Widget toggle_widgeti) {
239
240    variable_value = strdup(variable_valuei);
241    toggle_widget = toggle_widgeti;
242    next = NULL;
243
244}
245AW_toggle_struct::AW_toggle_struct(int variable_valuei, Widget toggle_widgeti) {
246
247    variable_int_value = variable_valuei;
248    toggle_widget = toggle_widgeti;
249    next = NULL;
250
251}
252AW_toggle_struct::AW_toggle_struct(float variable_valuei, Widget toggle_widgeti) {
253
254    variable_float_value = variable_valuei;
255    toggle_widget = toggle_widgeti;
256    next = NULL;
257
258}
259char *AW_select_table_struct::copy_string(const char *str) {
260    char *out = strdup(str);
261    char *p   = out;
262    int   ch;
263   
264    while ((ch=*(p++)) != 0) {
265        if (ch==',')
266            p[-1] = ';';
267        if (ch=='\n')
268            p[-1] = '#';
269    }
270    return out;
271}
272
273AW_select_table_struct::AW_select_table_struct(const char *displayedi,
274        const char *valuei) {
275    memset((char *)this, 0, sizeof(AW_select_table_struct));
276    displayed = copy_string(displayedi);
277    char_value = strdup(valuei);
278}
279AW_select_table_struct::AW_select_table_struct(const char *displayedi,
280        long valuei) {
281    memset((char *)this, 0, sizeof(AW_select_table_struct));
282    displayed = copy_string(displayedi);
283    int_value = valuei;;
284}
285AW_select_table_struct::AW_select_table_struct(const char *displayedi,
286        float valuei) {
287    memset((char *)this, 0, sizeof(AW_select_table_struct));
288    displayed = copy_string(displayedi);
289    float_value = valuei;
290}
291AW_select_table_struct::~AW_select_table_struct(void) {
292    free(displayed);
293    free(char_value);
294}
295
296AW_selection_list::AW_selection_list(const char *variable_namei,
297        int variable_typei, Widget select_list_widgeti) {
298    memset((char *)this, 0, sizeof(AW_selection_list));
299    variable_name = GB_strdup(variable_namei);
300    variable_type = (AW_VARIABLE_TYPE)variable_typei;
301    select_list_widget = select_list_widgeti;
302    list_table = NULL;
303    last_of_list_table = NULL;
304    default_select = NULL;
305    value_equal_display = false;
306}
307
308AW_root::AW_root(void) {
309    memset((char *)this, 0, sizeof(AW_root));
310    this->THIS = this;
311    this->prvt = (AW_root_Motif *)GB_calloc(sizeof(AW_root_Motif), 1);
312}
313
314AW_root::~AW_root(void) {
315    delete prvt;
316}
317
318AW_window_Motif::AW_window_Motif() {
319    memset((char*)this, 0, sizeof(AW_window_Motif));
320}
321
322AW_window::AW_window(void) {
323    memset((char *)this, 0, sizeof(AW_window));
324    p_w = new AW_window_Motif;
325    _at = new AW_at; // Note to valgrinders : the whole AW_window memory management suffers because Windows are NEVER deleted
326    picture = new AW_rectangle;
327    reset_scrolled_picture_size();
328    slider_pos_vertical = 0;
329    slider_pos_horizontal = 0;
330
331}
332
333AW_window::~AW_window(void) {
334    delete p_w;
335    delete picture;
336}
337
338#if defined(DEBUG)
339// #define DUMP_MENU_LIST          // this should NOT be defined normally (if defined, every window writes all menu-entries to stdout)
340#endif // DEBUG
341#if defined(DUMP_MENU_LIST)
342
343static char *window_name = 0;
344static char *sub_menu = 0;
345
346static void initMenuListing(const char *win_name) {
347    aw_assert(win_name);
348
349    free(window_name); window_name = strdup(win_name);
350    free(sub_menu); sub_menu = 0;
351
352    printf("---------------------------------------- list of menus for '%s'\n", window_name);
353}
354
355static void dumpMenuEntry(const char *entry) {
356    aw_assert(window_name);
357    if (sub_menu) {
358        printf("'%s/%s/%s'\n", window_name, sub_menu, entry);
359    }
360    else {
361        printf("'%s/%s'\n", window_name, entry);
362    }
363}
364
365static void dumpOpenSubMenu(const char *sub_name) {
366    aw_assert(sub_name);
367
368    dumpMenuEntry(sub_name); // dump the menu itself
369
370    if (sub_menu) {
371        char *new_sub_menu = strdup(GBS_global_string("%s/%s", sub_menu, sub_name));
372        free(sub_menu);
373        sub_menu = new_sub_menu;
374    }
375    else {
376        sub_menu = strdup(sub_name);
377    }
378}
379
380static void dumpCloseSubMenu() {
381    aw_assert(sub_menu);
382    char *lslash = strrchr(sub_menu, '/');
383    if (lslash) {
384        lslash[0] = 0;
385    }
386    else {
387        free(sub_menu); sub_menu = 0;
388    }
389}
390
391static void dumpCloseAllSubMenus() {
392    free(sub_menu); sub_menu = 0;
393}
394
395#endif // DUMP_MENU_LIST
396AW_window_menu_modes::AW_window_menu_modes(void) {
397}
398AW_window_menu_modes::~AW_window_menu_modes(void) {
399}
400
401AW_window_menu::AW_window_menu(void) {
402}
403AW_window_menu::~AW_window_menu(void) {
404}
405
406AW_window_simple::AW_window_simple(void) {
407}
408AW_window_simple::~AW_window_simple(void) {
409}
410
411AW_window_simple_menu::AW_window_simple_menu(void) {
412}
413AW_window_simple_menu::~AW_window_simple_menu(void) {
414}
415
416AW_window_message::AW_window_message(void) {
417}
418AW_window_message::~AW_window_message(void) {
419}
420
421/***********************************************************************/
422void AW_window::set_horizontal_scrollbar_left_indent(int indent) {
423    XtVaSetValues(p_w->scroll_bar_horizontal, XmNleftOffset, (int)indent, NULL);
424    left_indent_of_horizontal_scrollbar = indent;
425}
426
427/***********************************************************************/
428static void value_changed_scroll_bar_horizontal(Widget wgt,
429        XtPointer aw_cb_struct, XtPointer call_data) {
430    AWUSE(wgt);
431    XmScrollBarCallbackStruct *sbcbs = (XmScrollBarCallbackStruct *)call_data;
432    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
433    (cbs->aw)->slider_pos_horizontal = sbcbs->value; //setzt Scrollwerte im AW_window
434    cbs->run_callback();
435}
436static void drag_scroll_bar_horizontal(Widget wgt, XtPointer aw_cb_struct,
437        XtPointer call_data) {
438    AWUSE(wgt);
439    XmScrollBarCallbackStruct *sbcbs = (XmScrollBarCallbackStruct *)call_data;
440    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
441    (cbs->aw)->slider_pos_horizontal = sbcbs->value; //setzt Scrollwerte im AW_window
442    cbs->run_callback();
443}
444void AW_window::set_horizontal_change_callback(void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
445    XtAddCallback(p_w->scroll_bar_horizontal, XmNvalueChangedCallback,
446            (XtCallbackProc) value_changed_scroll_bar_horizontal,
447            (XtPointer) new AW_cb_struct(this, f, cd1, cd2, "") );
448    XtAddCallback(p_w->scroll_bar_horizontal, XmNdragCallback,
449            (XtCallbackProc) drag_scroll_bar_horizontal,
450            (XtPointer) new AW_cb_struct(this, f, cd1, cd2, "") );
451}
452
453static void value_changed_scroll_bar_vertical(Widget wgt,
454        XtPointer aw_cb_struct, XtPointer call_data) {
455    AWUSE(wgt);
456    XmScrollBarCallbackStruct *sbcbs = (XmScrollBarCallbackStruct *)call_data;
457    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
458    cbs->aw->slider_pos_vertical = sbcbs->value; //setzt Scrollwerte im AW_window
459    cbs->run_callback();
460}
461static void drag_scroll_bar_vertical(Widget wgt, XtPointer aw_cb_struct,
462        XtPointer call_data) {
463    AWUSE(wgt);
464    XmScrollBarCallbackStruct *sbcbs = (XmScrollBarCallbackStruct *)call_data;
465    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
466    cbs->aw->slider_pos_vertical = sbcbs->value; //setzt Scrollwerte im AW_window
467    cbs->run_callback();
468}
469
470void AW_window::set_vertical_change_callback(void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
471    XtAddCallback(p_w->scroll_bar_vertical, XmNvalueChangedCallback,
472            (XtCallbackProc) value_changed_scroll_bar_vertical,
473            (XtPointer) new AW_cb_struct(this, f, cd1, cd2, "") );
474    XtAddCallback(p_w->scroll_bar_vertical, XmNdragCallback,
475            (XtCallbackProc) drag_scroll_bar_vertical,
476            (XtPointer) new AW_cb_struct(this, f, cd1, cd2, "") );
477
478    XtAddCallback(p_w->scroll_bar_vertical, XmNpageIncrementCallback,
479            (XtCallbackProc) drag_scroll_bar_vertical,
480            (XtPointer) new AW_cb_struct(this, f, cd1, cd2, "") );
481    XtAddCallback(p_w->scroll_bar_vertical, XmNpageDecrementCallback,
482            (XtCallbackProc) drag_scroll_bar_vertical,
483            (XtPointer) new AW_cb_struct(this, f, cd1, cd2, "") );
484}
485
486void AW_window::tell_scrolled_picture_size(AW_rectangle rectangle) {
487    picture->l = rectangle.l;
488    picture->r = rectangle.r;
489    picture->t = rectangle.t;
490    picture->b = rectangle.b;
491}
492void AW_window::tell_scrolled_picture_size(AW_world rectangle) {
493    picture->l = (int)rectangle.l;
494    picture->r = (int)rectangle.r;
495    picture->t = (int)rectangle.t;
496    picture->b = (int)rectangle.b;
497}
498
499void AW_window::reset_scrolled_picture_size() {
500    picture->l = 0;
501    picture->r = 0;
502    picture->t = 0;
503    picture->b = 0;
504}
505AW_pos AW_window::get_scrolled_picture_width() {
506    return (picture->r - picture->l);
507}
508
509AW_pos AW_window::get_scrolled_picture_height() {
510    return (picture->b - picture->t);
511}
512
513void AW_window::calculate_scrollbars(void) {
514    AW_rectangle screen;
515    int slider_size_horizontal;
516    int slider_size_vertical;
517    AW_BOOL vertical, horizontal;
518    int position_of_slider;
519    int slider_max;
520
521    vertical = horizontal = AW_TRUE; // es gibt verticalen & horizontalen scrollbar
522
523    this->_get_area_size(AW_MIDDLE_AREA, &screen);
524
525    // HORIZONTAL
526    slider_max = (int)get_scrolled_picture_width();
527    if (slider_max <1) {
528        slider_max = 1;
529        XtVaSetValues(p_w->scroll_bar_horizontal, XmNsliderSize, 1, NULL);
530    }
531
532    slider_size_horizontal = (int)( (screen.r
533            -left_indent_of_horizontal_scrollbar));
534    if (slider_size_horizontal < 1)
535        slider_size_horizontal = 1; // ist der slider zu klein (<1) ?
536    if (slider_size_horizontal > slider_max) { // Schirm groesser als Bild
537        slider_size_horizontal = slider_max; // slider nimmt ganze laenge ein
538        XtVaSetValues(p_w->scroll_bar_horizontal, XmNvalue, 0, NULL); // slider ganz links setzen
539        horizontal = AW_FALSE; // kein horizontaler slider mehr
540    }
541
542    // check wether XmNValue is to big
543    XtVaGetValues(p_w->scroll_bar_horizontal, XmNvalue, &position_of_slider,
544            NULL);
545    if (position_of_slider > (slider_max-slider_size_horizontal)) {//steht der slider fuer slidergroesse zu rechts ?
546        position_of_slider = slider_max-slider_size_horizontal; //-1 ? vielleicht !
547        if (position_of_slider < 0)
548            position_of_slider = 0;
549        XtVaSetValues(p_w->scroll_bar_horizontal, XmNvalue, position_of_slider,
550                NULL);
551    }
552    // Anpassung fuer resize, wenn unbeschriebener Bereich vergroessert wird
553    if ( -slider_pos_horizontal + get_scrolled_picture_width() < screen.r
554            -left_indent_of_horizontal_scrollbar) {
555        if (horizontal == AW_TRUE)
556            slider_pos_horizontal = (int)(get_scrolled_picture_width()
557                    - (screen.r-left_indent_of_horizontal_scrollbar) );
558        else
559            slider_pos_horizontal = 0; //slider nach ganz oben, da alles sichtbar
560    }
561    XtVaSetValues(p_w->scroll_bar_horizontal, XmNsliderSize, 1, NULL);
562    XtVaSetValues(p_w->scroll_bar_horizontal, XmNmaximum, slider_max, NULL);
563    XtVaSetValues(p_w->scroll_bar_horizontal, XmNsliderSize,
564            slider_size_horizontal, NULL);
565    char buffer[200];
566    sprintf(buffer, "window/%s/horizontal_page_increment", window_defaults_name);
567    XtVaSetValues(p_w->scroll_bar_horizontal, XmNpageIncrement, (int)((screen.r
568            -left_indent_of_horizontal_scrollbar)*(get_root()->awar( buffer )->read_int()*0.01)), 
569    NULL);
570
571    sprintf(buffer, "window/%s/scroll_width_horizontal", window_defaults_name);
572    XtVaSetValues(p_w->scroll_bar_horizontal, XmNincrement, (int)(get_root()->awar( buffer )->read_int()), NULL);
573
574    sprintf(buffer, "window/%s/scroll_delay_horizontal", window_defaults_name);
575    XtVaSetValues(p_w->scroll_bar_horizontal, XmNrepeatDelay, (int)(get_root()->awar( buffer )->read_int()), NULL);
576
577    // VERTICAL
578    slider_max = (int)get_scrolled_picture_height();
579    if (slider_max <1) {
580        slider_max = 1;
581        XtVaSetValues(p_w->scroll_bar_vertical, XmNsliderSize, 1, NULL);
582    }
583
584    slider_size_vertical = (int)( (screen.b-top_indent_of_vertical_scrollbar
585            -bottom_indent_of_vertical_scrollbar));
586    if (slider_size_vertical < 1)
587        slider_size_vertical = 1;
588    if (slider_size_vertical > slider_max) {
589        slider_size_vertical = slider_max;
590        XtVaSetValues(p_w->scroll_bar_vertical, XmNvalue, 0, NULL);
591        vertical = AW_FALSE;
592    }
593
594    // check wether XmNValue is to big
595    XtVaGetValues(p_w->scroll_bar_vertical, XmNvalue, &position_of_slider, NULL);
596    if (position_of_slider > (slider_max-slider_size_vertical)) {
597        position_of_slider = slider_max-slider_size_vertical; //-1 ? vielleicht !
598        if (position_of_slider < 0)
599            position_of_slider = 0;
600        XtVaSetValues(p_w->scroll_bar_vertical, XmNvalue, position_of_slider,
601                NULL);
602    }
603    // Anpassung fuer resize, wenn unbeschriebener Bereich vergroessert wird
604    if ( -slider_pos_vertical + get_scrolled_picture_height() < screen.b
605            -top_indent_of_vertical_scrollbar
606            -bottom_indent_of_vertical_scrollbar) {
607        if (vertical == AW_TRUE)
608            slider_pos_vertical = (int)(get_scrolled_picture_height()
609                    - (screen.b-top_indent_of_vertical_scrollbar
610                            -bottom_indent_of_vertical_scrollbar));
611        else
612            slider_pos_vertical = 0; //slider nach ganz oben, da alles sichtbar
613    }
614    XtVaSetValues(p_w->scroll_bar_vertical, XmNsliderSize, 1, NULL);
615    XtVaSetValues(p_w->scroll_bar_vertical, XmNmaximum, slider_max, NULL);
616    XtVaSetValues(p_w->scroll_bar_vertical, XmNsliderSize,
617            slider_size_vertical, NULL);
618    sprintf(buffer, "window/%s/vertical_page_increment", window_defaults_name);
619    XtVaSetValues(p_w->scroll_bar_vertical, XmNpageIncrement, (int)((screen.b
620            -top_indent_of_vertical_scrollbar
621            -bottom_indent_of_vertical_scrollbar)*(get_root()->awar( buffer )->read_int()*0.01)), 
622    NULL);
623
624    sprintf(buffer, "window/%s/scroll_width_vertical", window_defaults_name);
625    XtVaSetValues(p_w->scroll_bar_vertical, XmNincrement, (int)(get_root()->awar( buffer )->read_int()), NULL);
626
627    sprintf(buffer, "window/%s/scroll_delay_vertical", window_defaults_name);
628    XtVaSetValues(p_w->scroll_bar_vertical, XmNrepeatDelay, (int)(get_root()->awar( buffer )->read_int()), NULL);
629}
630
631void AW_window::set_vertical_scrollbar_position(int position) {
632    slider_pos_vertical = position;
633    XtVaSetValues(p_w->scroll_bar_vertical, XmNvalue, position, NULL);
634}
635
636void AW_window::set_horizontal_scrollbar_position(int position) {
637    slider_pos_horizontal = position;
638    XtVaSetValues(p_w->scroll_bar_horizontal, XmNvalue, position, NULL);
639}
640
641/***********************************************************************/
642static void AW_timer_callback(XtPointer aw_timer_cb_struct, XtIntervalId *id) {
643    AWUSE(id);
644    AW_timer_cb_struct *tcbs = (AW_timer_cb_struct *) aw_timer_cb_struct;
645    if (!tcbs)
646        return;
647
648    AW_root *root = tcbs->ar;
649    if (root->disable_callbacks) {
650        // delay the timer callback for 25ms
651        XtAppAddTimeOut(p_global->context,
652        (unsigned long)25, // wait 25 msec = 1/40 sec
653        (XtTimerCallbackProc)AW_timer_callback,
654        aw_timer_cb_struct);
655    } else {
656        tcbs->f(root, tcbs->cd1, tcbs->cd2);
657        delete tcbs; // timer only once
658    }
659}
660
661static void AW_timer_callback_never_disabled(XtPointer aw_timer_cb_struct,
662        XtIntervalId *id) {
663    AWUSE(id);
664    AW_timer_cb_struct *tcbs = (AW_timer_cb_struct *) aw_timer_cb_struct;
665    if (!tcbs)
666        return;
667
668    tcbs->f(tcbs->ar, tcbs->cd1, tcbs->cd2);
669    delete tcbs; // timer only once
670}
671
672void AW_root::add_timed_callback(int ms, void (*f)(AW_root*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
673    XtAppAddTimeOut(p_r->context,
674    (unsigned long)ms,
675    (XtTimerCallbackProc)AW_timer_callback,
676    (XtPointer) new AW_timer_cb_struct( this, f, cd1, cd2));
677}
678
679void AW_root::add_timed_callback_never_disabled(int ms, void (*f)(AW_root*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
680    XtAppAddTimeOut(p_r->context,
681    (unsigned long)ms,
682    (XtTimerCallbackProc)AW_timer_callback_never_disabled,
683    (XtPointer) new AW_timer_cb_struct( this, f, cd1, cd2));
684}
685
686/***********************************************************************/
687void AW_POPDOWN(AW_window *aww) {
688    aww->hide();
689}
690
691#define BUFSIZE 256
692static char aw_size_awar_name_buffer[BUFSIZE];
693static const char *aw_size_awar_name(AW_window *aww, const char *sub_entry) {
694#if defined(DEBUG)
695    int size =
696#endif // DEBUG
697            sprintf(aw_size_awar_name_buffer, "window/windows/%s/%s",
698                    aww->window_defaults_name, sub_entry);
699#if defined(DEBUG)
700    aw_assert(size < BUFSIZE);
701#endif // DEBUG
702    return aw_size_awar_name_buffer;
703}
704#undef BUFSIZE
705
706#define aw_awar_name_posx(aww)   aw_size_awar_name((aww), "posx")
707#define aw_awar_name_posy(aww)   aw_size_awar_name((aww), "posy")
708#define aw_awar_name_width(aww)  aw_size_awar_name((aww), "width")
709#define aw_awar_name_height(aww) aw_size_awar_name((aww), "height")
710
711static void aw_calculate_WM_offsets(AW_window *aww) {
712    if (p_aww(aww)->WM_top_offset != -1000)
713        return; // very bad hack continued
714
715    AW_root *root = aww->get_root();
716    short posy, posx;
717    int oposy, oposx;
718
719    oposx = root->awar(aw_awar_name_posx(aww))->read_int();
720    oposy = root->awar(aw_awar_name_posy(aww))->read_int();
721
722    XtVaGetValues( p_aww(aww)->shell ,
723    XmNx, &posx,
724    XmNy, &posy,
725    NULL);
726    p_aww(aww)->WM_top_offset = posy-oposy;
727    p_aww(aww)->WM_left_offset = posx-oposx;
728}
729
730/************** standard callback server *********************/
731
732static void macro_message_cb(AW_window *aw, AW_CL);
733
734void AW_cb_struct::run_callback(void) {
735    AW_PPP g;
736    if (next)
737        next->run_callback(); // callback the whole list
738
739    AW_root *root = aw->get_root();
740    if (!f)
741        return;
742
743    if (root->disable_callbacks) {
744        //  the following callbacks are allowed even if disable_callbacks is true
745        if ( (f != (AW_CB)message_cb) && (f != (AW_CB)macro_message_cb) && (f
746                != (AW_CB)modify_input_cb) && (f != (AW_CB)input_cb) && (f
747                != (AW_CB)AW_POPUP_HELP) && (f != (AW_CB)AW_POPDOWN) &&
748
749        !aw->is_expose_callback(AW_MIDDLE_AREA, f) && !aw->is_resize_callback(
750                AW_MIDDLE_AREA, f) && !aw->is_expose_callback(AW_INFO_AREA, f)
751                && !aw->is_resize_callback(AW_INFO_AREA, f) ) {
752            aw_message("That has been ignored. Answer the prompt first!");
753            return;
754        }
755    }
756
757    if (f == AW_POPUP) {
758        if (pop_up_window) {
759            pop_up_window->show();
760        } else {
761            g = (AW_PPP)cd1;
762            if (g) {
763                pop_up_window = g(aw->get_root(), cd2, 0);
764                pop_up_window->show();
765            } else {
766                aw_message("Sorry Function not implemented");
767            }
768        }
769        if (pop_up_window && p_aww(pop_up_window)->popup_cb)
770            p_aww(pop_up_window)->popup_cb->run_callback();
771    } else {
772        f(aw, cd1, cd2);
773    }
774}
775
776AW_BOOL AW_cb_struct::contains(void (*g)(AW_window*,AW_CL ,AW_CL)) {
777    if (f == g)
778        return AW_TRUE;
779    if (!next)
780        return AW_FALSE;
781    return next->contains(g);
782}
783
784void AW_root_Motif::set_cursor(Display *d, Window w, Cursor c) {
785    XSetWindowAttributes attrs;
786    old_cursor_display = d;
787    old_cursor_window = w;
788
789    if (c)
790        attrs.cursor = c;
791    else
792        attrs.cursor = None;
793
794    if (d && w) {
795        XChangeWindowAttributes(d, w, CWCursor, &attrs);
796    }
797    XChangeWindowAttributes(XtDisplay(main_widget), XtWindow(main_widget),
798            CWCursor, &attrs);
799    XFlush(XtDisplay(main_widget));
800}
801
802void AW_root_Motif::normal_cursor(void) {
803    set_cursor(old_cursor_display, old_cursor_window, 0);
804}
805
806void AW_server_callback(Widget wgt, XtPointer aw_cb_struct, XtPointer call_data) {
807    AWUSE(wgt);
808    AWUSE(call_data);
809    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
810
811    AW_root *root = cbs->aw->get_root();
812    if (p_global->help_active) {
813        p_global->help_active = 0;
814        p_global->normal_cursor();
815
816        if (cbs->help_text && ((GBS_string_matches(cbs->help_text, "*.ps", GB_IGNORE_CASE)) ||
817                               (GBS_string_matches(cbs->help_text, "*.hlp", GB_IGNORE_CASE)) ||
818                               (GBS_string_matches(cbs->help_text, "*.help", GB_IGNORE_CASE))))
819        {
820            AW_POPUP_HELP(cbs->aw, (AW_CL)cbs->help_text);
821        }
822        else {
823            aw_message("Sorry no help available");
824        }
825        return;
826    }
827
828    if (root->prvt->recording_macro_file) {
829        if (cbs->id && strcmp(cbs->id, root->prvt->stop_action_name)) {
830            fprintf(root->prvt->recording_macro_file,
831                    "BIO::remote_action($gb_main,\"%s\",",
832                    root->prvt->application_name_for_macros);
833            GBS_fwrite_string(cbs->id, root->prvt->recording_macro_file);
834            fprintf(root->prvt->recording_macro_file, ");\n");
835        }
836    }
837
838    if (cbs->f == AW_POPUP) {
839        cbs->run_callback();
840    } else {
841        p_global->set_cursor(XtDisplay(p_global->toplevel_widget),
842                XtWindow(p_aww(cbs->aw)->shell),
843                p_global->clock_cursor);
844        cbs->run_callback();
845
846        XEvent event; // destroy all old events !!!
847        while (XCheckMaskEvent(XtDisplay(p_global->toplevel_widget), 
848        ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
849        KeyPressMask|KeyReleaseMask|PointerMotionMask, &event)) {
850        }
851
852        if (p_global->help_active) {
853            p_global->set_cursor(XtDisplay(p_global->toplevel_widget),
854                    XtWindow(p_aww(cbs->aw)->shell),
855                    p_global->question_cursor);
856        } else {
857            p_global->set_cursor(XtDisplay(p_global->toplevel_widget),
858                    XtWindow(p_aww(cbs->aw)->shell),
859                    0);
860        }
861    }
862
863}
864
865void AW_clock_cursor(AW_root *root) {
866    p_global->set_cursor(0, 0, p_global->clock_cursor);
867}
868
869void AW_normal_cursor(AW_root *root) {
870    p_global->set_cursor(0, 0, 0);
871}
872
873/***********************************************************************/
874static void AW_root_focusCB(Widget wgt, XtPointer *awrp) {
875    AWUSE(wgt);
876    AW_root *aw_root = (AW_root *)awrp;
877    if (aw_root->focus_callback_list) {
878        aw_root->focus_callback_list->run_callback(aw_root);
879    }
880}
881
882void AW_root::set_focus_callback(void (*f)(class AW_root*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
883    focus_callback_list = new AW_var_callback(f,cd1,cd2,focus_callback_list);
884}
885
886static void AW_focusCB(Widget wgt, XtPointer aw_cb_struct) {
887    AWUSE(wgt);
888    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
889    cbs->run_callback();
890}
891
892void AW_window::set_popup_callback(void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
893    p_w->popup_cb = new AW_cb_struct(this, f, cd1, cd2, 0, p_w->popup_cb);
894}
895
896void AW_window::set_focus_callback(void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
897    XtAddEventHandler(MIDDLE_WIDGET, EnterWindowMask, FALSE,
898    (XtEventHandler)AW_focusCB,
899    (XtPointer) new AW_cb_struct(this, f, cd1, cd2, 0));
900}
901
902/*******************************    expose  ****************************************/
903
904static void AW_exposeCB(Widget wgt, XtPointer aw_cb_struct,
905        XmDrawingAreaCallbackStruct *call_data) {
906    XEvent *ev = call_data->event;
907    AWUSE(wgt);
908    AW_area_management *aram = (AW_area_management *) aw_cb_struct;
909    if (ev->xexpose.count == 0) { // last expose cb
910        if (aram->expose_cb)
911            aram->expose_cb->run_callback();
912    }
913}
914
915void AW_area_management::set_expose_callback(AW_window *aww, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
916    // insert expose callback for draw_area
917    if (!expose_cb) {
918        XtAddCallback(area, XmNexposeCallback, (XtCallbackProc) AW_exposeCB,
919                (XtPointer) this );
920    }
921    expose_cb = new AW_cb_struct(aww, f, cd1, cd2, 0, expose_cb);
922}
923
924void AW_window::set_expose_callback(AW_area area, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
925    AW_area_management *aram= MAP_ARAM(area);
926    if (!aram)
927        return;
928    aram->set_expose_callback(this, f, cd1, cd2);
929}
930
931AW_BOOL AW_area_management::is_expose_callback(AW_window */*aww*/, void (*f)(AW_window*,AW_CL,AW_CL)) {
932    if (!expose_cb)
933        return AW_FALSE;
934    return expose_cb->contains(f);
935}
936
937AW_BOOL AW_window::is_expose_callback(AW_area area, void (*f)(AW_window*,AW_CL,AW_CL)) {
938    AW_area_management *aram= MAP_ARAM(area);
939    if (!aram)
940        return AW_FALSE;
941    return aram->is_expose_callback(this, f);
942}
943
944AW_BOOL AW_area_management::is_resize_callback(AW_window */*aww*/, void (*f)(AW_window*,AW_CL,AW_CL)) {
945    if (!resize_cb)
946        return AW_FALSE;
947    return resize_cb->contains(f);
948}
949
950AW_BOOL AW_window::is_resize_callback(AW_area area, void (*f)(AW_window*,AW_CL,AW_CL)) {
951    AW_area_management *aram= MAP_ARAM(area);
952    if (!aram)
953        return AW_FALSE;
954    return aram->is_resize_callback(this, f);
955}
956
957void AW_window::set_window_size(int width, int height) {
958    XtVaSetValues(p_w->shell, XmNwidth, (int)width, XmNheight, (int)height,
959            NULL);
960}
961
962void AW_window::get_window_size(int &width, int &height) {
963    unsigned short hoffset = 0;
964    if (p_w->menu_bar[0])
965        XtVaGetValues(p_w->menu_bar[0], XmNheight, &hoffset, NULL);
966    width = _at->max_x_size;
967    height = hoffset + _at->max_y_size;
968}
969
970void AW_window::window_fit(void) {
971    int width, height;
972    get_window_size(width, height);
973    set_window_size(width, height);
974}
975
976void AW_window::align(void) {
977    int width, height;
978    get_window_size(width, height);
979    int x = (WidthOfScreen(XtScreen(p_w->shell)) / 2) - (width / 2);
980    int y = (HeightOfScreen(XtScreen(p_w->shell)) / 4) - (height / 4);
981    if (x < 0) x= 0;
982    if (y < 0) y= 0;
983    XtVaSetValues(p_w->shell, XmNx, x, XmNy, y, NULL);
984}
985
986/*******************************    resize  ****************************************/
987
988// Predicate function: checks, if the given event is a ResizeEvent
989int is_resize_event(Display *display, XEvent *event, XPointer) {
990    if (event && (event->type == ResizeRequest || event->type
991            == ConfigureNotify) && event->xany.display == display) {
992        return 1;
993    }
994    return 0;
995}
996
997// Removes redundant resize events from the x-event queue
998void cleanupResizeEvents(Display *display) {
999    if (display) {
1000        XLockDisplay(display);
1001        XEvent event;
1002        if (XCheckIfEvent(display, &event, is_resize_event, 0)) {
1003            // Some magic happens here... ;-) (removing redundant events from queue)
1004            while (XCheckIfEvent(display, &event, is_resize_event, 0))
1005                ;
1006            // Keep last Event in queue
1007            XPutBackEvent(display, &event);
1008        }
1009        XUnlockDisplay(display);
1010    }
1011}
1012
1013static void AW_resizeCB_draw_area(Widget wgt, XtPointer aw_cb_struct,
1014        XtPointer call_data) {
1015    AWUSE(wgt);
1016    AWUSE(call_data);
1017    AW_area_management *aram = (AW_area_management *) aw_cb_struct;
1018    cleanupResizeEvents(aram->common->display);
1019    if (aram->resize_cb)
1020        aram->resize_cb->run_callback();
1021}
1022
1023void AW_area_management::set_resize_callback(AW_window *aww, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1024    // insert resize callback for draw_area
1025    if (!resize_cb) {
1026        XtAddCallback(area, XmNresizeCallback,
1027                (XtCallbackProc) AW_resizeCB_draw_area, (XtPointer) this );
1028    }
1029    resize_cb = new AW_cb_struct(aww, f, cd1, cd2, 0, resize_cb);
1030}
1031
1032void AW_window::set_resize_callback(AW_area area, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1033    AW_area_management *aram= MAP_ARAM(area);
1034    if (!aram)
1035        return;
1036    aram->set_resize_callback(this, f, cd1, cd2);
1037}
1038
1039/***********************************************************************/
1040static void AW_inputCB_draw_area(Widget wgt, XtPointer aw_cb_struct,
1041        XmDrawingAreaCallbackStruct *call_data) {
1042    AWUSE(wgt);
1043    XEvent *ev = call_data->event;
1044
1045    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
1046    AW_window *aww = cbs->aw;
1047    AW_BOOL run_callback = AW_FALSE;
1048    AW_BOOL run_double_click_callback = AW_FALSE;
1049    AW_area_management *area = 0;
1050    {
1051        int i;
1052        for (i=0; i<AW_MAX_AREA; i++) {
1053            if (p_aww(aww)->areas[i]->area == wgt) {
1054                area = p_aww(aww)->areas[i];
1055                break;
1056            }
1057        }
1058    }
1059
1060    if (ev->xbutton.type == ButtonPress) {
1061        aww->event.type = AW_Mouse_Press;
1062        aww->event.button = ev->xbutton.button;
1063        aww->event.x = ev->xbutton.x;
1064        aww->event.y = ev->xbutton.y;
1065        aww->event.keycode = AW_KEY_NONE;
1066        aww->event.keymodifier = AW_KEYMODE_NONE;
1067        aww->event.character = '\0';
1068
1069        if (area && area->double_click_cb) {
1070            if ( (ev->xbutton.time - area->click_time ) < 200) {
1071                run_double_click_callback = AW_TRUE;
1072            } else {
1073                run_callback = AW_TRUE;
1074            }
1075            area->click_time = ev->xbutton.time;
1076        } else {
1077            run_callback = AW_TRUE;
1078        }
1079
1080        aww->event.time = ev->xbutton.time;
1081    } else if (ev->xbutton.type == ButtonRelease) {
1082        aww->event.type = AW_Mouse_Release;
1083        aww->event.button = ev->xbutton.button;
1084        aww->event.x = ev->xbutton.x;
1085        aww->event.y = ev->xbutton.y;
1086        aww->event.keycode = AW_KEY_NONE;
1087        aww->event.keymodifier = AW_KEYMODE_NONE;
1088        aww->event.character = '\0';
1089        //  aww->event.time     use old time
1090
1091        run_callback = AW_TRUE;
1092    } else if (ev->xkey.type == KeyPress || ev->xkey.type == KeyRelease) {
1093        aww->event.time = ev->xbutton.time;
1094
1095        const awXKeymap *mykey = aw_xkey_2_awkey(&(ev->xkey));
1096
1097        aww->event.keycode = mykey->awkey;
1098        aww->event.keymodifier = mykey->awmod;
1099
1100        if (mykey->awstr) {
1101            aww->event.character = mykey->awstr[0];
1102        } else {
1103            aww->event.character = 0;
1104        }
1105
1106        if (ev->xkey.type == KeyPress) {
1107            aww->event.type = AW_Keyboard_Press;
1108        } else {
1109            aww->event.type = AW_Keyboard_Release;
1110        }
1111        aww->event.button = 0;
1112        aww->event.x = ev->xbutton.x;
1113        aww->event.y = ev->xbutton.y;
1114
1115        if (!mykey->awmod && mykey->awkey >= AW_KEY_F1 && mykey->awkey
1116                <= AW_KEY_F12 && p_aww(aww)->modes_f_callbacks && p_aww(aww)->modes_f_callbacks[mykey->awkey-AW_KEY_F1]
1117                && aww->event.type == AW_Keyboard_Press) {
1118            p_aww(aww)->modes_f_callbacks[mykey->awkey-AW_KEY_F1]->run_callback();
1119        } else {
1120            run_callback = AW_TRUE;
1121        }
1122    }
1123
1124    //  this is done above :
1125    //     else if (ev->xkey.type == KeyRelease) { // added Jan 98 to fetch multiple keystrokes in EDIT4 (may cause side effects)
1126    //         aww->event.time = ev->xbutton.time;
1127    //         aww->event.type = AW_Keyboard_Release;
1128    //         run_callback = AW_TRUE;
1129    //     }
1130
1131    if (run_double_click_callback) {
1132        if (cbs->help_text == (char*)1) {
1133            cbs->run_callback();
1134        } else {
1135            if (area)
1136                area->double_click_cb->run_callback();
1137        }
1138    }
1139
1140    if (run_callback && (cbs->help_text == (char*)0)) {
1141        cbs->run_callback();
1142    }
1143}
1144
1145void AW_area_management::set_input_callback(AW_window *aww, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1146    XtAddCallback(area, XmNinputCallback,
1147            (XtCallbackProc) AW_inputCB_draw_area,
1148            (XtPointer) new AW_cb_struct(aww, f, cd1, cd2, (char*)0) );
1149}
1150
1151void AW_window::set_input_callback(AW_area area, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1152    AW_area_management *aram= MAP_ARAM(area);
1153    if (!aram)
1154        return;
1155    aram->set_input_callback(this, f, cd1, cd2);
1156}
1157
1158/***********************************************************************/
1159void AW_area_management::set_double_click_callback(AW_window *aww, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1160    double_click_cb = new AW_cb_struct(aww, f, cd1, cd2, (char*)0, double_click_cb);
1161}
1162
1163void AW_window::set_double_click_callback(AW_area area, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1164    AW_area_management *aram= MAP_ARAM(area);
1165    if (!aram)
1166        return;
1167    aram->set_double_click_callback(this, f, cd1, cd2);
1168}
1169
1170void AW_window::get_event(AW_event *eventi) {
1171    *eventi = event;
1172}
1173
1174/***********************************************************************/
1175
1176static void AW_motionCB(Widget w, XtPointer aw_cb_struct, XEvent *ev) {
1177    AWUSE(w);
1178    AW_cb_struct *cbs = (AW_cb_struct *) aw_cb_struct;
1179
1180    cbs->aw->event.type = AW_Mouse_Drag;
1181    //  cbs->aw->event.button   = cbs->aw->event.button;
1182    cbs->aw->event.x = ev->xmotion.x;
1183    cbs->aw->event.y = ev->xmotion.y;
1184    cbs->aw->event.keycode = AW_KEY_NONE;
1185
1186    cbs->run_callback();
1187}
1188void AW_area_management::set_motion_callback(AW_window *aww, void (*f)(AW_window *,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1189    XtAddEventHandler(area, ButtonMotionMask, False,
1190            (XtEventHandler) AW_motionCB, (XtPointer) new AW_cb_struct(aww, f, cd1, cd2, "") );
1191}
1192void AW_window::set_motion_callback(AW_area area, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
1193    AW_area_management *aram= MAP_ARAM(area);
1194    if (!aram)
1195        return;
1196    aram->set_motion_callback(this, f, cd1, cd2);
1197}
1198
1199struct fallbacks {
1200    const char *fb;
1201    const char *awar;
1202    const char *init;
1203};
1204
1205static struct fallbacks aw_fb[] = {
1206// fallback awarname    init
1207
1208        { "FontList", "window/font", "8x13bold" }, { "background",
1209                "window/background", "grey" }, { "foreground",
1210                "window/foreground", "Black", }
1211, {0, "window/color_1", "red",}
1212, {0, "window/color_2", "green",}
1213, {0, "window/color_3", "blue",}
1214, {0, 0, 0}
1215};
1216
1217static const char *aw_awar_2_color[] = { "window/background",
1218        "window/foreground", "window/color_1", "window/color_2",
1219        "window/color_3", 0 };
1220
1221void AW_root::init_variables(AW_default database) {
1222
1223    application_database = database;
1224
1225    hash_table_for_variables = GBS_create_hash(1000, GB_MIND_CASE);
1226    hash_for_windows = GBS_create_hash(100, GB_MIND_CASE);
1227    prvt->action_hash = GBS_create_hash(1000, GB_MIND_CASE);
1228    int i;
1229    for (i=0; i<1000; i++) {
1230        if (aw_fb[i].awar == 0)
1231            break;
1232        awar_string(aw_fb[i].awar, aw_fb[i].init, application_database);
1233    }
1234    // PJ temporary site for vectorfont stuff
1235    vectorfont_lines =NULL; // font data not yet loaded
1236
1237    awar_float("vectorfont/userscale", 1.0, application_database); // ratio font point size to pixels
1238    awar_string("vectorfont/name", "lib/pictures/fontgfx.vfont",
1239            application_database); // name for default font in lib/pictures
1240    // from the filerequester
1241    awar_int("vectorfont/active", 1, application_database); // zoomtext-calls: call text or use vectorfont (1)
1242
1243    // this MIGHT lead to inconsistencies, as the validated data is in /name ---> worst case: reset
1244    aw_create_selection_box_awars(this, "vectorfont", GBS_global_string(
1245            "%s/lib/pictures", GB_getenvARBHOME()), ".vfont", vectorfont_name,
1246            application_database, true);
1247    awar("vectorfont/file_name")->add_callback( (AW_RCB0) aw_xfig_font_changefont_cb);
1248}
1249
1250void *AW_root::get_aw_var_struct(char *awar_name) {
1251    long vs;
1252    vs = (long)GBS_read_hash(hash_table_for_variables, awar_name);
1253    if (!vs) {
1254        AW_ERROR("AW_root::get_aw_var_struct: Variable %s not defined", awar_name);
1255    }
1256    return (void *)vs;
1257}
1258void *AW_root::get_aw_var_struct_no_error(char *awar_name) {
1259    long vs;
1260    vs = (long)GBS_read_hash(hash_table_for_variables, awar_name);
1261    return (void*)vs;
1262}
1263
1264static void aw_root_create_color_map(AW_root *root) {
1265    int i;
1266    XColor xcolor_returned, xcolor_exakt;
1267    GBDATA *gbd = (GBDATA*)root->application_database;
1268    p_global->color_table = (unsigned long *)GB_calloc(sizeof(unsigned long),AW_COLOR_MAX);
1269
1270    if (p_global->screen_depth == 1) { //Black and White Monitor
1271        unsigned long white= WhitePixelOfScreen( XtScreen(p_global->toplevel_widget) );
1272        unsigned long black= BlackPixelOfScreen( XtScreen(p_global->toplevel_widget) );
1273        p_global->foreground = black;
1274        p_global->background = white;
1275        for (i=0; i< AW_COLOR_MAX; i++) {
1276            p_global->color_table[i] = black;
1277        }
1278        p_global->color_table[AW_WINDOW_FG] = white;
1279        p_global->color_table[AW_WINDOW_C1] = white;
1280        p_global->color_table[AW_WINDOW_C2] = white;
1281        p_global->color_table[AW_WINDOW_C3] = white;
1282    } else { // Color monitor
1283        const char **awar_2_color;
1284        int color;
1285        for (color = 0, awar_2_color = aw_awar_2_color;
1286             *awar_2_color;
1287             awar_2_color++, color++)
1288        {
1289            const char *name_of_color = GB_read_char_pntr(GB_search(gbd, *awar_2_color, GB_FIND));
1290            if (XAllocNamedColor(p_global->display,p_global->colormap,name_of_color, &xcolor_returned,&xcolor_exakt) == 0) {
1291                fprintf(stderr,"XAllocColor failed: %s\n",name_of_color);
1292            }
1293            else {
1294                p_global->color_table[color] = xcolor_returned.pixel;
1295            }
1296        }
1297        p_global->foreground= BlackPixelOfScreen( XtScreen(p_global->toplevel_widget) );
1298        XtVaGetValues(p_global->toplevel_widget,XmNbackground,
1299        &p_global->background, NULL);
1300    }
1301    // AW_WINDOW_DRAG see init_devices
1302
1303}
1304
1305static void aw_message_forwarder(const char *msg) {
1306    aw_message(msg);
1307}
1308static void aw_message_forwarder_verbose(const char *msg) {
1309    fprintf(stderr, "ARB: %s\n", msg); // print to console as well
1310    aw_message(msg);
1311}
1312
1313static int aw_status_dummy(double val) {
1314    return aw_status(val);
1315}
1316
1317static int aw_status_dummy2(const char *val) {
1318    return aw_status((char *)val);
1319}
1320
1321void AW_root::init(const char *programmname, AW_BOOL no_exit) {
1322    // Initialisiert eine gesamte X-Anwendung
1323    int a = 0;
1324    int i;
1325    XFontStruct *fontstruct;
1326    char buffer[256];
1327    char *fallback_resources[100];
1328    p_r-> no_exit = no_exit;
1329
1330    for (i=0; i<1000; i++) {
1331        if (aw_fb[i].fb == 0)
1332            break;
1333        sprintf(buffer, "*%s: %s", aw_fb[i].fb, GB_read_char_pntr(GB_search(
1334                (GBDATA*)application_database, aw_fb[i].awar, GB_FIND)));
1335        fallback_resources[i] = strdup(buffer);
1336    }
1337    fallback_resources[i] = 0;
1338    GB_install_error_handler((gb_warning_func_type)aw_message_forwarder_verbose);
1339    GB_install_warning((gb_warning_func_type)aw_message_forwarder);
1340    GB_install_information((gb_information_func_type)0); // 0 means -> write to stdout only
1341
1342    GB_install_status((gb_status_func_type)aw_status_dummy);
1343    GB_install_status2((gb_status_func2_type)aw_status_dummy2);
1344
1345    // @@@ FIXME: the next line hangs if program runs inside debugger
1346    p_r->toplevel_widget = XtAppInitialize(&(p_r->context), programmname, NULL, 0,
1347            &a, /*&argc*/
1348            NULL, /*argv*/
1349            fallback_resources, NULL, 0);
1350
1351    for (i=0; i<1000 && fallback_resources[i]; i++) {
1352        free(fallback_resources[i]);
1353    }
1354
1355    p_r->display = XtDisplay(p_r->toplevel_widget);
1356
1357    if (p_r->display == NULL) {
1358        printf("cannot open display\n");
1359        exit(-1);
1360    }
1361    {
1362        GBDATA *gbd = (GBDATA*)application_database;
1363        const char *font = GB_read_char_pntr(GB_search(gbd, "window/font", GB_FIND));
1364        if ( !(fontstruct = XLoadQueryFont( p_r->display, font))) {
1365            if ( !(fontstruct = XLoadQueryFont( p_r->display, "fixed"))) {
1366                printf("can not load font\n");
1367                exit( -1);
1368            }
1369        }
1370    }
1371
1372    if (fontstruct->max_bounds.width == fontstruct->min_bounds.width) {
1373        font_width = fontstruct->max_bounds.width;
1374    } else {
1375        font_width = (fontstruct->min_bounds.width
1376                + fontstruct->max_bounds.width) / 2;
1377    }
1378
1379    font_height = fontstruct->max_bounds.ascent
1380            + fontstruct->max_bounds.descent;
1381    font_ascent = fontstruct->max_bounds.ascent;
1382
1383    p_r->fontlist = XmFontListCreate(fontstruct,XmSTRING_DEFAULT_CHARSET);
1384
1385    p_r->button_list = 0;
1386
1387    p_r->config_list = new AW_config_struct( "", AWM_ALL, NULL, "Programmer Name", "SH", NULL );
1388    p_r->last_config = p_r->config_list;
1389
1390    p_r->last_option_menu = p_r->current_option_menu = p_r->option_menu_list = NULL;
1391    p_r->last_toggle_field = p_r->toggle_field_list = NULL;
1392    p_r->last_selection_list = p_r->selection_list = NULL;
1393
1394    value_changed = AW_FALSE;
1395    y_correction_for_input_labels = 5;
1396    global_mask = AWM_ALL;
1397
1398    p_r->screen_depth = PlanesOfScreen( XtScreen(p_r->toplevel_widget) );
1399    if (p_r->screen_depth == 1) {
1400        color_mode = AW_MONO_COLOR;
1401    } else {
1402        color_mode = AW_RGB_COLOR;
1403    }
1404    p_r->colormap = DefaultColormapOfScreen( XtScreen(p_r->toplevel_widget) );
1405    p_r->clock_cursor = XCreateFontCursor(XtDisplay(p_r->toplevel_widget),XC_watch);
1406    p_r->question_cursor = XCreateFontCursor(XtDisplay(p_r->toplevel_widget),XC_question_arrow);
1407
1408    aw_root_create_color_map(this);
1409    aw_root_init_font(XtDisplay(p_r->toplevel_widget));
1410    aw_install_xkeys(XtDisplay(p_r->toplevel_widget));
1411
1412}
1413
1414/***********************************************************************/
1415void AW_window::_get_area_size(AW_area area, AW_rectangle *square) {
1416    AW_area_management *aram= MAP_ARAM(area);
1417    *square = aram->common->screen;
1418}
1419
1420/***********************************************************************/
1421
1422static void horizontal_scrollbar_redefinition_cb(class AW_root *aw_root,
1423        AW_CL cd1, AW_CL cd2) {
1424    AW_rectangle screen;
1425    AWUSE(aw_root);
1426
1427    char buffer[200];
1428    AW_window *aw = (AW_window *)cd1;
1429    Widget w = (Widget)cd2;
1430
1431    aw->_get_area_size(AW_MIDDLE_AREA, &screen);
1432
1433    sprintf(buffer, "window/%s/horizontal_page_increment",
1434            aw->window_defaults_name);
1435    XtVaSetValues(w, XmNpageIncrement, (int)((screen.r
1436            -aw->left_indent_of_horizontal_scrollbar)*(aw->get_root()->awar( buffer )->read_int()*0.01)), NULL);
1437
1438    sprintf(buffer, "window/%s/scroll_width_horizontal",
1439            aw->window_defaults_name);
1440    XtVaSetValues(w, XmNincrement, (int)(aw->get_root()->awar( buffer )->read_int()), NULL);
1441
1442    sprintf(buffer, "window/%s/scroll_delay_horizontal",
1443            aw->window_defaults_name);
1444    XtVaSetValues(w, XmNrepeatDelay, (int)(aw->get_root()->awar( buffer )->read_int()), NULL);
1445
1446}
1447
1448static void vertical_scrollbar_redefinition_cb(class AW_root *aw_root,
1449        AW_CL cd1, AW_CL cd2) {
1450    AW_rectangle screen;
1451    AWUSE(aw_root);
1452
1453    char buffer[200];
1454    AW_window *aw = (AW_window *)cd1;
1455    Widget w = (Widget)cd2;
1456
1457    aw->_get_area_size(AW_MIDDLE_AREA, &screen);
1458
1459    sprintf(buffer, "window/%s/vertical_page_increment",
1460            aw->window_defaults_name);
1461    XtVaSetValues(w, XmNpageIncrement, (int)((screen.b
1462            -aw->top_indent_of_vertical_scrollbar
1463            -aw->bottom_indent_of_vertical_scrollbar)*(aw->get_root()->awar( buffer )->read_int()*0.01)), NULL);
1464
1465    sprintf(buffer, "window/%s/scroll_width_vertical", aw->window_defaults_name);
1466    XtVaSetValues(w, XmNincrement, (int)(aw->get_root()->awar( buffer )->read_int()), NULL);
1467
1468    sprintf(buffer, "window/%s/scroll_delay_vertical", aw->window_defaults_name);
1469    XtVaSetValues(w, XmNrepeatDelay, (int)(aw->get_root()->awar( buffer )->read_int()), NULL);
1470}
1471
1472void AW_window::create_window_variables(void) {
1473
1474    char buffer[200];
1475    memset(buffer, 0, 200);
1476    sprintf(buffer, "window/%s/horizontal_page_increment", window_defaults_name);
1477    get_root()->awar_int(buffer, 50, get_root()->application_database);
1478    get_root()->awar( buffer)->add_callback(
1479            (AW_RCB)horizontal_scrollbar_redefinition_cb, (AW_CL)this,
1480            (AW_CL)p_w->scroll_bar_horizontal );
1481
1482    sprintf(buffer, "window/%s/vertical_page_increment", window_defaults_name);
1483    get_root()->awar_int(buffer, 50, get_root()->application_database);
1484    get_root()->awar( buffer)->add_callback( (AW_RCB)vertical_scrollbar_redefinition_cb,
1485            (AW_CL)this, (AW_CL)p_w->scroll_bar_vertical );
1486
1487    sprintf(buffer, "window/%s/scroll_delay_vertical", window_defaults_name);
1488    get_root()->awar_int(buffer, 20, get_root()->application_database);
1489    get_root()->awar( buffer)->add_callback( (AW_RCB)vertical_scrollbar_redefinition_cb,
1490            (AW_CL)this, (AW_CL)p_w->scroll_bar_vertical );
1491
1492    sprintf(buffer, "window/%s/scroll_delay_horizontal", window_defaults_name);
1493    get_root()->awar_int(buffer, 20, get_root()->application_database);
1494    get_root()->awar( buffer)->add_callback(
1495            (AW_RCB)horizontal_scrollbar_redefinition_cb, (AW_CL)this,
1496            (AW_CL)p_w->scroll_bar_horizontal );
1497
1498    sprintf(buffer, "window/%s/scroll_width_horizontal", window_defaults_name);
1499    get_root()->awar_int(buffer, 9, get_root()->application_database);
1500    get_root()->awar( buffer)->add_callback(
1501            (AW_RCB)horizontal_scrollbar_redefinition_cb, (AW_CL)this,
1502            (AW_CL)p_w->scroll_bar_horizontal );
1503
1504    sprintf(buffer, "window/%s/scroll_width_vertical", window_defaults_name);
1505    get_root()->awar_int(buffer, 20, get_root()->application_database);
1506    get_root()->awar( buffer)->add_callback( (AW_RCB)vertical_scrollbar_redefinition_cb,
1507            (AW_CL)this, (AW_CL)p_w->scroll_bar_vertical );
1508
1509}
1510
1511/***********************************************************************/
1512void AW_area_management::create_devices(AW_window *aww, AW_area ar) {
1513    AW_root *root =aww->get_root();
1514    common = new AW_common(aww,ar,XtDisplay(area),XtWindow(area),p_global->color_table,
1515            (unsigned int **)&aww->color_table, &aww->color_table_size );
1516}
1517
1518const char *AW_window::GC_to_RGB(AW_device *device, int gc, int& red,
1519        int& green, int& blue) {
1520    AW_common *common = device->common;
1521    AW_GC_Xm *gcm= AW_MAP_GC(gc);
1522    aw_assert(gcm);
1523    unsigned pixel = (unsigned short)(gcm->color);
1524    GB_ERROR error = 0;
1525    XColor query_color;
1526
1527    query_color.pixel = pixel;
1528    XQueryColor(p_global->display, p_global->colormap, &query_color);
1529    // @@@ FIXME: error handling!
1530
1531    red = query_color.red;
1532    green = query_color.green;
1533    blue = query_color.blue;
1534
1535    if (error) {
1536        red = green = blue = -1;
1537    }
1538    return error;
1539}
1540
1541// Converts GC to RGB float values to the range (0 - 1.0)
1542const char *AW_window::GC_to_RGB_float(AW_device *device, int gc, float& red,
1543        float& green, float& blue) {
1544    AW_common *common = device->common;
1545    AW_GC_Xm *gcm= AW_MAP_GC(gc);
1546    aw_assert(gcm);
1547    unsigned pixel = (unsigned short)(gcm->color);
1548    GB_ERROR error = 0;
1549    XColor query_color;
1550
1551    query_color.pixel = pixel;
1552
1553    XQueryColor(p_global->display, p_global->colormap, &query_color);
1554    // @@@ FIXME: error handling!
1555
1556    red = query_color.red/65535.0;
1557    green = query_color.green/65535.0;
1558    blue = query_color.blue/65535.0;
1559
1560    if (error) {
1561        red = green = blue = 1.0f;
1562    }
1563    return error;
1564}
1565
1566AW_color AW_window::alloc_named_data_color(int colnum, char *colorname) {
1567    if (!color_table_size) {
1568        color_table_size = AW_COLOR_MAX + colnum;
1569        color_table = (unsigned long *)malloc(sizeof(unsigned long)
1570                *color_table_size);
1571        memset((char *)color_table, -1, (size_t)(color_table_size
1572                *sizeof(unsigned long)));
1573    } else {
1574        if (colnum>=color_table_size) {
1575            color_table = (unsigned long *)realloc((char *)color_table, (8
1576                    + colnum)*sizeof(long)); // valgrinders : never free'd because AW_window never is free'd
1577            memset( (char *)(color_table+color_table_size), -1, (int)(8
1578                    + colnum - color_table_size) * sizeof(long));
1579            color_table_size = 8+colnum;
1580        }
1581    }
1582    XColor xcolor_returned, xcolor_exakt;
1583
1584    if (p_global->screen_depth == 1) { //Black and White Monitor
1585        static int col = 1;
1586        if (colnum == AW_DATA_BG) {
1587            col =1;
1588            if (strcmp(colorname, "white"))
1589                col *=-1;
1590        }
1591        if (col==1) {
1592            color_table[colnum] = WhitePixelOfScreen( XtScreen(p_global->toplevel_widget) );
1593        } else {
1594            color_table[colnum] = BlackPixelOfScreen( XtScreen(p_global->toplevel_widget) );
1595        }
1596        if (colnum == AW_DATA_BG)
1597            col *=-1;
1598    } else { // Color monitor
1599        if (color_table[colnum] !=(unsigned long)-1 ) {
1600            XFreeColors(p_global->display, p_global->colormap, &color_table[colnum],1,0);
1601        }
1602        if (XAllocNamedColor(p_global->display,p_global->colormap,colorname,
1603        &xcolor_returned,&xcolor_exakt) == 0) {
1604            sprintf(AW_ERROR_BUFFER, "XAllocColor failed: %s\n", colorname);
1605            aw_message();
1606            color_table[colnum] = (unsigned long)-1;
1607        } else {
1608            color_table[colnum] = xcolor_returned.pixel;
1609        }
1610    }
1611    if (colnum == AW_DATA_BG) {
1612        XtVaSetValues(p_w->areas[AW_MIDDLE_AREA]->area, 
1613        XmNbackground, color_table[colnum], NULL);
1614    }
1615    return (AW_color)colnum;
1616}
1617
1618void AW_window::create_devices(void) {
1619    unsigned long background_color;
1620    if (p_w->areas[AW_INFO_AREA]) {
1621        p_w->areas[AW_INFO_AREA]->create_devices(this, AW_INFO_AREA);
1622        XtVaGetValues(p_w->areas[AW_INFO_AREA]->area, 
1623        XmNbackground, &background_color, NULL);
1624        p_global->color_table[AW_WINDOW_DRAG] =
1625        background_color ^ p_global->color_table[AW_WINDOW_FG];
1626    }
1627    if (p_w->areas[AW_MIDDLE_AREA]) {
1628        p_w->areas[AW_MIDDLE_AREA]->create_devices(this, AW_MIDDLE_AREA);
1629    }
1630    if (p_w->areas[AW_BOTTOM_AREA]) {
1631        p_w->areas[AW_BOTTOM_AREA]->create_devices(this, AW_BOTTOM_AREA);
1632    }
1633}
1634
1635#if 0
1636// currently unused
1637void activate_question(AW_root *root,AW_window *aww) {
1638    p_global->help_active = 1;
1639    p_global->set_cursor( XtDisplay(p_global->toplevel_widget),
1640            XtWindow(p_aww(aww)->shell),
1641            p_global->question_cursor);
1642}
1643#endif
1644
1645void AW_help_entry_pressed(AW_window *aww) {
1646    AW_root *root = aww->get_root();
1647    p_global->help_active = 1;
1648}
1649
1650static void create_help_entry(AW_window *aww) {
1651    aww->insert_help_topic(0,
1652            "Click here and then on the questionable button/menu/...", "P", 0,
1653            AWM_ALL, (AW_CB)AW_help_entry_pressed, 0, 0);
1654}
1655
1656/****************************************************************************************************************************/
1657/****************************************************************************************************************************/
1658/****************************************************************************************************************************/
1659
1660const char *aw_str_2_label(const char *str, AW_window *aww) {
1661    static char buffer[256];
1662    static char *var_value = 0;
1663    static char *last_value = 0;
1664    static const char *last_pointer = 0;
1665
1666    if (str == last_pointer && strcmp(str, last_value) == 0) { // same as last
1667        str = 0; // return last result
1668    } else {
1669        free(last_value);
1670        last_value = strdup(str);
1671        last_pointer = str;
1672    }
1673
1674    if (str) {
1675        free(var_value);
1676        var_value = 0;
1677
1678        if (str[0] == '#') {
1679            const char *arbhome = GB_getenvARBHOME();
1680            sprintf(buffer, "%s/lib/pixmaps/%s", arbhome, str+1);
1681        } else {
1682            AW_awar *vs;
1683            if (strchr(str, '/') && (vs=aww->get_root()->awar_no_error(str))) {
1684                int wanted_len = aww->_at->length_of_buttons-2;
1685                if (wanted_len<1)
1686                    wanted_len = 1;
1687
1688                var_value = (char*)malloc(wanted_len+1);
1689                memset(var_value, 'y', wanted_len);
1690
1691                var_value[wanted_len] = 0;
1692            } else {
1693                if (strlen(str)<256)
1694                    sprintf(buffer, "%s", str);
1695                else
1696                    var_value = strdup(str);
1697            }
1698        }
1699    }
1700
1701    return var_value ? var_value : buffer;
1702}
1703
1704void AW_label_in_awar_list(AW_window *aww, Widget widget, const char *str) {
1705    AW_awar *vs =0;
1706    if (strchr(str, '/') && (vs=aww->get_root()->awar_no_error(str))) {
1707        char *var_value = vs->read_as_string();
1708        if (var_value) {
1709            aww->update_label((int*)widget, var_value);
1710        } else {
1711            AW_ERROR("AW_label_in_awar_list:: AWAR %s not found\n", str);
1712            aww->update_label((int*)widget, str);
1713        }
1714        free(var_value);
1715        AW_INSERT_BUTTON_IN_AWAR_LIST( vs,0, widget, AW_WIDGET_LABEL_FIELD, aww);
1716    }
1717}
1718/*********************************************************************************************/
1719/*********************************************************************************************/
1720/*********************************************************************************************/
1721
1722static void aw_window_avoid_destroy_cb(Widget, AW_window *,
1723        XmAnyCallbackStruct *) {
1724    aw_message("If YOU do not know what to answer, how should ARB know?\nPlease think again and answer the prompt!");
1725}
1726
1727static void aw_window_destroy_cb(Widget w, AW_window *aww,
1728        XmAnyCallbackStruct *cbs) {
1729    AWUSE(cbs);
1730    AWUSE(w);
1731    AW_root *root = aww->get_root();
1732    if ( (p_global->main_aww == aww) || !p_global->main_aww->get_show()) {
1733#ifdef NDEBUG
1734        if (aw_message("Are you sure to quit ??","YES,NO") ) return;
1735#endif
1736        exit(0);
1737    }
1738    aww->hide();
1739}
1740
1741static long aw_loop_get_window_geometry(const char *key, long val) {
1742    AWUSE(key);
1743    AW_window *aww = (AW_window *)val;
1744    short posx, posy;
1745
1746    AW_root *root = aww->get_root();
1747    unsigned short width, height, borderwidth;
1748
1749    XtVaGetValues( p_aww(aww)->shell , // bad hack
1750    XmNborderWidth, &borderwidth,
1751    XmNwidth, &width,
1752    XmNheight, &height,
1753    XmNx, &posx,
1754    XmNy, &posy,
1755    NULL);
1756    if ( p_aww(aww)->WM_top_offset != -1000) {
1757        posy -= p_aww(aww)->WM_top_offset;
1758    }
1759    posx -= p_aww(aww)->WM_left_offset;
1760
1761    if (posx<0)
1762        posx = 0;
1763    if (posy<0)
1764        posy = 0;
1765
1766    root->awar(aw_awar_name_width (aww))->write_int(width);
1767    root->awar(aw_awar_name_height(aww))->write_int(height);
1768    root->awar(aw_awar_name_posx (aww))->write_int(posx);
1769    root->awar(aw_awar_name_posy (aww))->write_int(posy);
1770
1771    return val;
1772}
1773
1774void aw_update_awar_window_geometry(AW_root *awr) {
1775    GBS_hash_do_loop(awr->hash_for_windows,
1776            (gb_hash_loop_type)aw_loop_get_window_geometry);
1777}
1778
1779static Widget aw_create_shell(AW_window *aww, AW_BOOL allow_resize,
1780        AW_BOOL allow_close, int width, int height, int posx, int posy) {
1781    AW_root *root = aww->get_root();
1782    Widget shell;
1783
1784    // set minimum window size to size provided by init
1785    if (width>aww->_at->max_x_size)
1786        aww->_at->max_x_size = width;
1787    if (height>aww->_at->max_y_size)
1788        aww->_at->max_y_size = height;
1789
1790    if ( !GBS_read_hash(root->hash_for_windows, aww->window_name)) {
1791        GBS_write_hash(root->hash_for_windows, aww->window_name, (long)aww);
1792        bool has_user_geometry = false;
1793
1794        const char *temp= aw_awar_name_width(aww);
1795        root->awar_int(temp, width);
1796        if (allow_resize) {
1797            int found_width = (int)root->awar(temp)->read_int();
1798            if (width != found_width) {
1799                has_user_geometry = true;
1800                width = found_width;
1801            }
1802        }
1803
1804        temp = aw_awar_name_height(aww);
1805        root->awar_int(temp, height);
1806        if (allow_resize) {
1807            int found_height = (int)root->awar(temp)->read_int();
1808            if (height != found_height) {
1809                has_user_geometry = true;
1810                height = found_height;
1811            }
1812        }
1813
1814        temp = aw_awar_name_posx(aww);
1815        root->awar_int(temp,posx)->set_minmax(0, 4000);
1816        // @@@ FIXME:  maximum should be set to current screen size minus some offset
1817        // to ensure that windows do not appear outside screen
1818        // same for posy below!
1819
1820        int found_posx = (int)root->awar(temp)->read_int();
1821        if (posx != found_posx) {
1822            has_user_geometry = true;
1823            posx = found_posx;
1824        }
1825
1826        temp = aw_awar_name_posy(aww);
1827        root->awar_int(temp,posy)->set_minmax(0, 3000);
1828        int found_posy = (int)root->awar(temp)->read_int();
1829        if (posy != found_posy) {
1830            has_user_geometry = true;
1831            posy = found_posy;
1832        }
1833
1834        if (has_user_geometry) {
1835#if defined(DEBUG)
1836            // printf("User geometry detected for window '%s'\n", aww->window_defaults_name);
1837#endif // DEBUG
1838            aww->recalc_size_at_show = 2; // keep user geometry (only if user size is smaller than default size, the latter is used)
1839        }
1840    }
1841
1842    if (allow_resize) {
1843        // create the window big enough to ensure that all widgets
1844        // are created in visible area (otherwise widget are crippled).
1845        // window will be resized later (on show)
1846
1847        width = 4000;
1848        height = 3000;
1849
1850        if (!aww->recalc_size_at_show)
1851            aww->recalc_size_at_show = 1;
1852    }
1853
1854    Widget father= p_global->toplevel_widget;
1855
1856    if (!p_global->main_widget || !p_global->main_aww->get_show()) {
1857
1858        shell = XtVaCreatePopupShell("editor", applicationShellWidgetClass,
1859                father, 
1860                XmNwidth, width, 
1861                XmNheight, height, 
1862                XmNx, posx, 
1863                XmNy, posy, 
1864                XmNtitle, aww->window_name, 
1865                XmNiconName, aww->window_name, 
1866                XmNkeyboardFocusPolicy, XmPOINTER, 
1867                XmNdeleteResponse, XmDO_NOTHING, 
1868                NULL);
1869    } else {
1870        shell = XtVaCreatePopupShell("transient", transientShellWidgetClass,
1871                father, 
1872                XmNwidth, width, 
1873                XmNheight, height, 
1874                XmNx, posx, 
1875                XmNy, posy, 
1876                XmNtitle, aww->window_name, 
1877                XmNiconName, aww->window_name, 
1878                XmNkeyboardFocusPolicy, XmPOINTER, 
1879                XmNdeleteResponse, XmDO_NOTHING, 
1880                NULL);
1881    }
1882    XtAddEventHandler(shell, EnterWindowMask, FALSE,
1883            (XtEventHandler)AW_root_focusCB, (XtPointer) aww->get_root());
1884
1885    if (!p_global->main_widget) {
1886        p_global->main_widget = shell;
1887        p_global->main_aww = aww;
1888    } else {
1889        if ( !p_global->main_aww->get_show()) { // now i am the root window
1890            p_global->main_widget = shell;
1891            p_global->main_aww = aww;
1892        }
1893    }
1894
1895    Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay(shell),
1896            (char*)"WM_DELETE_WINDOW", False);
1897
1898    if (allow_close == AW_FALSE) {
1899        XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW, (XtCallbackProc)aw_window_avoid_destroy_cb,(caddr_t)aww);
1900    } else if (!p_global->no_exit) {
1901        XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW, (XtCallbackProc)aw_window_destroy_cb,(caddr_t)aww);
1902    }
1903    return shell;
1904}
1905
1906void AW_window::set_icon(const char *icon, const char *default_icon) {
1907    int xpos, ypos;
1908    unsigned int xsize, ysize, borderwidth, depth;
1909    Window window, wroot;
1910    Widget w = p_w->shell;
1911    Display *dpy = XtDisplay(w);
1912    if (!icon)
1913        icon = "default";
1914    if (!default_icon)
1915        default_icon = "default";
1916    while (w) {
1917        if (XtIsWMShell(w))
1918            break;
1919        w = XtParent(w);
1920    }
1921    if (w == NULL)
1922        return;
1923    char path[2048], path2[2048];
1924
1925    const char *arbhome = GB_getenvARBHOME();
1926    sprintf( &path[0], "%s/lib/pixmaps/icons/%s.bitmap", arbhome, icon);
1927    sprintf( &path2[0], "%s/lib/pixmaps/icons/%s.bitmap", arbhome, default_icon);
1928    XtVaGetValues(w, XmNforeground, &p_global->foreground, NULL);
1929
1930    Pixmap pixmap = XmGetPixmap(XtScreen(w), path, p_global->foreground,
1931            p_global->background);
1932    if (pixmap == XmUNSPECIFIED_PIXMAP) {
1933        XmDestroyPixmap(XtScreen(w), pixmap);
1934        pixmap = XmGetPixmap(XtScreen(w), path2, p_global->foreground,
1935                p_global->background);
1936    }
1937
1938    if (pixmap == XmUNSPECIFIED_PIXMAP) {
1939        AW_ERROR("Cannot find pixmap '%s' or '%s'", path, path2);
1940        return;
1941    }
1942
1943    XSetWindowAttributes attr;
1944    XtVaGetValues(w, XmNiconWindow, &window, NULL);
1945
1946    if ( !window) {
1947        attr.background_pixmap = pixmap;
1948        if ( !XGetGeometry(dpy, pixmap, &wroot, &xpos, &ypos, &xsize, &ysize,
1949                &borderwidth, &depth) || (window = XCreateWindow(dpy, wroot, 0,
1950                0, xsize, ysize, 0, depth, CopyFromParent, CopyFromParent,
1951                CWBackPixmap, &attr)) == 0) {
1952            XtVaSetValues(w, XmNiconPixmap, pixmap, NULL);
1953            XmDestroyPixmap(XtScreen(w), pixmap);
1954            return;
1955        }
1956        XtVaSetValues(w, XmNiconWindow, window, NULL);
1957    }
1958    XSetWindowBackgroundPixmap(dpy, window, pixmap);
1959    XClearWindow(dpy, window);
1960    XmDestroyPixmap(XtScreen(w), pixmap);
1961
1962    return;
1963}
1964
1965static void aw_realize_widget(AW_window *aww) {
1966    if ( p_aww(aww)->areas[AW_INFO_AREA] && p_aww(aww)->areas[AW_INFO_AREA]->form) {
1967        XtManageChild(p_aww(aww)->areas[AW_INFO_AREA]->form);
1968    }
1969    if ( p_aww(aww)->areas[AW_MIDDLE_AREA] && p_aww(aww)->areas[AW_MIDDLE_AREA]->form) {
1970        XtManageChild(p_aww(aww)->areas[AW_MIDDLE_AREA]->form);
1971    }
1972    if ( p_aww(aww)->areas[AW_BOTTOM_AREA] && p_aww(aww)->areas[AW_BOTTOM_AREA]->form) {
1973        XtManageChild(p_aww(aww)->areas[AW_BOTTOM_AREA]->form);
1974    }
1975    XtRealizeWidget( p_aww(aww)->shell);
1976    p_aww(aww)->WM_top_offset = -1000;
1977}
1978
1979void AW_window_menu_modes::init(AW_root *root_in, const char *wid,
1980        const char *windowname, int width, int height) {
1981    Widget main_window;
1982    Widget help_popup;
1983    Widget help_label;
1984    Widget separator;
1985    Widget form1;
1986    Widget form2;
1987    //Widget frame;
1988    const char *help_button = "HELP";
1989    const char *help_mnemonic = "H";
1990
1991#if defined(DUMP_MENU_LIST)
1992    initMenuListing(windowname);
1993#endif // DUMP_MENU_LIST
1994    root = root_in; // for makro
1995    window_name = strdup(windowname);
1996    window_defaults_name = GBS_string_2_key(wid);
1997
1998    int posx = 50;
1999    int posy = 50;
2000
2001    p_w->shell= aw_create_shell(this, AW_TRUE, AW_TRUE, width, height, posx,
2002            posy);
2003
2004    main_window = XtVaCreateManagedWidget("mainWindow1",
2005            xmMainWindowWidgetClass, p_w->shell, 
2006            NULL);
2007
2008    p_w->menu_bar[0] = XtVaCreateManagedWidget("menu1", xmRowColumnWidgetClass,
2009            main_window, 
2010            XmNrowColumnType, XmMENU_BAR, 
2011            NULL);
2012
2013    // create shell for help-cascade
2014    help_popup = XtVaCreatePopupShell("menu_shell", xmMenuShellWidgetClass,
2015            p_w->menu_bar[0], 
2016            XmNwidth, 1, 
2017            XmNheight, 1, 
2018            XmNallowShellResize, AW_TRUE, 
2019            XmNoverrideRedirect, AW_TRUE, 
2020            NULL);
2021
2022    //create row column in Pull-Down shell
2023    p_w->help_pull_down = XtVaCreateWidget("menu_row_column",
2024            xmRowColumnWidgetClass, help_popup, 
2025            XmNrowColumnType, XmMENU_PULLDOWN, 
2026            NULL);
2027
2028    // create HELP-label in menu bar
2029    help_label = XtVaCreateManagedWidget("menu1_top_b1",
2030            xmCascadeButtonWidgetClass, p_w->menu_bar[0], 
2031            RES_CONVERT( XmNlabelString, help_button ),
2032                                          RES_CONVERT( XmNmnemonic, help_mnemonic ), 
2033                                          XmNsubMenuId, p_w->help_pull_down, NULL );
2034    XtVaSetValues(p_w->menu_bar[0], XmNmenuHelpWidget, help_label, NULL);
2035    //insert help_label to button_list
2036    AW_INSERT_BUTTON_IN_SENS_LIST ( root, help_button, AWM_ALL, help_label );
2037
2038    form1 = XtVaCreateManagedWidget( "form1",
2039    xmFormWidgetClass,
2040    main_window,
2041    // XmNwidth, width,
2042    // XmNheight, height,
2043    XmNresizePolicy, XmRESIZE_NONE,
2044    // XmNx, 0,
2045    // XmNy, 0,
2046    NULL);
2047
2048    p_w->mode_area = XtVaCreateManagedWidget( "mode area",
2049    xmDrawingAreaWidgetClass,
2050    form1,
2051    XmNresizePolicy, XmRESIZE_NONE,
2052    XmNwidth, 38,
2053    XmNheight, height,
2054    XmNx, 0,
2055    XmNy, 0,
2056    XmNleftOffset, 0,
2057    XmNtopOffset, 0,
2058    XmNbottomAttachment, XmATTACH_FORM,
2059    XmNleftAttachment, XmATTACH_POSITION,
2060    XmNtopAttachment, XmATTACH_POSITION,
2061    XmNmarginHeight, 2,
2062    XmNmarginWidth, 1,
2063    NULL);
2064
2065    separator = XtVaCreateManagedWidget( "separator",
2066    xmSeparatorWidgetClass,
2067    form1,
2068    XmNx, 37,
2069    XmNshadowThickness, 4,
2070    XmNorientation, XmVERTICAL,
2071    XmNbottomAttachment, XmATTACH_FORM,
2072    XmNtopAttachment, XmATTACH_FORM,
2073    XmNleftAttachment, XmATTACH_NONE,
2074    XmNleftWidget, NULL,
2075    XmNrightAttachment, XmATTACH_NONE,
2076    XmNleftOffset, 70,
2077    XmNleftPosition, 0,
2078    NULL);
2079
2080    form2 = XtVaCreateManagedWidget( "form2",
2081    xmFormWidgetClass,
2082    form1,
2083    XmNwidth, width,
2084    XmNheight, height,
2085    XmNtopOffset, 0,
2086    XmNbottomOffset, 0,
2087    XmNleftOffset, 0,
2088    XmNrightOffset, 0,
2089    XmNrightAttachment, XmATTACH_FORM,
2090    XmNbottomAttachment, XmATTACH_FORM,
2091    XmNleftAttachment, XmATTACH_WIDGET,
2092    XmNleftWidget, separator,
2093    XmNtopAttachment, XmATTACH_POSITION,
2094    XmNresizePolicy, XmRESIZE_NONE,
2095    XmNx, 0,
2096    XmNy, 0,
2097    NULL);
2098    p_w->areas[AW_INFO_AREA] =
2099    new AW_area_management(root, form2, XtVaCreateManagedWidget( "info_area",
2100            xmDrawingAreaWidgetClass,
2101            form2,
2102            XmNheight, 0,
2103            XmNbottomAttachment, XmATTACH_NONE,
2104            XmNtopAttachment, XmATTACH_FORM,
2105            XmNleftAttachment, XmATTACH_FORM,
2106            XmNrightAttachment, XmATTACH_FORM,
2107            XmNmarginHeight, 2,
2108            XmNmarginWidth, 2,
2109            NULL));
2110
2111    p_w->areas[AW_BOTTOM_AREA] =
2112    new AW_area_management(root, form2, XtVaCreateManagedWidget( "bottom_area",
2113            xmDrawingAreaWidgetClass,
2114            form2,
2115            XmNheight, 0,
2116            XmNbottomAttachment, XmATTACH_FORM,
2117            XmNtopAttachment, XmATTACH_NONE,
2118            XmNleftAttachment, XmATTACH_FORM,
2119            XmNrightAttachment, XmATTACH_FORM,
2120            NULL));
2121
2122    p_w->scroll_bar_horizontal = XtVaCreateManagedWidget( "scroll_bar_horizontal",
2123    xmScrollBarWidgetClass,
2124    form2,
2125    XmNheight, 15,
2126    XmNminimum, 0,
2127    XmNmaximum, AW_SCROLL_MAX,
2128    XmNincrement, 10,
2129    XmNsliderSize, AW_SCROLL_MAX,
2130    XmNrightAttachment, XmATTACH_FORM,
2131    XmNbottomAttachment, XmATTACH_FORM,
2132    XmNbottomOffset, 0,
2133    XmNleftAttachment, XmATTACH_FORM,
2134    XmNtopAttachment, XmATTACH_NONE,
2135    XmNorientation, XmHORIZONTAL,
2136    XmNrightOffset, 18,
2137    NULL );
2138
2139    p_w->scroll_bar_vertical = XtVaCreateManagedWidget( "scroll_bar_vertical",
2140    xmScrollBarWidgetClass,
2141    form2,
2142    XmNwidth, 15,
2143    XmNminimum, 0,
2144    XmNmaximum, AW_SCROLL_MAX,
2145    XmNincrement, 10,
2146    XmNsliderSize, AW_SCROLL_MAX,
2147    XmNrightAttachment, XmATTACH_FORM,
2148    XmNbottomAttachment, XmATTACH_WIDGET,
2149    XmNbottomWidget, p_w->scroll_bar_horizontal,
2150    XmNbottomOffset, 3,
2151    XmNleftOffset, 3,
2152    XmNrightOffset, 3,
2153    XmNleftAttachment, XmATTACH_NONE,
2154    XmNtopAttachment, XmATTACH_WIDGET,
2155    XmNtopWidget, INFO_WIDGET,
2156    NULL );
2157
2158    p_w->frame = XtVaCreateManagedWidget( "draw_area",
2159    xmFrameWidgetClass,
2160    form2,
2161    XmNshadowType, XmSHADOW_IN,
2162    XmNshadowThickness, 2,
2163    XmNleftOffset, 3,
2164    XmNtopOffset, 3,
2165    XmNbottomOffset, 3,
2166    XmNrightOffset, 3,
2167    XmNbottomAttachment, XmATTACH_WIDGET,
2168    XmNbottomWidget, p_w->scroll_bar_horizontal,
2169    XmNtopAttachment, XmATTACH_FORM,
2170    XmNtopOffset, 0,
2171    XmNleftAttachment, XmATTACH_FORM,
2172    XmNrightAttachment, XmATTACH_WIDGET,
2173    XmNrightWidget, p_w->scroll_bar_vertical,
2174    NULL);
2175
2176    p_w->areas[AW_MIDDLE_AREA] =
2177    new AW_area_management(root,p_w->frame, XtVaCreateManagedWidget( "draw area",
2178            xmDrawingAreaWidgetClass,
2179            p_w->frame,
2180            XmNmarginHeight, 0,
2181            XmNmarginWidth, 0,
2182            NULL));
2183
2184    XmMainWindowSetAreas( main_window, p_w->menu_bar[0], (Widget) NULL, (Widget) NULL, (Widget) NULL, form1 );
2185
2186    aw_realize_widget(this);
2187
2188    create_devices();
2189    create_help_entry(this);
2190    create_window_variables();
2191    set_icon(window_defaults_name);
2192}
2193
2194void AW_window_menu::init(AW_root *root_in, const char *wid,
2195        const char *windowname, int width, int height) {
2196    Widget main_window;
2197    Widget help_popup;
2198    Widget help_label;
2199    Widget separator;
2200    Widget form1;
2201    Widget form2;
2202    //Widget frame;
2203    const char *help_button = "HELP";
2204    const char *help_mnemonic = "H";
2205
2206#if defined(DUMP_MENU_LIST)
2207    initMenuListing(windowname);
2208#endif // DUMP_MENU_LIST
2209    root = root_in; // for makro
2210    window_name = strdup(windowname);
2211    window_defaults_name = GBS_string_2_key(wid);
2212
2213    int posx = 50;
2214    int posy = 50;
2215
2216    p_w->shell= aw_create_shell(this, AW_TRUE, AW_TRUE, width, height, posx,
2217            posy);
2218
2219    main_window = XtVaCreateManagedWidget("mainWindow1",
2220            xmMainWindowWidgetClass, p_w->shell, 
2221            NULL);
2222
2223    p_w->menu_bar[0] = XtVaCreateManagedWidget("menu1", xmRowColumnWidgetClass,
2224            main_window, 
2225            XmNrowColumnType, XmMENU_BAR, 
2226            NULL);
2227
2228    // create shell for help-cascade
2229    help_popup = XtVaCreatePopupShell("menu_shell", xmMenuShellWidgetClass,
2230            p_w->menu_bar[0], 
2231            XmNwidth, 1, 
2232            XmNheight, 1, 
2233            XmNallowShellResize, AW_TRUE, 
2234            XmNoverrideRedirect, AW_TRUE, 
2235            NULL);
2236
2237    //create row column in Pull-Down shell
2238    p_w->help_pull_down = XtVaCreateWidget("menu_row_column",
2239            xmRowColumnWidgetClass, help_popup, 
2240            XmNrowColumnType, XmMENU_PULLDOWN, 
2241            NULL);
2242
2243    // create HELP-label in menu bar
2244    help_label = XtVaCreateManagedWidget("menu1_top_b1",
2245            xmCascadeButtonWidgetClass, p_w->menu_bar[0], 
2246            RES_CONVERT( XmNlabelString, help_button ),
2247                                          RES_CONVERT( XmNmnemonic, help_mnemonic ), 
2248                                          XmNsubMenuId, p_w->help_pull_down, NULL );
2249    XtVaSetValues(p_w->menu_bar[0], XmNmenuHelpWidget, help_label, NULL);
2250    //insert help_label to button_list
2251    AW_INSERT_BUTTON_IN_SENS_LIST ( root, help_button, AWM_ALL, help_label );
2252
2253    form1 = XtVaCreateManagedWidget( "form1",
2254    xmFormWidgetClass,
2255    main_window,
2256    // XmNwidth, width,
2257    // XmNheight, height,
2258    XmNresizePolicy, XmRESIZE_NONE,
2259    // XmNx, 0,
2260    // XmNy, 0,
2261    NULL);
2262
2263    p_w->mode_area = XtVaCreateManagedWidget( "mode area",
2264    xmDrawingAreaWidgetClass,
2265    form1,
2266    XmNresizePolicy, XmRESIZE_NONE,
2267    XmNwidth, 17,
2268    XmNheight, height,
2269    XmNx, 0,
2270    XmNy, 0,
2271    XmNleftOffset, 0,
2272    XmNtopOffset, 0,
2273    XmNbottomAttachment, XmATTACH_FORM,
2274    XmNleftAttachment, XmATTACH_POSITION,
2275    XmNtopAttachment, XmATTACH_POSITION,
2276    XmNmarginHeight, 2,
2277    XmNmarginWidth, 1,
2278    NULL);
2279
2280    separator = p_w->mode_area;
2281
2282    form2 = XtVaCreateManagedWidget( "form2",
2283    xmFormWidgetClass,
2284    form1,
2285    XmNwidth, width,
2286    XmNheight, height,
2287    XmNtopOffset, 0,
2288    XmNbottomOffset, 0,
2289    XmNleftOffset, 0,
2290    XmNrightOffset, 0,
2291    XmNrightAttachment, XmATTACH_FORM,
2292    XmNbottomAttachment, XmATTACH_FORM,
2293    XmNleftAttachment, XmATTACH_WIDGET,
2294    XmNleftWidget, separator,
2295    XmNtopAttachment, XmATTACH_POSITION,
2296    XmNresizePolicy, XmRESIZE_NONE,
2297    XmNx, 0,
2298    XmNy, 0,
2299    NULL);
2300    p_w->areas[AW_INFO_AREA] =
2301    new AW_area_management(root,form2, XtVaCreateManagedWidget( "info_area",
2302            xmDrawingAreaWidgetClass,
2303            form2,
2304            XmNheight, 0,
2305            XmNbottomAttachment, XmATTACH_NONE,
2306            XmNtopAttachment, XmATTACH_FORM,
2307            XmNleftAttachment, XmATTACH_FORM,
2308            XmNrightAttachment, XmATTACH_FORM,
2309            XmNmarginHeight, 2,
2310            XmNmarginWidth, 2,
2311            NULL));
2312
2313    p_w->areas[AW_BOTTOM_AREA] =
2314    new AW_area_management(root,form2, XtVaCreateManagedWidget( "bottom_area",
2315            xmDrawingAreaWidgetClass,
2316            form2,
2317            XmNheight, 0,
2318            XmNbottomAttachment, XmATTACH_FORM,
2319            XmNtopAttachment, XmATTACH_NONE,
2320            XmNleftAttachment, XmATTACH_FORM,
2321            XmNrightAttachment, XmATTACH_FORM,
2322            NULL));
2323
2324    p_w->scroll_bar_horizontal = XtVaCreateManagedWidget( "scroll_bar_horizontal",
2325    xmScrollBarWidgetClass,
2326    form2,
2327    XmNheight, 15,
2328    XmNminimum, 0,
2329    XmNmaximum, AW_SCROLL_MAX,
2330    XmNincrement, 10,
2331    XmNsliderSize, AW_SCROLL_MAX,
2332    XmNrightAttachment, XmATTACH_FORM,
2333    XmNbottomAttachment, XmATTACH_FORM,
2334    XmNbottomOffset, 0,
2335    XmNleftAttachment, XmATTACH_FORM,
2336    XmNtopAttachment, XmATTACH_NONE,
2337    XmNorientation, XmHORIZONTAL,
2338    XmNrightOffset, 18,
2339    NULL );
2340
2341    p_w->scroll_bar_vertical = XtVaCreateManagedWidget( "scroll_bar_vertical",
2342    xmScrollBarWidgetClass,
2343    form2,
2344    XmNwidth, 15,
2345    XmNminimum, 0,
2346    XmNmaximum, AW_SCROLL_MAX,
2347    XmNincrement, 10,
2348    XmNsliderSize, AW_SCROLL_MAX,
2349    XmNrightAttachment, XmATTACH_FORM,
2350    XmNbottomAttachment, XmATTACH_WIDGET,
2351    XmNbottomWidget, p_w->scroll_bar_horizontal,
2352    XmNbottomOffset, 3,
2353    XmNleftOffset, 3,
2354    XmNrightOffset, 3,
2355    XmNleftAttachment, XmATTACH_NONE,
2356    XmNtopAttachment, XmATTACH_WIDGET,
2357    XmNtopWidget, INFO_WIDGET,
2358    NULL );
2359
2360    p_w->frame = XtVaCreateManagedWidget( "draw_area",
2361    xmFrameWidgetClass,
2362    form2,
2363    XmNshadowType, XmSHADOW_IN,
2364    XmNshadowThickness, 2,
2365    XmNleftOffset, 3,
2366    XmNtopOffset, 3,
2367    XmNbottomOffset, 3,
2368    XmNrightOffset, 3,
2369    XmNbottomAttachment, XmATTACH_WIDGET,
2370    XmNbottomWidget, p_w->scroll_bar_horizontal,
2371    XmNtopAttachment, XmATTACH_FORM,
2372    XmNtopOffset, 0,
2373    XmNleftAttachment, XmATTACH_FORM,
2374    XmNrightAttachment, XmATTACH_WIDGET,
2375    XmNrightWidget, p_w->scroll_bar_vertical,
2376    NULL);
2377
2378    p_w->areas[AW_MIDDLE_AREA] =
2379    new AW_area_management(root,p_w->frame, XtVaCreateManagedWidget( "draw area",
2380            xmDrawingAreaWidgetClass,
2381            p_w->frame,
2382            XmNmarginHeight, 0,
2383            XmNmarginWidth, 0,
2384            NULL));
2385
2386    XmMainWindowSetAreas( main_window, p_w->menu_bar[0], (Widget) NULL,
2387    (Widget) NULL, (Widget) NULL, form1 );
2388
2389    aw_realize_widget(this);
2390
2391    create_devices();
2392    create_help_entry(this);
2393    create_window_variables();
2394    set_icon(window_defaults_name);
2395}
2396
2397void AW_window_simple::init(AW_root *root_in, const char *wid,
2398        const char *windowname) {
2399    //Arg args[10];
2400    root = root_in; // for makro
2401
2402    int width = 100; // this is only the minimum size!
2403    int height = 100;
2404    int posx = 50;
2405    int posy = 50;
2406
2407    window_name = strdup(windowname);
2408    window_defaults_name = GBS_string_2_key(wid);
2409
2410    p_w->shell= aw_create_shell(this, AW_TRUE, AW_TRUE, width, height, posx,
2411            posy);
2412
2413    // add this to disable resize or maximize in simple dialogs (avoids broken layouts)
2414    // XtVaSetValues(p_w->shell, XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
2415    //         NULL);
2416
2417    Widget form1 = XtVaCreateManagedWidget("forms", xmFormWidgetClass,
2418            p_w->shell, 
2419            NULL);
2420
2421    p_w->areas[AW_INFO_AREA] = new AW_area_management(root,form1, XtVaCreateManagedWidget( "info_area",
2422                    xmDrawingAreaWidgetClass,
2423                    form1,
2424                    XmNbottomAttachment, XmATTACH_FORM,
2425                    XmNtopAttachment, XmATTACH_FORM,
2426                    XmNleftAttachment, XmATTACH_FORM,
2427                    XmNrightAttachment, XmATTACH_FORM,
2428                    XmNmarginHeight, 2,
2429                    XmNmarginWidth, 2,
2430                    NULL));
2431
2432    aw_realize_widget(this);
2433    create_devices();
2434    set_icon(window_defaults_name);
2435}
2436
2437void AW_window_simple_menu::init(AW_root *root_in, const char *wid,
2438        const char *windowname) {
2439    //  Arg args[10];
2440
2441    root = root_in; // for makro
2442
2443    const char *help_button = "HELP";
2444    const char *help_mnemonic = "H";
2445    window_name = strdup(windowname);
2446    window_defaults_name = GBS_string_2_key(wid);
2447
2448    int width = 100;
2449    int height = 100;
2450    int posx = 50;
2451    int posy = 50;
2452
2453    p_w->shell= aw_create_shell(this, AW_TRUE, AW_TRUE, width, height, posx,
2454            posy);
2455
2456    Widget main_window;
2457    Widget help_popup;
2458    Widget help_label;
2459    Widget form1;
2460
2461    main_window = XtVaCreateManagedWidget("mainWindow1",
2462            xmMainWindowWidgetClass, p_w->shell, 
2463            NULL);
2464
2465    p_w->menu_bar[0] = XtVaCreateManagedWidget("menu1", xmRowColumnWidgetClass,
2466            main_window, 
2467            XmNrowColumnType, XmMENU_BAR, 
2468            NULL);
2469
2470    // create shell for help-cascade
2471    help_popup = XtVaCreatePopupShell("menu_shell", xmMenuShellWidgetClass,
2472            p_w->menu_bar[0], 
2473            XmNwidth, 1, 
2474            XmNheight, 1, 
2475            XmNallowShellResize, AW_TRUE, 
2476            XmNoverrideRedirect, AW_TRUE, 
2477            NULL);
2478
2479    //create row column in Pull-Down shell
2480    p_w->help_pull_down = XtVaCreateWidget("menu_row_column",
2481            xmRowColumnWidgetClass, help_popup, 
2482            XmNrowColumnType, XmMENU_PULLDOWN, 
2483            NULL);
2484
2485    // create HELP-label in menu bar
2486    help_label = XtVaCreateManagedWidget("menu1_top_b1",
2487            xmCascadeButtonWidgetClass, p_w->menu_bar[0], 
2488            RES_CONVERT( XmNlabelString, help_button ),
2489                                          RES_CONVERT( XmNmnemonic, help_mnemonic ), 
2490                                          XmNsubMenuId, p_w->help_pull_down, NULL );
2491    XtVaSetValues(p_w->menu_bar[0], XmNmenuHelpWidget, help_label, NULL);
2492    //insert help_label to button_list
2493    AW_INSERT_BUTTON_IN_SENS_LIST ( root, help_button, AWM_ALL, help_label );
2494
2495    form1 = XtVaCreateManagedWidget( "form1",
2496    xmFormWidgetClass,
2497    main_window,
2498    XmNtopOffset, 10,
2499    XmNresizePolicy, XmRESIZE_NONE,
2500    NULL);
2501
2502    p_w->areas[AW_INFO_AREA] =
2503    new AW_area_management(root, form1, XtVaCreateManagedWidget( "info_area",
2504            xmDrawingAreaWidgetClass,
2505            form1,
2506            XmNbottomAttachment, XmATTACH_FORM,
2507            XmNtopAttachment, XmATTACH_FORM,
2508            XmNleftAttachment, XmATTACH_FORM,
2509            XmNrightAttachment, XmATTACH_FORM,
2510            XmNmarginHeight, 2,
2511            XmNmarginWidth, 2,
2512            NULL));
2513
2514    aw_realize_widget(this );
2515
2516    create_help_entry(this);
2517    create_devices();
2518    set_icon(window_defaults_name);
2519}
2520
2521void AW_window_message::init(AW_root *root_in, const char *windowname,
2522        bool allow_close) {
2523    //  Arg args[10];
2524
2525    root = root_in; // for makro
2526
2527    int width = 100;
2528    int height = 100;
2529    int posx = 50;
2530    int posy = 50;
2531
2532    window_name = strdup(windowname);
2533    window_defaults_name = GBS_string_2_key(window_name);
2534
2535    // create shell for message box
2536    p_w->shell= aw_create_shell(this, AW_TRUE, allow_close, width, height,
2537            posx, posy);
2538
2539    // disable resize or maximize in simple dialogs (avoids broken layouts)
2540    XtVaSetValues(p_w->shell, XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
2541            NULL);
2542
2543    p_w->areas[AW_INFO_AREA] = new AW_area_management(root,p_w->shell, XtVaCreateManagedWidget( "info_area",
2544                    xmDrawingAreaWidgetClass,
2545                    p_w->shell,
2546                    XmNheight, 0,
2547                    XmNbottomAttachment, XmATTACH_NONE,
2548                    XmNtopAttachment, XmATTACH_FORM,
2549                    XmNleftAttachment, XmATTACH_FORM,
2550                    XmNrightAttachment, XmATTACH_FORM,
2551                    NULL));
2552
2553    aw_realize_widget(this);
2554    //  create_devices();
2555    set_icon("message");
2556}
2557
2558void AW_window::set_info_area_height(int height) {
2559    XtVaSetValues(INFO_WIDGET, XmNheight, height, NULL);
2560    XtVaSetValues(p_w->frame, XmNtopOffset, height, NULL);
2561}
2562
2563void AW_window::set_bottom_area_height(int height) {
2564    XtVaSetValues(BOTTOM_WIDGET, XmNheight, height, NULL);
2565    XtVaSetValues(p_w->scroll_bar_horizontal, XmNbottomOffset, (int)height,
2566            NULL);
2567}
2568
2569void AW_window::set_vertical_scrollbar_top_indent(int indent) {
2570    XtVaSetValues(p_w->scroll_bar_vertical, XmNtopOffset, (int)indent, NULL);
2571    top_indent_of_vertical_scrollbar = indent;
2572}
2573
2574void AW_window::set_vertical_scrollbar_bottom_indent(int indent) {
2575    XtVaSetValues(p_w->scroll_bar_vertical, XmNbottomOffset, (int)(3+indent),
2576            NULL);
2577    bottom_indent_of_vertical_scrollbar = indent;
2578}
2579
2580void AW_root::set_sensitive(AW_active mask) {
2581    AW_buttons_struct *list;
2582
2583    global_mask = mask;
2584    for (list = p_r->button_list; list; list = list->next) {
2585        if (!list->button)
2586            continue;
2587        if (list->mask & mask) {
2588            XtSetSensitive(list->button, True);
2589        } else {
2590            XtSetSensitive(list->button, False);
2591
2592        }
2593    }
2594}
2595
2596void AW_root::set_sensitive(const char *id) {
2597    AW_buttons_struct *list= p_r->button_list;
2598
2599    do {
2600        if (list->id && !strcmp(list->id, id) ) {
2601            XtSetSensitive(list->button, True);
2602        }
2603        list = list->next;
2604    } while (list != NULL);
2605
2606}
2607
2608void AW_root::set_insensitive(const char *id) {
2609    AW_buttons_struct *list= p_r->button_list;
2610
2611    do {
2612        if (list->id && !strcmp(list->id, id) ) {
2613            XtSetSensitive(list->button, False);
2614        }
2615        list = list->next;
2616    } while (list != NULL);
2617
2618}
2619
2620void AW_window::select_mode(int mode) {
2621    if (mode >= p_w->number_of_modes)
2622        return;
2623
2624    Widget oldwidget = p_w->modes_widgets[p_w->selected_mode];
2625    p_w->selected_mode = mode;
2626    Widget widget = p_w->modes_widgets[p_w->selected_mode];
2627    XtVaSetValues(oldwidget, XmNbackground, p_global->background, NULL);
2628    XtVaSetValues(widget, XmNbackground, p_global->foreground, NULL);
2629}
2630
2631static void aw_mode_callback(AW_window *aww, long mode, AW_cb_struct *cbs) {
2632    aww->select_mode((int)mode);
2633    cbs->run_callback();
2634}
2635
2636#define MODE_BUTTON_OFFSET 34
2637inline int yoffset_for_mode_button(int button_number) {
2638    return button_number*MODE_BUTTON_OFFSET + (button_number/4)*8 + 2;
2639}
2640
2641int AW_window::create_mode(const char *mode_id, const char *pixmap,
2642        const char *helpText, AW_active Mask, void (*f)(AW_window*, AW_CL, AW_CL), AW_CL cd1, AW_CL cd2) {
2643    Widget button;
2644
2645    TuneBackground(p_w->mode_area, TUNE_BUTTON); // set background color for mode-buttons
2646
2647    char path[256];
2648    memset(path, 0, 256);
2649    sprintf(path, "%s/lib/pixmaps/%s", GB_getenvARBHOME(), pixmap);
2650    int y = yoffset_for_mode_button(p_w->number_of_modes);
2651    button = XtVaCreateManagedWidget("", xmPushButtonWidgetClass,
2652            p_w->mode_area, 
2653            XmNx, 0, 
2654            XmNy, y, 
2655            XmNlabelType, XmPIXMAP, 
2656            XmNshadowThickness, 1, 
2657            XmNbackground, _at->background_color, 
2658            NULL);
2659    XtVaSetValues(button, RES_CONVERT( XmNlabelPixmap, path ),NULL );
2660    XtVaGetValues(button,XmNforeground, &p_global->foreground, NULL);
2661
2662    AW_cb_struct *cbs = new AW_cb_struct(this, f, cd1, cd2, 0);
2663    AW_cb_struct *cb2 = new AW_cb_struct(this, (AW_CB)aw_mode_callback, (AW_CL)p_w->number_of_modes, (AW_CL)cbs, helpText, cbs);
2664    XtAddCallback(button, XmNactivateCallback,
2665    (XtCallbackProc) AW_server_callback,
2666    (XtPointer) cb2);
2667
2668    if (!p_w->modes_f_callbacks) {
2669        p_w->modes_f_callbacks = (AW_cb_struct **)GB_calloc(sizeof(AW_cb_struct*),AW_NUMBER_OF_F_KEYS); // valgrinders : never free'd because AW_window never is free'd
2670    }
2671    if (!p_w->modes_widgets) {
2672        p_w->modes_widgets = (Widget *)GB_calloc(sizeof(Widget),AW_NUMBER_OF_F_KEYS);
2673    }
2674    if (p_w->number_of_modes<AW_NUMBER_OF_F_KEYS) {
2675        p_w->modes_f_callbacks[p_w->number_of_modes] = cb2;
2676        p_w->modes_widgets[p_w->number_of_modes] = button;
2677    }
2678
2679    AW_INSERT_BUTTON_IN_SENS_LIST ( root, mode_id, Mask, button );
2680    p_w->number_of_modes++;
2681
2682    int ynext = yoffset_for_mode_button(p_w->number_of_modes);
2683    if (ynext> _at->max_y_size) _at->max_y_size = ynext;
2684
2685    return p_w->number_of_modes;
2686}
2687
2688// ------------------------
2689//      Hotkey Checking
2690// ------------------------
2691
2692#ifdef DEBUG
2693
2694#define MAX_DEEP_TO_TEST     10
2695#define MAX_MENU_ITEMS_TO_TEST   50
2696
2697static char *TD_menu_name = 0;
2698static char TD_mnemonics[MAX_DEEP_TO_TEST][MAX_MENU_ITEMS_TO_TEST];
2699static int TD_topics[MAX_DEEP_TO_TEST];
2700
2701struct SearchPossibilities {
2702    char *menu_topic;
2703    SearchPossibilities *next;
2704
2705    SearchPossibilities(const char* menu_topic_, SearchPossibilities *next_) {
2706        menu_topic = strdup(menu_topic_);
2707        next = next_;
2708    }
2709
2710    ~SearchPossibilities() {
2711        free(menu_topic);
2712        delete next;
2713    }
2714};
2715
2716typedef SearchPossibilities *SearchPossibilitiesPtr;
2717static SearchPossibilitiesPtr TD_poss[MAX_DEEP_TO_TEST] = { 0 };
2718
2719inline void addToPoss(int menu_deep, const char *topic_name) {
2720    TD_poss[menu_deep] = new SearchPossibilities(topic_name, TD_poss[menu_deep]);
2721}
2722
2723inline char oppositeCase(char c) {
2724    return isupper(c) ? tolower(c) : toupper(c);
2725}
2726
2727static void strcpy_overlapping(char *dest, char *src) {
2728    int src_len = strlen(src);
2729    memmove(dest, src, src_len+1);
2730}
2731
2732static const char *possible_mnemonics(int menu_deep, const char *topic_name) {
2733    int t;
2734    static char *unused;
2735
2736    if (unused)
2737        free(unused);
2738    unused = strdup(topic_name);
2739
2740    for (t = 0; unused[t]; ++t) {
2741        bool remove = false;
2742        if (!isalnum(unused[t])) { // remove useless chars
2743            remove = true;
2744        } else {
2745            char *dup = strchr(unused, unused[t]);
2746            if (dup && (dup-unused)<t) { // remove duplicated chars
2747                remove = true;
2748            } else {
2749                dup = strchr(unused, oppositeCase(unused[t]));
2750                if (dup && (dup-unused)<t) { // char is duplicated with opposite case
2751                    dup[0] = toupper(dup[0]); // prefer upper case
2752                    remove = true;
2753                }
2754            }
2755        }
2756        if (remove) {
2757            strcpy_overlapping(unused+t, unused+t+1);
2758            --t;
2759        }
2760    }
2761
2762    int topics = TD_topics[menu_deep];
2763    for (t = 0; t<topics; ++t) {
2764        char c = TD_mnemonics[menu_deep][t]; // upper case!
2765        char *u = strchr(unused, c);
2766        if (u)
2767            strcpy_overlapping(u, u+1); // remove char
2768        u = strchr(unused, tolower(c));
2769        if (u)
2770            strcpy_overlapping(u, u+1); // remove char
2771    }
2772
2773    return unused;
2774}
2775
2776static void printPossibilities(int menu_deep) {
2777    SearchPossibilities *sp = TD_poss[menu_deep];
2778    while (sp) {
2779        const char *poss = possible_mnemonics(menu_deep, sp->menu_topic);
2780        fprintf(stderr, "          - Possibilities for '%s': '%s'\n", sp->menu_topic, poss);
2781
2782        sp = sp->next;
2783    }
2784
2785    delete TD_poss[menu_deep];
2786    TD_poss[menu_deep] = 0;
2787}
2788
2789static int menu_deep_check = 0;
2790
2791static void test_duplicate_mnemonics(int menu_deep, const char *topic_name,
2792        const char *mnemonic) {
2793    if (mnemonic && mnemonic[0] != 0) {
2794        if (mnemonic[1]) { // longer than 1 char -> wrong
2795            fprintf(stderr, "Warning: Hotkey '%s' is too long; only 1 character allowed (%s|%s)\n", mnemonic, TD_menu_name, topic_name);
2796        }
2797        if (topic_name[0] == '#') { // graphical menu
2798            if (mnemonic[0]) {
2799                fprintf(stderr, "Warning: Hotkey '%s' is useless for graphical menu entry (%s|%s)\n", mnemonic, TD_menu_name, topic_name);
2800            }
2801        } else {
2802            if (strchr(topic_name, mnemonic[0])) { // occurs in menu text
2803                int topics = TD_topics[menu_deep];
2804                int t;
2805                char hotkey = toupper(mnemonic[0]); // store hotkeys case-less (case does not matter when pressing the hotkey)
2806
2807                TD_mnemonics[menu_deep][topics] = hotkey;
2808
2809                for (t=0; t<topics; t++) {
2810                    if (TD_mnemonics[menu_deep][t]==hotkey) {
2811                        fprintf(stderr, "Warning: Hotkey '%c' used twice (%s|%s)\n", hotkey, TD_menu_name, topic_name);
2812                        addToPoss(menu_deep, topic_name);
2813                        break;
2814                    }
2815                }
2816
2817                TD_topics[menu_deep] = topics+1;
2818            } else {
2819                fprintf(stderr, "Warning: Hotkey '%c' is useless; does not occur in text (%s|%s)\n", mnemonic[0], TD_menu_name, topic_name);
2820                addToPoss(menu_deep, topic_name);
2821            }
2822        }
2823    }
2824}
2825
2826static void open_test_duplicate_mnemonics(int menu_deep,
2827        const char *sub_menu_name, const char *mnemonic) {
2828    aw_assert(menu_deep == menu_deep_check+1);
2829    menu_deep_check = menu_deep;
2830
2831    int len = strlen(TD_menu_name)+1+strlen(sub_menu_name)+1;
2832    char *buf = (char*)malloc(len);
2833
2834    memset(buf, 0, len);
2835
2836    sprintf(buf, "%s|%s", TD_menu_name, sub_menu_name);
2837
2838    test_duplicate_mnemonics(menu_deep-1, sub_menu_name, mnemonic);
2839
2840    free(TD_menu_name);
2841    TD_menu_name = buf;
2842
2843    TD_poss[menu_deep] = 0;
2844}
2845
2846static void close_test_duplicate_mnemonics(int menu_deep) {
2847    aw_assert(menu_deep == menu_deep_check);
2848    menu_deep_check = menu_deep-1;
2849
2850    printPossibilities(menu_deep);
2851    TD_topics[menu_deep] = 0;
2852
2853    aw_assert(TD_menu_name);
2854    // otherwise no menu was opened
2855
2856    char *slash = strrchr(TD_menu_name, '|');
2857    if (slash) {
2858        slash[0] = 0;
2859    } else {
2860        TD_menu_name[0] = 0;
2861    }
2862}
2863
2864static void init_duplicate_mnemonic() {
2865    int i;
2866
2867    if (TD_menu_name) {
2868        close_test_duplicate_mnemonics(1); // close last menu
2869        free(TD_menu_name);
2870        TD_menu_name = 0;
2871    }
2872
2873    TD_menu_name = strdup("");
2874
2875    for (i=0; i<MAX_DEEP_TO_TEST; i++) {
2876        TD_topics[i] = 0;
2877    }
2878    aw_assert(menu_deep_check == 0);
2879}
2880static void exit_duplicate_mnemonic() {
2881    close_test_duplicate_mnemonics(1); // close last menu
2882    aw_assert(TD_menu_name);
2883    free(TD_menu_name);
2884    TD_menu_name = 0;
2885    aw_assert(menu_deep_check == 0);
2886}
2887#endif
2888
2889// --------------------------------------------------------------------------------
2890
2891void AW_window::create_menu(const char *menu_id, AW_label name,
2892        const char *mnemonic, const char *helpText, AW_active Mask) {
2893    p_w->menu_deep = 0;
2894#ifdef DEBUG
2895    init_duplicate_mnemonic();
2896#endif
2897#if defined(DUMP_MENU_LIST)
2898    dumpCloseAllSubMenus();
2899#endif // DUMP_MENU_LIST
2900    insert_sub_menu(menu_id, name, mnemonic, helpText, Mask);
2901}
2902
2903void AW_window::all_menus_created() { // this is called by AW_window::show() (i.e. after all menus have been created)
2904#if defined(DEBUG)
2905    if (p_w->menu_deep>0) { // window had menu
2906        aw_assert(p_w->menu_deep == 1);
2907        // some unclosed sub-menus ?
2908        if (menu_deep_check == 1) { // otherwise the window is just re-shown (already has been checked!)
2909            exit_duplicate_mnemonic();
2910        }
2911    }
2912#endif // DEBUG
2913}
2914
2915void AW_window::insert_sub_menu(const char *smenu_id, AW_label name,
2916        const char *mnemonic, const char *helpText, AW_active Mask) {
2917    AWUSE(helpText);
2918    Widget shell, Label;
2919
2920    TuneBackground(p_w->menu_bar[p_w->menu_deep], TUNE_SUBMENU); // set background color for submenus
2921    // (Note: This must even be called if TUNE_SUBMENU is 0!
2922    //        Otherwise several submenus get the TUNE_MENUTOPIC color)
2923
2924#if defined(DUMP_MENU_LIST)
2925    dumpOpenSubMenu(name);
2926#endif // DUMP_MENU_LIST
2927#ifdef DEBUG
2928    open_test_duplicate_mnemonics(p_w->menu_deep+1, name, mnemonic);
2929#endif
2930
2931    // create shell for Pull-Down
2932    shell = XtVaCreatePopupShell("menu_shell", xmMenuShellWidgetClass,
2933            p_w->menu_bar[p_w->menu_deep], 
2934            XmNwidth, 1, 
2935            XmNheight, 1, 
2936            XmNallowShellResize, AW_TRUE, 
2937            XmNoverrideRedirect, AW_TRUE, 
2938            NULL);
2939
2940    //create row column in Pull-Down shell
2941
2942    p_w->menu_bar[p_w->menu_deep+1] = XtVaCreateWidget("menu_row_column",
2943            xmRowColumnWidgetClass, shell, 
2944            XmNrowColumnType, XmMENU_PULLDOWN, 
2945            XmNtearOffModel, XmTEAR_OFF_ENABLED, 
2946            NULL);
2947
2948    // create label in menu bar
2949    if (mnemonic && *mnemonic && strchr(name, mnemonic[0])) {
2950        // if mnemonic is "" -> Cannot convert string "" to type KeySym
2951        Label = XtVaCreateManagedWidget("menu1_top_b1",
2952                xmCascadeButtonWidgetClass, p_w->menu_bar[p_w->menu_deep], 
2953                RES_CONVERT( XmNlabelString, name ),
2954                                         RES_CONVERT( XmNmnemonic, mnemonic ), 
2955                                         XmNsubMenuId, p_w->menu_bar[p_w->menu_deep+1], 
2956                                         XmNbackground, _at->background_color, NULL );
2957    }
2958    else {
2959        Label = XtVaCreateManagedWidget( "menu1_top_b1",
2960        xmCascadeButtonWidgetClass,
2961        p_w->menu_bar[p_w->menu_deep],
2962        RES_CONVERT( XmNlabelString, name ),
2963        XmNsubMenuId, p_w->menu_bar[p_w->menu_deep+1],
2964        XmNbackground, _at->background_color,
2965        NULL);
2966    }
2967
2968    if (p_w->menu_deep < AW_MAX_MENU_DEEP-1) p_w->menu_deep++;
2969
2970    AW_INSERT_BUTTON_IN_SENS_LIST ( root, smenu_id, Mask, Label );
2971}
2972
2973void AW_window::close_sub_menu(void) {
2974#ifdef DEBUG
2975    close_test_duplicate_mnemonics(p_w->menu_deep);
2976#endif
2977#if defined(DUMP_MENU_LIST)
2978    dumpCloseSubMenu();
2979#endif // DUMP_MENU_LIST
2980    if (p_w->menu_deep>0)
2981        p_w->menu_deep--;
2982}
2983
2984void AW_window::insert_menu_topic(const char *topic_id, AW_label name,
2985        const char *mnemonic, const char *helpText, AW_active Mask, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) {
2986    Widget button;
2987    if (!topic_id)
2988        topic_id = name;
2989
2990    TuneBackground(p_w->menu_bar[p_w->menu_deep], TUNE_MENUTOPIC); // set background color for normal menu topics
2991
2992#if defined(DUMP_MENU_LIST)
2993    dumpMenuEntry(name);
2994#endif // DUMP_MENU_LIST
2995#ifdef DEBUG
2996    test_duplicate_mnemonics(p_w->menu_deep, name, mnemonic);
2997#endif
2998    if (mnemonic && *mnemonic && strchr(name, mnemonic[0])) {
2999        // create one sub-menu-point
3000        button = XtVaCreateManagedWidget("", xmPushButtonWidgetClass,
3001                p_w->menu_bar[p_w->menu_deep], 
3002                RES_LABEL_CONVERT( name ),
3003                                          RES_CONVERT( XmNmnemonic, mnemonic ), 
3004                                          XmNbackground, _at->background_color, NULL );
3005    } else {
3006        button = XtVaCreateManagedWidget( "",
3007        xmPushButtonWidgetClass,
3008        p_w->menu_bar[p_w->menu_deep],
3009        RES_LABEL_CONVERT( name ),
3010        XmNbackground, _at->background_color,
3011        NULL);
3012    }
3013
3014    AW_label_in_awar_list(this,button,name);
3015    AW_cb_struct *cbs = new AW_cb_struct(this, f, cd1, cd2, helpText);
3016    XtAddCallback(button, XmNactivateCallback,
3017    (XtCallbackProc) AW_server_callback,
3018    (XtPointer) cbs);
3019
3020    cbs->id = GBS_global_string_copy("%s",topic_id);
3021    GBS_write_hash(get_root()->prvt->action_hash,topic_id,(long)cbs);
3022    if(!(Mask&get_root()->global_mask)) {
3023        XtSetSensitive( button, False );
3024    }
3025    AW_INSERT_BUTTON_IN_SENS_LIST(root, topic_id, Mask, button);
3026}
3027
3028void AW_window::insert_help_topic(const char *topic_id, AW_label name,
3029        const char *mnemonic, const char *helpText, AW_active Mask, void (*f)(AW_window*, AW_CL , AW_CL ), AW_CL cd1, AW_CL cd2) {
3030    Widget button;
3031
3032    // create one help-sub-menu-point
3033    button = XtVaCreateManagedWidget("", xmPushButtonWidgetClass,
3034            p_w->help_pull_down, 
3035            RES_CONVERT( XmNlabelString, name ),
3036                                      RES_CONVERT( XmNmnemonic, mnemonic ), NULL );
3037    XtAddCallback(button, XmNactivateCallback,
3038    (XtCallbackProc) AW_server_callback,
3039    (XtPointer) new AW_cb_struct(this, f, cd1, cd2, helpText));
3040
3041    AW_INSERT_BUTTON_IN_SENS_LIST ( root, topic_id, Mask, button );
3042}
3043
3044void AW_window::insert_separator(void) {
3045    Widget separator;
3046
3047    // create one help-sub-menu-point
3048    separator = XtVaCreateManagedWidget("", xmSeparatorWidgetClass,
3049            p_w->menu_bar[p_w->menu_deep], 
3050            NULL);
3051}
3052
3053void AW_window::insert_separator_help(void) {
3054    Widget separator;
3055
3056    // create one help-sub-menu-point
3057    separator = XtVaCreateManagedWidget("", xmSeparatorWidgetClass,
3058            p_w->help_pull_down, 
3059            NULL);
3060}
3061
3062AW_area_management::AW_area_management(AW_root *awr, Widget formi, Widget widget) {
3063    memset((char *)this, 0, sizeof(AW_area_management));
3064    form = formi;
3065    area = widget;
3066    XtAddEventHandler(area, EnterWindowMask, FALSE,
3067            (XtEventHandler)AW_root_focusCB, (XtPointer)awr);
3068}
3069
3070AW_device *AW_window::get_device(AW_area area) {
3071    AW_area_management *aram= MAP_ARAM(area);
3072    if (!aram)
3073        return 0;
3074    if (!aram->device)
3075        aram->device = new AW_device_Xm(aram->common);
3076    aram->device->init();
3077    return (AW_device *)(aram->device);
3078}
3079
3080AW_device *AW_window::get_size_device(AW_area area) {
3081    AW_area_management *aram= MAP_ARAM(area);
3082    if (!aram)
3083        return 0;
3084    if (!aram->size_device)
3085        aram->size_device = new AW_device_size(aram->common);
3086    aram->size_device->init();
3087    aram->size_device->reset();
3088    return (AW_device *)(aram->size_device);
3089}
3090
3091AW_device *AW_window::get_print_device(AW_area area) {
3092    AW_area_management *aram= MAP_ARAM(area);
3093    if (!aram)
3094        return 0;
3095    if (!aram->print_device)
3096        aram->print_device = new AW_device_print(aram->common);
3097    aram->print_device->init();
3098    return (AW_device *)(aram->print_device);
3099}
3100
3101AW_device *AW_window::get_click_device(AW_area area, int mousex, int mousey,
3102        AW_pos max_distance_linei, AW_pos max_distance_texti, AW_pos radi) {
3103    AW_area_management *aram= MAP_ARAM(area);
3104    if (!aram)
3105        return 0;
3106    if (!aram->click_device)
3107        aram->click_device = new AW_device_click(aram->common);
3108    aram->click_device->init(mousex, mousey, max_distance_linei,
3109            max_distance_texti, radi, (AW_bitset)-1);
3110    return (AW_device *)(aram->click_device);
3111}
3112
3113void AW_window::show(void) {
3114    if (!window_is_shown) {
3115        all_menus_created();
3116        get_root()->window_show();
3117        window_is_shown = AW_TRUE;
3118    }
3119
3120    if (recalc_size_at_show) {
3121        if (recalc_size_at_show == 1) {
3122            window_fit();
3123        } else {
3124            aw_assert(recalc_size_at_show == 2);
3125            // check whether user size is too small and increase to minimum (aka default)
3126            int default_width, default_height;
3127            get_window_size(default_width, default_height);
3128            AW_root *tmp_root = get_root();
3129            int user_width = tmp_root->awar(aw_awar_name_width(this))->read_int();
3130            int user_height = tmp_root->awar(aw_awar_name_height(this))->read_int();
3131
3132#if defined(DEBUG)
3133            // printf("default size = %i/%i  user size = %i/%i\n", default_width, default_height, user_width, user_height);
3134#endif // DEBUG
3135            if (user_width<default_width)
3136                user_width = default_width;
3137            if (user_height<default_height)
3138                user_height = default_height;
3139
3140#if defined(DEBUG)
3141            // printf("using size = %i/%i\n", user_width, user_height);
3142#endif // DEBUG
3143            set_window_size(user_width, user_height);
3144        }
3145        recalc_size_at_show = 0;
3146    }
3147
3148    XtPopup(p_w->shell, XtGrabNone);
3149    XtVaSetValues(p_w->shell, XmNiconic, False, NULL);
3150    if (p_w->WM_top_offset == -1000) { // very bad hack
3151        set_expose_callback(AW_INFO_AREA, (AW_CB)aw_calculate_WM_offsets, 0, 0);
3152    }
3153}
3154
3155void AW_window::show_grabbed(void) {
3156    if (!window_is_shown) {
3157        get_root()->window_show();
3158        window_is_shown = AW_TRUE;
3159    }
3160    XtPopup(p_w->shell, XtGrabExclusive);
3161    if (p_w->WM_top_offset == -1000) { // very bad hack
3162        set_expose_callback(AW_INFO_AREA, (AW_CB)aw_calculate_WM_offsets, 0, 0);
3163    }
3164}
3165
3166void AW_window::hide(void) {
3167    if (window_is_shown) {
3168        get_root()->window_hide();
3169        window_is_shown = AW_FALSE;
3170    }
3171    XtPopdown(p_w->shell);
3172}
3173
3174AW_BOOL AW_window::get_show(void) {
3175    return window_is_shown;
3176}
3177
3178void AW_root::window_show() {
3179    active_windows++;
3180}
3181
3182void AW_root::window_hide() {
3183    active_windows--;
3184    if (active_windows<0) {
3185        exit(0);
3186    }
3187}
3188
3189void AW_root::main_loop(void) {
3190    XtAppMainLoop(p_r->context);
3191}
3192
3193void AW_root::process_events(void) {
3194    XtAppProcessEvent(p_r->context,XtIMAll);
3195}
3196
3197/** Returns type if key event follows, else 0 */
3198
3199AW_ProcessEventType AW_root::peek_key_event(AW_window */*aww*/) {
3200    XEvent xevent;
3201    Boolean result = XtAppPeekEvent(p_r->context,&xevent);
3202
3203#if defined(DEBUG) && 0
3204    printf("peek_key_event\n");
3205#endif // DEBUG
3206    if (!result)
3207        return NO_EVENT;
3208    if ( (xevent.type != KeyPress) && (xevent.type != KeyRelease))
3209        return NO_EVENT;
3210    //XKeyEvent *kev = &xevent.xkey;
3211    return (AW_ProcessEventType)xevent.type;
3212}
3213
3214static void timed_window_title_cb(class AW_root* aw_root, AW_CL cd1, AW_CL cd2) {
3215    AWUSE(aw_root);
3216    char *title = (char *)cd1;
3217    AW_window *aw = (AW_window *)cd2;
3218
3219    aw->number_of_timed_title_changes--;
3220    if ( !aw->number_of_timed_title_changes) {
3221        aw->set_window_title_intern(title);
3222    }
3223
3224    delete title;
3225}
3226void AW_window::message(char *title, int ms) {
3227    char *old_title= NULL;
3228
3229    number_of_timed_title_changes++;
3230
3231    old_title = strdup(window_name);
3232
3233    XtVaSetValues(p_w->shell, XmNtitle, title, NULL);
3234
3235    get_root()->add_timed_callback(ms, timed_window_title_cb, (AW_CL)old_title,
3236            (AW_CL)this );
3237
3238}
3239
3240void AW_window::set_window_title_intern(char *title) {
3241    XtVaSetValues(p_w->shell, XmNtitle, title, NULL);
3242}
3243
3244void AW_window::set_window_title(const char *title) {
3245    XtVaSetValues(p_w->shell, XmNtitle, title, NULL);
3246    free(window_name);
3247    window_name = strdup(title);
3248}
3249
3250const char *AW_window::get_window_title(void) {
3251    char *title;
3252
3253    XtVaGetValues(p_w->shell, XmNtitle, &title, NULL);
3254
3255    return title;
3256}
3257
3258/***************************************************************************************************************************/
3259/***************************************************************************************************************************/
3260/***************************************************************************************************************************/
3261static void AW_xfigCB_info_area(AW_window *aww, AW_xfig *xfig) {
3262
3263    AW_device *device = aww->get_device(AW_INFO_AREA);
3264    device->reset();
3265    if (aww->get_root()->color_mode == 0) { // mono colr
3266        device->clear(-1);
3267    }
3268    device->set_offset(AW::Vector(-xfig->minx, -xfig->miny));
3269    xfig->print(device);
3270}
3271
3272void AW_window::load_xfig(const char *file, AW_BOOL resize) {
3273    AW_xfig *xfig;
3274
3275    if (file)
3276        xfig = new AW_xfig(file, get_root()->font_width, get_root()->font_height);
3277    else
3278        xfig = new AW_xfig( get_root()->font_width, get_root()->font_height); // create an empty xfig
3279
3280    xfig_data = (void*)xfig;
3281
3282    set_expose_callback(AW_INFO_AREA, (AW_CB)AW_xfigCB_info_area,
3283            (AW_CL)xfig_data, 0);
3284    xfig->create_gcs(get_device(AW_INFO_AREA), get_root()->color_mode ? 8 : 1);
3285
3286    int xsize = xfig->maxx - xfig->minx;
3287    int ysize = xfig->maxy - xfig->miny;
3288
3289    if (xsize>_at->max_x_size)
3290        _at->max_x_size = xsize;
3291    if (ysize>_at->max_y_size)
3292        _at->max_y_size = ysize;
3293
3294    if (resize) {
3295        if (recalc_size_at_show == 0)
3296            recalc_size_at_show = 1;
3297        set_window_size(_at->max_x_size+1000, _at->max_y_size+1000);
3298        align();
3299    }
3300}
3301
3302void AW_window::draw_line(int x1, int y1, int x2, int y2, int width,
3303        AW_BOOL resize) {
3304    AW_xfig *xfig = (AW_xfig*)xfig_data;
3305    aw_assert(xfig);
3306    // forgot to call load_xfig ?
3307
3308    xfig->add_line(x1, y1, x2, y2, width);
3309
3310    class x {
3311public:
3312        static inline int max(int i1, int i2) {
3313            return i1>i2 ? i1 : i2;
3314        }
3315    };
3316
3317    _at->max_x_size = x::max(_at->max_x_size, xfig->maxx - xfig->minx);
3318    _at->max_y_size = x::max(_at->max_y_size, xfig->maxy - xfig->miny);
3319
3320    if (resize) {
3321        if (recalc_size_at_show == 0)
3322            recalc_size_at_show = 1;
3323        set_window_size(_at->max_x_size+1000, _at->max_y_size+1000);
3324    }
3325}
3326
3327void AW_window::_set_activate_callback(void *widget) {
3328    if (_callback && (long)_callback != 1) {
3329        if (!_callback->help_text && _at->helptext_for_next_button) {
3330            _callback->help_text = _at->helptext_for_next_button;
3331            _at->helptext_for_next_button = 0;
3332        }
3333
3334        XtAddCallback((Widget) widget, XmNactivateCallback,
3335                (XtCallbackProc) AW_server_callback, (XtPointer) _callback );
3336    }
3337    _callback = NULL;
3338}
3339
3340/***********************************************************************/
3341/*****************      AW_MACRO_MESSAGE     *******************/
3342/***********************************************************************/
3343
3344#define AW_MESSAGE_AWAR "tmp/message/macro"
3345
3346static void macro_message_cb(AW_window *aw, AW_CL) {
3347    AW_root *root = aw->get_root();
3348    aw->hide();
3349
3350    if (root->prvt->recording_macro_file) {
3351        char *s = root->awar(AW_MESSAGE_AWAR)->read_string();
3352        fprintf(root->prvt->recording_macro_file, "MESSAGE\t");
3353        GBS_fwrite_string(s, root->prvt->recording_macro_file);
3354        fprintf(root->prvt->recording_macro_file, "\n");
3355        delete s;
3356    }
3357
3358    if (root->prvt->executing_macro_file) {
3359        //root->enable_execute_macro(); @@@@
3360    }
3361
3362    return;
3363}
3364
3365static void aw_clear_macro_message_cb(AW_window *aww) {
3366    aww->get_root()->awar(AW_MESSAGE_AWAR)->write_string("");
3367}
3368
3369void aw_macro_message(const char *templat, ...)
3370// @@@ this function is unused.
3371{
3372
3373    AW_root *root = AW_root::THIS;
3374    char buffer[10000];
3375    {
3376        va_list parg;
3377        va_start(parg,templat);
3378        vsprintf(buffer, templat, parg);
3379    }
3380    static AW_window_message *aw_msg = 0;
3381
3382    root->awar_string(AW_MESSAGE_AWAR)->write_string(buffer);
3383
3384    if (!aw_msg) {
3385        aw_msg = new AW_window_message;
3386
3387        aw_msg->init(root, "MESSAGE", false);
3388        aw_msg->load_xfig("macro_message.fig");
3389
3390        aw_msg->at("clear");
3391        aw_msg->callback(aw_clear_macro_message_cb);
3392        aw_msg->create_button("OK", "OK", "O");
3393
3394        aw_msg->at("Message");
3395        aw_msg->create_text_field(AW_MESSAGE_AWAR);
3396
3397        aw_msg->at("hide");
3398        aw_msg->callback(macro_message_cb, 0);
3399        aw_msg->create_button("OK", "OK", "O");
3400    }
3401
3402    aw_msg->show();
3403    if (root->prvt->executing_macro_file) {
3404        root->stop_execute_macro();
3405    }
3406}
3407
3408GB_ERROR AW_root::start_macro_recording(const char *file,
3409        const char *application_id, const char *stop_action_name) {
3410    if (prvt->recording_macro_file) {
3411        return GB_export_error("Already Recording Macro");
3412    }
3413    char *path = 0;
3414    if (file[0] == '/') {
3415        path = strdup(file);
3416    } else {
3417        path = GBS_global_string_copy("%s/%s", GB_getenvARBMACROHOME(), file);
3418    }
3419    char *macro_header = GB_read_file("$(ARBHOME)/lib/macro.head");
3420    if (!macro_header) {
3421        return GB_export_error("Cannot open file '%s'",
3422                "$(ARBHOME)/lib/macro.head");
3423    }
3424
3425    prvt->recording_macro_file = fopen(path, "w");
3426    prvt->recording_macro_path = path;
3427    if (!prvt->recording_macro_file) {
3428        delete macro_header;
3429        return GB_export_error("Cannot open file '%s' for writing", file);
3430    }
3431    prvt->stop_action_name = strdup(stop_action_name);
3432    prvt->application_name_for_macros = strdup(application_id);
3433
3434    fprintf(prvt->recording_macro_file, "%s", macro_header);
3435    free(macro_header);
3436    return 0;
3437}
3438
3439GB_ERROR AW_root::stop_macro_recording() {
3440    if (!prvt->recording_macro_file) {
3441        return GB_export_error("Not recording macro");
3442    }
3443    fprintf(prvt->recording_macro_file, "ARB::close($gb_main);");
3444    fclose(prvt->recording_macro_file);
3445
3446    long mode = GB_mode_of_file(prvt->recording_macro_path);
3447
3448    GB_set_mode_of_file(prvt->recording_macro_path, mode | ((mode >> 2)& 0111));
3449    prvt->recording_macro_file = 0;
3450
3451    free(prvt->recording_macro_path);
3452    free(prvt->stop_action_name);
3453    free(prvt->application_name_for_macros);
3454
3455    prvt->recording_macro_path = 0;
3456    prvt->stop_action_name = 0;
3457    prvt->application_name_for_macros = 0;
3458
3459    return 0;
3460}
3461
3462GB_ERROR AW_root::execute_macro(const char *file) {
3463    char *path = 0;
3464    if (file[0] == '/') {
3465        path = strdup(file);
3466    } else {
3467        path = GBS_global_string_copy("%s/%s", GB_getenvARBMACROHOME(), file);
3468    }
3469    const char *com = GBS_global_string("perl %s &", path);
3470    printf("Action '%s'\n", com);
3471    if (system(com)) {
3472        aw_message(GBS_global_string("Calling '%s' failed", com));
3473    }
3474    free(path);
3475    return 0;
3476}
3477
3478void AW_root::stop_execute_macro() {
3479
3480}
3481
3482/*  Macro Main Loop, replaces Window Mainloop
3483 *
3484 */
3485#if 0
3486GB_ERROR AW_root::enable_execute_macro(FILE *mfile,const char *mname) {
3487    char *com = 0;
3488    char *awar = 0;
3489    char *act = 0;
3490    char *value = 0;
3491    GB_ERROR error = 0;
3492    while (1) {
3493        delete com;
3494        com = GBS_fread_string(mfile,0);
3495        if (!com || !strlen(com)) break;
3496        if (strcasecmp(com,"ACTION")==0) {
3497            act = GBS_fread_string(mfile,0);
3498            AW_cb_struct *cbs = (AW_cb_struct *)GBS_read_hash(prvt->action_hash,act);
3499            if (cbs) {
3500                cbs->run_callback();
3501            } else {
3502                aw_message(error = GB_export_error("Unknown action '%s' in macro '%s'",act,mname));
3503                break;
3504            }
3505            delete act;act = 0;
3506            continue;
3507        }
3508        if (strcasecmp(com,"AWAR")==0) {
3509            awar = GBS_fread_string(mfile,0);
3510            value = GBS_fread_string(mfile,0);
3511            AW_awar *aw = awar(awar);
3512            if (aw) {
3513                error = aw->write_as_string(value);
3514                if (error) break;
3515            } else {
3516                error = GB_export_error("Error in Macro: AWAR '%s' not found in macro '%s'",awar,mname);
3517                break;
3518            }
3519            delete awar;awar = 0;
3520            delete value;value = 0;
3521        }
3522    }
3523    delete act;
3524    delete awar;
3525    delete value;
3526    return error;
3527}
3528#endif
3529
3530#if defined(DEBUG)
3531#if defined(DEVEL_RALF)
3532#define DUMP_REMOTE_ACTIONS
3533#endif // DEVEL_RALF
3534#endif // DEBUG
3535GB_ERROR AW_root::check_for_remote_command(AW_default gb_maind,
3536        const char *rm_base) {
3537    GBDATA *gb_main = (GBDATA *)gb_maind;
3538    char awar_action[1024];
3539    sprintf(awar_action, "%s/action", rm_base);
3540    char awar_value[1024];
3541    sprintf(awar_value, "%s/value", rm_base);
3542    char awar_awar[1024];
3543    sprintf(awar_awar, "%s/awar", rm_base);
3544    char awar_result[1024];
3545    sprintf(awar_result, "%s/result", rm_base);
3546    GB_push_transaction(gb_main);
3547    char *action = GBT_read_string2(gb_main, awar_action, "");
3548    char *value = GBT_read_string2(gb_main, awar_value, "");
3549    char *tmp_awar = GBT_read_string2(gb_main, awar_awar, "");
3550    if (tmp_awar[0]) {
3551        GB_ERROR error = 0;
3552        if (strcmp(action, "AWAR_REMOTE_READ") == 0) {
3553            char *read_value = this->awar(tmp_awar)->read_as_string();
3554            GBT_write_string(gb_main, awar_value, read_value);
3555#if defined(DUMP_REMOTE_ACTIONS)
3556            printf("remote command 'AWAR_REMOTE_READ' awar='%s' value='%s'\n", tmp_awar, read_value);
3557#endif // DUMP_REMOTE_ACTIONS
3558            free(read_value);
3559            // clear action (AWAR_REMOTE_READ is just a pseudo-action) :
3560            action[0] = 0;
3561            GBT_write_string(gb_main, awar_action, "");
3562        } else if (strcmp(action, "AWAR_REMOTE_TOUCH") == 0) {
3563            this->awar(tmp_awar)->touch();
3564#if defined(DUMP_REMOTE_ACTIONS)
3565            printf("remote command 'AWAR_REMOTE_TOUCH' awar='%s'\n", tmp_awar);
3566#endif // DUMP_REMOTE_ACTIONS
3567            // clear action (AWAR_REMOTE_TOUCH is just a pseudo-action) :
3568            action[0] = 0;
3569            GBT_write_string(gb_main, awar_action, "");
3570        } else {
3571#if defined(DUMP_REMOTE_ACTIONS)
3572            printf("remote command (write awar) awar='%s' value='%s'\n", tmp_awar, value);
3573#endif // DUMP_REMOTE_ACTIONS
3574            error = this->awar(tmp_awar)->write_as_string(value);
3575        }
3576        GBT_write_string(gb_main, awar_result, error ? error : "");
3577        GBT_write_string(gb_main, awar_awar, ""); // this works as READY-signal for perl-client (remote_awar and remote_read_awar)
3578    }
3579    GB_pop_transaction(gb_main);
3580
3581    if (action[0]) {
3582        AW_cb_struct *cbs = (AW_cb_struct *)GBS_read_hash(prvt->action_hash,
3583                action);
3584
3585#if defined(DUMP_REMOTE_ACTIONS)
3586        printf("remote command (%s) exists=%i\n", action, int(cbs != 0));
3587#endif                          // DUMP_REMOTE_ACTIONS
3588        if (cbs) {
3589            cbs->run_callback();
3590            GBT_write_string(gb_main, awar_result, "");
3591        } else {
3592            aw_message(GB_export_error("Unknown action '%s' in macro", action));
3593            GBT_write_string(gb_main, awar_result, GB_get_error());
3594        }
3595        GBT_write_string(gb_main, awar_action, ""); // this works as READY-signal for perl-client (remote_action)
3596    }
3597    free(tmp_awar);
3598    free(value);
3599    free(action);
3600    return 0;
3601}
3602
3603void AW_window::set_background(const char *colorname, Widget parentWidget) {
3604    bool colorSet = false;
3605
3606    if (colorname) {
3607        XColor unused, color;
3608
3609        if (XAllocNamedColor(p_global->display, p_global->colormap, colorname, &color, &unused)
3610                == 0) {
3611            fprintf(stderr,"XAllocColor failed: %s\n", colorname);
3612        } else {
3613            _at->background_color = color.pixel;
3614            colorSet = true;
3615        }
3616    }
3617
3618    if (!colorSet) {
3619        XtVaGetValues(parentWidget, XmNbackground, &(_at->background_color),
3620                NULL); // fallback to background color
3621    }
3622}
3623
3624void AW_window::TuneOrSetBackground(Widget w, const char *color, int modStrength) {
3625    // Sets the background for the next created widget.
3626    //
3627    // If 'color' is specified, it may contain one of the following values:
3628    //      "+"    means: slightly increase color of parent widget 'w'
3629    //      "-"    means: slightly decrease color of parent widget 'w'
3630    //      otherwise it contains a specific color ('name' or '#RGB')
3631    //
3632    // If color is not specified, the color of the parent widget 'w' is modified
3633    // by 'modStrength' (increased if positive,  decreased if negative)
3634    //
3635    // If it's not possible to modify the color (e.g. we cannot increase 'white'),
3636    // the color will be modified in the opposite direction. For details see TuneBackground()
3637
3638    if (color) {
3639        switch (color[0]) {
3640        case '+':
3641            TuneBackground(w, TUNE_BRIGHT);
3642            break;
3643        case '-':
3644            TuneBackground(w, TUNE_DARK);
3645            break;
3646        default:
3647            set_background(color, w); // use explicit color
3648        }
3649    } else {
3650        TuneBackground(w, modStrength);
3651    }
3652}
3653
3654void AW_window::TuneBackground(Widget w, int modStrength) {
3655    // Gets the Background Color, modifies the rgb values slightly and sets new background color
3656    // Intended to give buttons a nicer 3D-look.
3657    //
3658    // possible values for modStrength:
3659    //
3660    //    0        = do not modify (i.e. set to background color of parent widget)
3661    //    1 .. 127 = increase if background is bright, decrease if background is dark
3662    //   -1 ..-127 = opposite behavior than above
3663    //  256 .. 383 = always increase
3664    // -256 ..-383 = always decrease
3665    //
3666    // if it's impossible to decrease or increase -> opposite direction is used.
3667
3668    int col[3];
3669    {
3670        Pixel bg;
3671        XtVaGetValues(w, XmNbackground, &bg, NULL);
3672
3673        XColor xc;
3674        xc.pixel = bg;
3675        XQueryColor(XtDisplay(w), p_global->colormap, &xc);
3676
3677        col[0] = xc.red >> 8; // take MSB
3678        col[1] = xc.green >> 8;
3679        col[2] = xc.blue >> 8;
3680    }
3681
3682    int mod = modStrength;
3683    int preferredDir = 0;
3684    bool invertedMod = false;
3685
3686    if (modStrength>0) {
3687        if (modStrength>255) {
3688            mod -= 256;
3689            preferredDir = 1; // increase preferred
3690        }
3691    } else {
3692        if (modStrength<-255) {
3693            mod = -modStrength-256;
3694            preferredDir = -1; // decrease preferred
3695        } else {
3696            invertedMod = true;
3697            mod = -mod;
3698        }
3699    }
3700
3701    aw_assert(mod >= 0 && mod < 128);
3702    // illegal modification
3703
3704    bool incPossible[3]; // increment possible for color
3705    bool decPossible[3]; // decrement possible for color
3706    int incs = 0; // count possible increments
3707    int decs = 0; // count possible decrements
3708
3709    for (int i = 0; i<3; ++i) {
3710        if ((incPossible[i] = ((col[i]+mod) <= 255)))
3711            incs++;
3712        if ((decPossible[i] = ((col[i]-mod) >= 0)))
3713            decs++;
3714    }
3715
3716    aw_assert(incs||decs);
3717
3718    switch (preferredDir) {
3719    case 0: // no direction preferred yet, need to decide
3720        if (invertedMod)
3721            preferredDir = decs ? -1 : 1;
3722        else
3723            preferredDir = incs ? 1 : -1;
3724        break;
3725    case 1:
3726        if (!incs)
3727            preferredDir = -1;
3728        break;
3729    case -1:
3730        if (!decs)
3731            preferredDir = 1;
3732        break;
3733    }
3734
3735    aw_assert(preferredDir == 1 || preferredDir == -1); // no direction chosen above
3736   
3737    if (preferredDir == 1) {
3738        for (int i=0; i<3; ++i) col[i] += (incPossible[i] ? mod : 0);
3739    }
3740    else if (preferredDir == -1) {
3741        for (int i=0; i<3; ++i) col[i] -= (decPossible[i] ? mod : 0);
3742    }
3743   
3744
3745    char hex_color[50];
3746    sprintf(hex_color, "#%2.2X%2.2X%2.2X", col[0], col[1], col[2]);
3747    aw_assert(strlen(hex_color) == 7);
3748    // otherwise some value overflowed
3749    set_background(hex_color, w);
3750}
3751
3752/// Extended by Daniel Koitzsch & Christian Becker 19-05-04
3753#if defined(ARB_OPENGL)
3754
3755AW_window_menu_modes_opengl::AW_window_menu_modes_opengl(void) {
3756}
3757
3758AW_window_menu_modes_opengl::~AW_window_menu_modes_opengl(void) {
3759}
3760
3761void AW_window_menu_modes_opengl::init(AW_root *root_in, const char *wid,
3762                                       const char *windowname, int width, int height) {
3763
3764    Widget main_window;
3765    Widget help_popup;
3766    Widget help_label;
3767    Widget separator;
3768    Widget form1;
3769    Widget form2;
3770    //Widget frame;
3771    const char *help_button = "HELP";
3772    const char *help_mnemonic = "H";
3773
3774#if defined(DUMP_MENU_LIST)
3775    initMenuListing(windowname);
3776#endif // DUMP_MENU_LIST
3777    root = root_in; // for makro
3778    window_name = strdup(windowname);
3779    window_defaults_name = GBS_string_2_key(wid);
3780
3781    int posx = 50;
3782    int posy = 50;
3783
3784    p_w->shell= aw_create_shell(this, AW_TRUE, AW_TRUE, width, height, posx,
3785                                posy);
3786
3787    main_window = XtVaCreateManagedWidget("mainWindow1",
3788                                          xmMainWindowWidgetClass, p_w->shell, 
3789                                          NULL);
3790
3791    p_w->menu_bar[0] = XtVaCreateManagedWidget("menu1", xmRowColumnWidgetClass,
3792                                               main_window, 
3793                                               XmNrowColumnType, XmMENU_BAR, 
3794                                               NULL);
3795
3796    // create shell for help-cascade
3797    help_popup = XtVaCreatePopupShell("menu_shell", xmMenuShellWidgetClass,
3798                                      p_w->menu_bar[0], 
3799                                      XmNwidth, 1, 
3800                                      XmNheight, 1, 
3801                                      XmNallowShellResize, AW_TRUE, 
3802                                      XmNoverrideRedirect, AW_TRUE, 
3803                                      NULL);
3804
3805    //create row column in Pull-Down shell
3806    p_w->help_pull_down = XtVaCreateWidget("menu_row_column",
3807                                           xmRowColumnWidgetClass, help_popup, 
3808                                           XmNrowColumnType, XmMENU_PULLDOWN, 
3809                                           NULL);
3810
3811    // create HELP-label in menu bar
3812    help_label = XtVaCreateManagedWidget("menu1_top_b1",
3813                                         xmCascadeButtonWidgetClass, p_w->menu_bar[0], 
3814                                         RES_CONVERT( XmNlabelString, help_button ),
3815                                         RES_CONVERT( XmNmnemonic, help_mnemonic ), 
3816                                         XmNsubMenuId, p_w->help_pull_down, NULL );
3817    XtVaSetValues(p_w->menu_bar[0], XmNmenuHelpWidget, help_label, NULL);
3818    //insert help_label to button_list
3819    AW_INSERT_BUTTON_IN_SENS_LIST ( root, help_button, AWM_ALL, help_label );
3820
3821    form1 = XtVaCreateManagedWidget( "form1",
3822                                     xmFormWidgetClass,
3823                                     main_window,
3824                                     // XmNwidth, width,
3825                                     // XmNheight, height,
3826                                     XmNresizePolicy, XmRESIZE_NONE,
3827                                     // XmNx, 0,
3828                                     // XmNy, 0,
3829                                     NULL);
3830
3831    p_w->mode_area = XtVaCreateManagedWidget( "mode area",
3832                                              xmDrawingAreaWidgetClass,
3833                                              form1,
3834                                              XmNresizePolicy, XmRESIZE_NONE,
3835                                              XmNwidth, 38,
3836                                              XmNheight, height,
3837                                              XmNx, 0,
3838                                              XmNy, 0,
3839                                              XmNleftOffset, 0,
3840                                              XmNtopOffset, 0,
3841                                              XmNbottomAttachment, XmATTACH_FORM,
3842                                              XmNleftAttachment, XmATTACH_POSITION,
3843                                              XmNtopAttachment, XmATTACH_POSITION,
3844                                              XmNmarginHeight, 2,
3845                                              XmNmarginWidth, 1,
3846                                              NULL);
3847
3848    separator = XtVaCreateManagedWidget( "separator",
3849                                         xmSeparatorWidgetClass,
3850                                         form1,
3851                                         XmNx, 37,
3852                                         XmNshadowThickness, 4,
3853                                         XmNorientation, XmVERTICAL,
3854                                         XmNbottomAttachment, XmATTACH_FORM,
3855                                         XmNtopAttachment, XmATTACH_FORM,
3856                                         XmNleftAttachment, XmATTACH_NONE,
3857                                         XmNleftWidget, NULL,
3858                                         XmNrightAttachment, XmATTACH_NONE,
3859                                         XmNleftOffset, 70,
3860                                         XmNleftPosition, 0,
3861                                         NULL);
3862
3863    form2 = XtVaCreateManagedWidget( "form2",
3864                                     xmFormWidgetClass,
3865                                     form1,
3866                                     XmNwidth, width,
3867                                     XmNheight, height,
3868                                     XmNtopOffset, 0,
3869                                     XmNbottomOffset, 0,
3870                                     XmNleftOffset, 0,
3871                                     XmNrightOffset, 0,
3872                                     XmNrightAttachment, XmATTACH_FORM,
3873                                     XmNbottomAttachment, XmATTACH_FORM,
3874                                     XmNleftAttachment, XmATTACH_WIDGET,
3875                                     XmNleftWidget, separator,
3876                                     XmNtopAttachment, XmATTACH_POSITION,
3877                                     XmNresizePolicy, XmRESIZE_NONE,
3878                                     XmNx, 0,
3879                                     XmNy, 0,
3880                                     NULL);
3881    p_w->areas[AW_INFO_AREA] =
3882        new AW_area_management(root, form2, XtVaCreateManagedWidget( "info_area",
3883                                                                     xmDrawingAreaWidgetClass,
3884                                                                     form2,
3885                                                                     XmNheight, 0,
3886                                                                     XmNbottomAttachment, XmATTACH_NONE,
3887                                                                     XmNtopAttachment, XmATTACH_FORM,
3888                                                                     XmNleftAttachment, XmATTACH_FORM,
3889                                                                     XmNrightAttachment, XmATTACH_FORM,
3890                                                                     XmNmarginHeight, 2,
3891                                                                     XmNmarginWidth, 2,
3892                                                                     NULL));
3893
3894    p_w->areas[AW_BOTTOM_AREA] =
3895        new AW_area_management(root, form2, XtVaCreateManagedWidget( "bottom_area",
3896                                                                     xmDrawingAreaWidgetClass,
3897                                                                     form2,
3898                                                                     XmNheight, 0,
3899                                                                     XmNbottomAttachment, XmATTACH_FORM,
3900                                                                     XmNtopAttachment, XmATTACH_NONE,
3901                                                                     XmNleftAttachment, XmATTACH_FORM,
3902                                                                     XmNrightAttachment, XmATTACH_FORM,
3903                                                                     NULL));
3904
3905    /*p_w->scroll_bar_horizontal = XtVaCreateWidget( "scroll_bar_horizontal",
3906      xmScrollBarWidgetClass, form2,
3907      //XmNincrement, 10,
3908      NULL );
3909
3910      p_w->scroll_bar_vertical = XtVaCreateWidget( "scroll_bar_vertical",
3911      xmScrollBarWidgetClass, form2,
3912      //XmNincrement, 10,
3913      NULL );*/
3914
3915    /// If I define the scroll bars as unmanaged widgets, they won't appear.
3916
3917    //p_w->scroll_bar_horizontal = XtVaCreateManagedWidget( "scroll_bar_horizontal",
3918    p_w->scroll_bar_horizontal = XtVaCreateWidget( "scroll_bar_horizontal",
3919                                                   xmScrollBarWidgetClass,
3920                                                   form2,
3921                                                   XmNheight, 15,
3922                                                   XmNminimum, 0,
3923                                                   XmNmaximum, AW_SCROLL_MAX,
3924                                                   XmNincrement, 10,
3925
3926                                                   //XmNpageIncrement, 1,
3927                                                   //XmNinitialDelay, 1,
3928
3929                                                   XmNsliderSize, AW_SCROLL_MAX,
3930                                                   XmNrightAttachment, XmATTACH_FORM,
3931                                                   XmNbottomAttachment, XmATTACH_FORM,
3932                                                   XmNbottomOffset, 0,
3933                                                   XmNleftAttachment, XmATTACH_FORM,
3934                                                   XmNtopAttachment, XmATTACH_NONE,
3935                                                   XmNorientation, XmHORIZONTAL,
3936                                                   XmNrightOffset, 18,
3937                                                   NULL );
3938
3939    //p_w->scroll_bar_vertical = XtVaCreateManagedWidget( "scroll_bar_vertical",
3940    p_w->scroll_bar_vertical = XtVaCreateWidget( "scroll_bar_vertical",
3941                                                 xmScrollBarWidgetClass,
3942                                                 form2,
3943                                                 XmNwidth, 15,
3944                                                 XmNminimum, 0,
3945                                                 XmNmaximum, AW_SCROLL_MAX,
3946                                                 XmNincrement, 10,
3947
3948                                                 //XmNpageIncrement, 1,
3949                                                 //XmNinitialDelay, 1,
3950
3951                                                 XmNsliderSize, AW_SCROLL_MAX,
3952                                                 XmNrightAttachment, XmATTACH_FORM,
3953                                                 XmNbottomAttachment, XmATTACH_WIDGET,
3954                                                 XmNbottomWidget, p_w->scroll_bar_horizontal,
3955                                                 XmNbottomOffset, 3,
3956                                                 XmNleftOffset, 3,
3957                                                 XmNrightOffset, 3,
3958                                                 XmNleftAttachment, XmATTACH_NONE,
3959                                                 XmNtopAttachment, XmATTACH_WIDGET,
3960                                                 XmNtopWidget, INFO_WIDGET,
3961                                                 NULL );
3962    //XmScrollBarSetValues();
3963
3964    p_w->frame = XtVaCreateManagedWidget( "draw_area",
3965                                          xmFrameWidgetClass,
3966                                          //                    xmDrawingAreaWidgetClass,
3967                                          form2,
3968                                          XmNshadowType, XmSHADOW_IN,
3969                                          XmNshadowThickness, 2,
3970                                          XmNleftOffset, 3,
3971                                          XmNtopOffset, 3,
3972                                          XmNbottomOffset, 3,
3973                                          XmNrightOffset, 3,
3974                                          //XmNbottomAttachment, XmATTACH_WIDGET,
3975                                          //    XmNbottomAttachment, XmATTACH_FORM,
3976                                          //XmNbottomWidget, p_w->scroll_bar_horizontal,
3977
3978                                          //XmNtopAttachment, XmATTACH_FORM,
3979                                          //    XmNtopAttachment, XmATTACH_WIDGET,
3980                                          //    XmNtopWidget, p_w->areas[AW_INFO_AREA]->area,
3981
3982                                          XmNtopOffset, 0,
3983                                          //      XmNleftAttachment, XmATTACH_FORM,
3984                                          //    XmNrightAttachment, XmATTACH_FORM,
3985                                          //XmNrightAttachment, XmATTACH_WIDGET,
3986                                          //XmNrightWidget, p_w->scroll_bar_vertical,
3987                                          NULL);
3988
3989    Arg args[20];
3990    int n;
3991    Widget glw;
3992    n = 0;
3993
3994    XtSetArg(args[n], (char *) GLwNrgba, True); n++;
3995    XtSetArg(args[n], (char *) GLwNallocateBackground, True); n++;
3996    XtSetArg(args[n], (char *) GLwNallocateOtherColors,True); n++;
3997    XtSetArg(args[n], (char *) GLwNdoublebuffer, True); n++;
3998    XtSetArg(args[n], (char *) GLwNdepthSize, True); n++;
3999    XtSetArg(args[n], (char *) GLwNredSize, 4); n++;
4000    XtSetArg(args[n], (char *) GLwNgreenSize, 4); n++;
4001    XtSetArg(args[n], (char *) GLwNblueSize, 4); n++;
4002
4003    static int alpha_Attributes[] = {GLX_RGBA,
4004                                     GLX_DEPTH_SIZE, 12,
4005                                     GLX_RED_SIZE, 4,
4006                                     GLX_GREEN_SIZE, 4,
4007                                     GLX_BLUE_SIZE, 4,
4008                                     GLX_ALPHA_SIZE, 4,
4009                                     None};
4010
4011    Widget tmp = XtCreateWidget("glw", glwMDrawingAreaWidgetClass,
4012                                form2, args, n);
4013
4014    XVisualInfo *vi;
4015    Display *dpy;
4016    dpy = XtDisplay(tmp);
4017    vi = glXChooseVisual(dpy, DefaultScreen( dpy ), alpha_Attributes);
4018    if (vi) {
4019        XtSetArg(args[n], (char *) GLwNalphaSize, 4); n++;
4020        AW_alpha_Size_Supported = true;
4021        printf("Alpha channel supported\n");
4022    } else {
4023        AW_alpha_Size_Supported = false;
4024        printf("Alpha channel NOT supported\n");
4025    }
4026
4027    XtSetArg(args[n], XmNmarginHeight, 0); n++;
4028    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4029    XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4030    XtSetArg(args[n], XmNtopWidget, p_w->areas[AW_INFO_AREA]->area); n++;
4031    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4032    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4033
4034    glw = XtCreateManagedWidget("glw", glwMDrawingAreaWidgetClass,
4035                                form2, args, n);
4036
4037    p_w->areas[AW_MIDDLE_AREA] =
4038        new AW_area_management(root,p_w->frame,glw);
4039
4040    /*p_w->areas[AW_MIDDLE_AREA] =
4041      new AW_area_management(root,p_w->frame, XtVaCreateManagedWidget( "draw area",
4042      //xmDrawingAreaWidgetClass,
4043      glwMDrawingAreaWidgetClass,
4044      form2,
4045      //p_w->frame,
4046      XmNmarginHeight, 0,
4047      //XtNresize, TRUE,
4048      XmNmarginWidth, 0,
4049      XmNbottomAttachment, XmATTACH_FORM,
4050      XmNtopAttachment, XmATTACH_WIDGET,
4051      XmNtopWidget, p_w->areas[AW_INFO_AREA]->area,
4052      XmNleftAttachment, XmATTACH_FORM,
4053      XmNrightAttachment, XmATTACH_FORM,
4054      NULL));*/
4055
4056    /*XtVaSetValues( p_w->areas[AW_MIDDLE_AREA]->area,
4057      XmNx, 0,
4058      XmNy, 0,
4059      XmNwidth, 600,
4060      XmNheight, 700,
4061      NULL );*/
4062
4063    XmMainWindowSetAreas( main_window, p_w->menu_bar[0], (Widget) NULL, (Widget) NULL, (Widget) NULL, form1 );
4064
4065    aw_realize_widget(this);
4066
4067    create_devices();
4068    create_help_entry(this);
4069    create_window_variables();
4070    set_icon(window_defaults_name);
4071}
4072#endif // ARB_OPENGL
4073
Note: See TracBrowser for help on using the repository browser.