OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / win / gem / wingem1.c
1 /*      SCCS Id: @(#)wingem1.c  3.4     1999/12/10      */
2 /* Copyright (c) Christian Bressler 1999          */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #define __TCC_COMPAT__
6
7 #include        <stdio.h>
8 #include        <stdlib.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include <ctype.h>
12 #include <e_gem.h>
13 #include <string.h>
14
15 #include "gem_rsc.h"
16 #include "load_img.h"
17 #include "gr_rect.h"
18
19 #define genericptr_t void *
20 typedef signed char schar;
21 #include "wintype.h"
22 #undef genericptr_t
23
24 #define NDECL(f)        f(void)
25 #define FDECL(f,p)      f p
26 #define CHAR_P char
27 #define SCHAR_P schar
28 #define UCHAR_P uchar
29 #define XCHAR_P xchar
30 #define SHORT_P short
31 #define BOOLEAN_P boolean
32 #define ALIGNTYP_P aligntyp
33 typedef signed char     xchar;
34 #include "wingem.h"
35 #undef CHAR_P
36 #undef SCHAR_P
37 #undef UCHAR_P
38 #undef XCHAR_P
39 #undef SHORT_P
40 #undef BOOLEAN_P
41 #undef ALIGNTYP_P
42 #undef NDECL
43 #undef FDECL
44
45 static char nullstr[]="",  md[]="NetHack 3.4.3", strCancel[]="Cancel", strOk[]="Ok", strText[]="Text";
46
47 extern winid WIN_MESSAGE, WIN_MAP, WIN_STATUS, WIN_INVEN;
48
49 #define MAXWIN 20
50 #define ROWNO 21
51 #define COLNO 80
52 #define MSGLEN 100
53
54 #define MAP_GADGETS NAME|MOVER|CLOSER|FULLER|LFARROW|RTARROW|UPARROW|DNARROW|VSLIDE|HSLIDE|SIZER|SMALLER
55 #define DIALOG_MODE AUTO_DIAL|MODAL|NO_ICONIFY
56
57 /*
58  *  Keyboard translation tables.
59  */
60 #define C(c)    (0x1f & (c))
61 #define M(c)    (0x80 | (c))
62
63 #define KEYPADLO        0x61
64 #define KEYPADHI        0x71
65
66 #define PADKEYS         (KEYPADHI - KEYPADLO + 1)
67 #define iskeypad(x)     (KEYPADLO <= (x) && (x) <= KEYPADHI)
68
69 /*
70  * Keypad keys are translated to the normal values below.
71  * When iflags.BIOS is active, shifted keypad keys are translated to the
72  *    shift values below.
73  */
74 static const struct pad {
75         char normal, shift, cntrl;
76 } keypad[PADKEYS] = {
77                         {C('['), 'Q', C('[')},          /* UNDO */
78                         {'?', '/', '?'},                /* HELP */
79                         {'(', 'a', '('},                /* ( */
80                         {')', 'w', ')'},                /* ) */
81                         {'/', '/', '/'},                /* / */
82                         {C('p'), '$', C('p')},          /* * */
83                         {'y', 'Y', C('y')},             /* 7 */
84                         {'k', 'K', C('k')},             /* 8 */
85                         {'u', 'U', C('u')},             /* 9 */
86                         {'h', 'H', C('h')},             /* 4 */
87                         {'.', '.', '.'},
88                         {'l', 'L', C('l')},             /* 6 */
89                         {'b', 'B', C('b')},             /* 1 */
90                         {'j', 'J', C('j')},             /* 2 */
91                         {'n', 'N', C('n')},             /* 3 */
92                         {'i', 'I', C('i')},             /* Ins */
93                         {'.', ':', ':'}                 /* Del */
94 }, numpad[PADKEYS] = {
95                         {C('['), 'Q', C('[')}   ,       /* UNDO */
96                         {'?', '/', '?'},                /* HELP */
97                         {'(', 'a', '('},                /* ( */
98                         {')', 'w', ')'},                /* ) */
99                         {'/', '/', '/'},                /* / */
100                         {C('p'), '$', C('p')},          /* * */
101                         {'7', M('7'), '7'},             /* 7 */
102                         {'8', M('8'), '8'},             /* 8 */
103                         {'9', M('9'), '9'},             /* 9 */
104                         {'4', M('4'), '4'},             /* 4 */
105                         {'.', '.', '.'},                /* 5 */
106                         {'6', M('6'), '6'},             /* 6 */
107                         {'1', M('1'), '1'},             /* 1 */
108                         {'2', M('2'), '2'},             /* 2 */
109                         {'3', M('3'), '3'},             /* 3 */
110                         {'i', 'I', C('i')},             /* Ins */
111                         {'.', ':', ':'}                 /* Del */
112 };
113
114 #define TBUFSZ 300
115 #define BUFSZ 256
116 extern int yn_number;                                                   /* from decl.c */
117 extern char toplines[TBUFSZ];                                   /* from decl.c */
118 extern char mapped_menu_cmds[];                         /* from options.c */
119 extern int mar_iflags_numpad(void);                     /* from wingem.c */
120 extern void Gem_raw_print(const char *);        /* from wingem.c */
121 extern int mar_hp_query(void);                          /* from wingem.c */
122 extern int mar_get_msg_history(void);           /* from wingem.c */
123 extern int mar_get_msg_visible(void);           /* from wingem.c */
124 extern void mar_get_font(int,char **,int *);/* from wingem.c */
125 extern int vdi2dev4[];                                                  /* from load_img.c */
126
127 void recalc_msg_win(GRECT*);
128 void recalc_status_win(GRECT*);
129 void calc_std_winplace(int, GRECT *);
130 int (*v_mtext)(int,int,int,char*);
131 static int no_glyph;    /* the int indicating there is no glyph */
132 IMG_header tile_image, titel_image, rip_image;
133 MFDB Tile_bilder, Map_bild, Titel_bild, Rip_bild, Black_bild, Pet_Mark, FontCol_Bild;
134 static int Tile_width=16, Tile_heigth=16, Tiles_per_line=20;
135 char *Tilefile=NULL;
136 /* pet_mark Design by Warwick Allison warwick@troll.no */
137 static int pet_mark_data[]={0x0000,0x3600,0x7F00,0x7F00,0x3E00,0x1C00,0x0800};
138 static short    *normal_palette=NULL;
139
140 static struct gw{
141         WIN *gw_window;
142         int gw_type, gw_dirty;
143         GRECT gw_place;
144 } Gem_nhwindow[MAXWIN];
145
146 typedef struct {
147         int id;
148         int size;
149         int cw, ch;
150         int prop;
151 } NHGEM_FONT;
152
153 /*struct gemmapdata {*/
154         GRECT dirty_map_area={COLNO-1,ROWNO,0,0};
155         int map_cursx=0, map_cursy=0, curs_col=WHITE;
156         int draw_cursor=TRUE, scroll_margin=-1;
157         NHGEM_FONT map_font;
158         SCROLL  scroll_map;
159         char **map_glyphs=NULL;
160         dirty_rect *dr_map;
161 /*};*/
162
163 /*struct gemstatusdata{*/
164         char **status_line;
165         int Anz_status_lines, status_w, status_align=FALSE;
166         NHGEM_FONT status_font;
167         dirty_rect *dr_stat;
168 /*};*/
169
170 /*struct gemmessagedata{*/
171         int mar_message_pause=TRUE;
172         int mar_esc_pressed=FALSE;
173         int messages_pro_zug=0;
174         char **message_line;
175         int *message_age;
176         int msg_pos=0, msg_max=0, msg_anz=0, msg_width=0, msg_vis=3, msg_align=TRUE;
177         NHGEM_FONT msg_font;
178         dirty_rect *dr_msg;
179 /*};*/
180
181 /*struct geminvdata {*/
182         SCROLL scroll_menu;
183         Gem_menu_item *invent_list;
184         int Anz_inv_lines=0, Inv_breite=16;
185         NHGEM_FONT menu_font;
186         int Inv_how;
187 /*};*/
188
189 /*struct gemtextdata{*/
190         char **text_lines;
191         int Anz_text_lines=0, text_width;
192         NHGEM_FONT text_font;
193         int use_rip=FALSE;
194         extern char** rip_line;
195 /*};*/
196
197 static OBJECT *zz_oblist[NHICON+1];
198
199 MITEM scroll_keys[]={
200 /* menu, key, state, mode, msg */
201         {FAIL,key(CTRLLEFT,0),K_CTRL,PAGE_LEFT,FAIL},
202         {FAIL,key(CTRLRIGHT,0),K_CTRL,PAGE_RIGHT,FAIL},
203         {FAIL,key(SCANUP,0),K_SHIFT,PAGE_UP,FAIL},
204         {FAIL,key(SCANDOWN,0),K_SHIFT,PAGE_DOWN,FAIL},
205         {FAIL,key(SCANLEFT,0),0,LINE_LEFT,FAIL},
206         {FAIL,key(SCANRIGHT,0),0,LINE_RIGHT,FAIL},
207         {FAIL,key(SCANUP,0),0,LINE_UP,FAIL},
208         {FAIL,key(SCANDOWN,0),0,LINE_DOWN,FAIL},
209         {FAIL,key(SCANLEFT,0),K_SHIFT,LINE_START,FAIL},
210         {FAIL,key(SCANRIGHT,0),K_SHIFT,LINE_END,FAIL},
211         {FAIL,key(SCANUP,0),K_CTRL,WIN_START,FAIL},
212         {FAIL,key(SCANDOWN,0),K_CTRL,WIN_END,FAIL},
213         {FAIL,key(SCANHOME,0),K_SHIFT,WIN_END,FAIL},
214         {FAIL,key(SCANHOME,0),0,WIN_START,FAIL}
215 };
216 #define SCROLL_KEYS     14
217
218 static DIAINFO *Inv_dialog;
219
220 #define null_free(ptr)  free(ptr), (ptr)=NULL
221 #define test_free(ptr)  if(ptr) null_free(ptr)
222
223 static char *Menu_title=NULL;
224
225 void mar_display_nhwindow(winid);
226 void mar_check_hilight_status(void){}   /* to be filled :-) */
227 static char *mar_copy_of(const char *);
228
229 extern void panic(const char *, ...);
230 void *m_alloc(size_t amt){
231         void *ptr;
232
233         ptr=malloc(amt);
234         if (!ptr) panic("Memory allocation failure; cannot get %lu bytes", amt);
235         return(ptr);
236 }
237
238 void mar_clear_messagewin(void){
239         int i, *ptr=message_age;
240
241         if(WIN_MESSAGE==WIN_ERR) return;
242         for(i=msg_anz;--i>=0;ptr++){
243                 if(*ptr)
244                         Gem_nhwindow[WIN_MESSAGE].gw_dirty=TRUE;
245                 *ptr=FALSE;
246         }
247         mar_message_pause=FALSE;
248
249         mar_display_nhwindow(WIN_MESSAGE);
250 }
251
252 void clipbrd_save(void *data,int cnt,boolean append,boolean is_inv){
253         char path[MAX_PATH],*text,*crlf="\r\n";
254         long handle;
255         int i;
256
257         if (data && cnt>0 && scrp_path(path,"scrap.txt") && (handle = append ? Fopen(path,1) : Fcreate(path,0))>0){
258                 if (append)
259                         Fseek(0L,(int) handle,SEEK_END);
260                 if(is_inv){
261                         Gem_menu_item *it=(Gem_menu_item *)data;
262
263                         for(;it;it=it->Gmi_next){
264                                 text=it->Gmi_str;
265                                 Fwrite((int) handle,strlen(text),text);
266                                 Fwrite((int) handle,2L,crlf);
267                         }
268                 }else{
269                         for(i=0;i<cnt;i++){
270                                 text=((char **)data)[i]+1;
271                                 Fwrite((int) handle,strlen(text),text);
272                                 Fwrite((int) handle,2L,crlf);
273                         }
274                 }
275                 Fclose((int) handle);
276
277                 scrp_changed(SCF_TEXT,0x2e545854l);     /* .TXT */
278         }
279 }
280
281 void move_win(WIN *z_win){
282         GRECT frame=desk;
283
284         v_set_mode(MD_XOR);
285         v_set_line(BLACK,1,1,0,0);
286         frame.g_w<<=1, frame.g_h<<=1;
287         if(graf_rt_dragbox(FALSE,&z_win->curr,&frame,&z_win->curr.g_x,&z_win->curr.g_y,NULL))
288                 window_size(z_win,&z_win->curr);
289         else
290                 window_top(z_win);
291 }
292
293 void message_handler(int x, int y){
294         switch(objc_find(zz_oblist[MSGWIN],ROOT,MAX_DEPTH,x,y)){
295         case UPMSG:
296                 if(msg_pos>msg_vis-1){
297                         msg_pos--;
298                         Gem_nhwindow[WIN_MESSAGE].gw_dirty=TRUE;
299                         mar_display_nhwindow(WIN_MESSAGE);
300                 }
301                 Event_Timer(50,0,TRUE);
302                 break;
303         case DNMSG:
304                 if(msg_pos<msg_max){
305                         msg_pos++;
306                         Gem_nhwindow[WIN_MESSAGE].gw_dirty=TRUE;
307                         mar_display_nhwindow(WIN_MESSAGE);
308                 }
309                 Event_Timer(50,0,TRUE);
310                 break;
311         case GRABMSGWIN:
312         default:
313                 move_win(Gem_nhwindow[WIN_MESSAGE].gw_window);
314                 break;
315         case -1:
316                 break;
317         }
318 }
319
320 int mar_ob_mapcenter(OBJECT *p_obj){
321         WIN *p_w= WIN_MAP!=WIN_ERR ? Gem_nhwindow[WIN_MAP].gw_window : NULL;
322
323         if(p_obj && p_w){
324                 p_obj->ob_x=p_w->work.g_x+p_w->work.g_w/2-p_obj->ob_width/2;
325                 p_obj->ob_y=p_w->work.g_y+p_w->work.g_h/2-p_obj->ob_height/2;
326                 return(DIA_LASTPOS);
327         }
328         return(DIA_CENTERED);
329 }
330
331 /****************************** set_no_glyph *************************************/
332
333 void
334 mar_set_no_glyph(ng)
335 int ng;
336 {
337         no_glyph=ng;
338 }
339
340 void
341 mar_set_tilefile(name)
342 char* name;
343 {
344         Tilefile=name;
345 }
346 void
347 mar_set_tilex(value)
348 int value;
349 {
350         Min(&value,32);
351         Max(&value,1);
352         Tile_width=value;
353 }
354 void
355 mar_set_tiley(value)
356 int value;
357 {
358         Min(&value,32);
359         Max(&value,1);
360         Tile_heigth=value;
361 }
362 /****************************** userdef_draw *************************************/
363
364 void rearrange_windows(void);
365 void mar_set_status_align(int sa){
366         if(status_align!=sa){
367                 status_align=sa;
368                 rearrange_windows();
369         }
370 }
371 void mar_set_msg_align(int ma){
372         if(msg_align!=ma){
373                 msg_align=ma;
374                 rearrange_windows();
375         }
376 }
377 void mar_set_msg_visible(int mv){
378         if(mv!=msg_vis){
379                 Max(&mv,1);
380                 Min(&mv,min(msg_anz,20));
381                 Min(&mv,desk.g_h/msg_font.ch/2);
382                 msg_vis=mv;
383                 rearrange_windows();
384         }
385 }
386 /* size<0 cellheight; size>0 points */
387 void mar_set_fontbyid(int type, int id, int size){
388         int chardim[4];
389         if(id<=0)
390                 id=ibm_font_id;
391         if((size>-3 && size<3) || size<-20 || size>20)
392                 size=-ibm_font;
393         /* MAR -- 17.Mar 2002 For now allow FNT_PROP only with NHW_TEXT */
394         if(type!=NHW_TEXT && (FontInfo(id)->type & (FNT_PROP|FNT_ASCII)))
395                 id=ibm_font_id;
396         switch(type){
397         case NHW_MESSAGE:
398                 if(msg_font.size==-size && msg_font.id==id)
399                         break;
400                 msg_font.size=-size;
401                 msg_font.id=id;
402                 msg_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII);
403                 v_set_text(msg_font.id,msg_font.size,BLACK,0,0,chardim);
404                 msg_font.ch=chardim[3] ? chardim[3] : 1;
405                 msg_font.cw=chardim[2] ? chardim[2] : 1;
406                 msg_width=min(max_w/msg_font.cw-3,MSGLEN);
407                 rearrange_windows();
408                 break;
409         case NHW_MAP:
410                 if(map_font.size!=-size || map_font.id!=id){
411                         MFDB mtmp;
412                         map_font.size=-size;
413                         map_font.id=id;
414                         map_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII);
415                         v_set_text(map_font.id,map_font.size,BLACK,0,0,chardim);
416                         map_font.ch=chardim[3] ? chardim[3] : 1;
417                         map_font.cw=chardim[2] ? chardim[2] : 1;
418                         mfdb(&mtmp,NULL,(COLNO-1)*map_font.cw, ROWNO*map_font.ch, 0, planes);
419                         if(mfdb_size(&mtmp)>mfdb_size(&FontCol_Bild) && mfdb_size(&mtmp)>mfdb_size(&Map_bild)){
420                                 FontCol_Bild.fd_addr=Map_bild.fd_addr=(int *)realloc(Map_bild.fd_addr,mfdb_size(&mtmp));
421                                 if(!Map_bild.fd_addr)   /* FIXME -- Not really neccessary since the former space is still valid */
422                                         panic("Not enough Space for the map.");
423                         }
424                         mfdb(&FontCol_Bild,FontCol_Bild.fd_addr,(COLNO-1)*map_font.cw, ROWNO*map_font.ch, 0, planes);
425                         rearrange_windows();
426                 }
427                 break;
428         case NHW_STATUS:
429                 if(status_font.size==-size && status_font.id==id)
430                         break;
431                 status_font.size=-size;
432                 status_font.id=id;
433                 status_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII);
434                 v_set_text(status_font.id,status_font.size,BLACK,0,0,chardim);
435                 status_font.ch=chardim[3] ? chardim[3] : 1;
436                 status_font.cw=chardim[2] ? chardim[2] : 1;
437                 rearrange_windows();
438                 break;
439         case NHW_MENU:
440                 if(menu_font.size==-size && menu_font.id==id)
441                         break;
442                 menu_font.size=-size;
443                 menu_font.id=id;
444                 menu_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII);
445                 v_set_text(menu_font.id,menu_font.size,BLACK,0,0,chardim);
446                 menu_font.ch=chardim[3] ? chardim[3] : 1;
447                 menu_font.cw=chardim[2] ? chardim[2] : 1;
448                 break;
449         case NHW_TEXT:
450                 if(text_font.size==-size && text_font.id==id)
451                         break;
452                 text_font.size=-size;
453                 text_font.id=id;
454                 text_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII);
455                 v_set_text(text_font.id,text_font.size,BLACK,0,0,chardim);
456                 text_font.ch=chardim[3] ? chardim[3] : 1;
457                 text_font.cw=chardim[2] ? chardim[2] : 1;
458                 break;
459         default:
460                 break;
461         }
462 }
463 void mar_set_font(int type, const char *font_name, int size){
464         int id=0;
465         /* MAR -- 17.Mar 2002 usual Gem behavior, use the Font-ID */
466         if(font_name && *font_name){
467                 id=atoi(font_name);
468                 if(id<=0){
469                         int i, tid;
470                         char name[32];
471                         for(i=fonts_loaded;--i>=0;){
472                                 tid=vqt_name(x_handle,i,name);
473                                 if(!stricmp(name,font_name)){
474                                         id=tid;
475                                         break;
476                                 }
477                         }
478                 }
479         }
480         mar_set_fontbyid(type,id,size);
481 }
482 void rearrange_windows(void){
483         GRECT area;
484         int todo=TRUE;
485         if(WIN_MAP != WIN_ERR && Gem_nhwindow[WIN_MAP].gw_window){
486                 scroll_map.px_hline=mar_set_tile_mode(FAIL)?Tile_width:map_font.cw;
487                 scroll_map.px_vline=mar_set_tile_mode(FAIL)?Tile_heigth:map_font.ch;
488                 if(todo){
489                         calc_std_winplace(FAIL,&area);
490                         todo=FALSE;
491                 }
492                 calc_std_winplace(NHW_MAP,&area);
493                 Gem_nhwindow[WIN_MAP].gw_window->max.g_w=area.g_w;
494                 Gem_nhwindow[WIN_MAP].gw_window->max.g_h=area.g_h;
495                 Gem_nhwindow[WIN_MAP].gw_window->max.g_w=area.g_w;
496                 window_reinit(Gem_nhwindow[WIN_MAP].gw_window,md,md,NULL,FALSE,FALSE);
497                 {
498                         int buf[8];
499                         buf[3]=K_CTRL;
500                         buf[4]=C('L');
501                         AvSendMsg(ap_id,AV_SENDKEY,buf);
502                 }
503         }
504         if(WIN_MESSAGE != WIN_ERR && Gem_nhwindow[WIN_MESSAGE].gw_window){
505                 if(todo){
506                         calc_std_winplace(FAIL,&area);
507                         todo=FALSE;
508                 }
509                 calc_std_winplace(NHW_MESSAGE,&area);
510                 Gem_nhwindow[WIN_MESSAGE].gw_window->min_h=area.g_h;
511                 window_size(Gem_nhwindow[WIN_MESSAGE].gw_window,&area);
512                 redraw_window(Gem_nhwindow[WIN_MESSAGE].gw_window,NULL);
513         }
514         if(WIN_STATUS != WIN_ERR && Gem_nhwindow[WIN_STATUS].gw_window){
515                 if(todo){
516                         calc_std_winplace(FAIL,&area);
517                         todo=FALSE;
518                 }
519                 calc_std_winplace(NHW_STATUS,&area);
520                 Gem_nhwindow[WIN_STATUS].gw_window->min_h=area.g_h;
521                 window_size(Gem_nhwindow[WIN_STATUS].gw_window,&area);
522                 redraw_window(Gem_nhwindow[WIN_STATUS].gw_window,NULL);
523         }
524 }
525 void my_color_area(GRECT *area, int col){
526         int pxy[4];
527
528         v_set_fill(col,1,IP_SOLID,0);
529         rc_grect_to_array(area,pxy);
530         v_bar(x_handle,pxy);
531 }
532
533 void my_clear_area(GRECT *area){
534         my_color_area(area, WHITE);
535 }
536
537 int mar_set_tile_mode(int);
538
539 static void win_draw_map(int first, WIN *win, GRECT *area){
540         int pla[8], w=area->g_w-1, h=area->g_h-1;
541         int i, x, y;
542         GRECT back=*area;
543
544         first=first;
545
546         if(!mar_set_tile_mode(FAIL)){
547                 int start=(area->g_x-win->work.g_x)/map_font.cw+scroll_map.hpos;
548                 int stop=(area->g_x+area->g_w+map_font.cw-1-win->work.g_x)/map_font.cw+scroll_map.hpos;
549                 int starty=(area->g_y-win->work.g_y)/map_font.ch+scroll_map.vpos;
550                 int stopy=min((area->g_y+area->g_h+map_font.ch-1-win->work.g_y)/map_font.ch+scroll_map.vpos,ROWNO);
551                 char tmp;
552                 v_set_text(map_font.id,map_font.size,WHITE,0,0,NULL);
553                 v_set_mode(MD_TRANS);
554
555                 x=win->work.g_x-scroll_map.px_hpos+start*map_font.cw;
556                 y=win->work.g_y-scroll_map.px_vpos+starty*map_font.ch;
557                 pla[2]=pla[0]=scroll_map.px_hpos+area->g_x-win->work.g_x;
558                 pla[3]=pla[1]=starty*map_font.ch;
559                 pla[2]+=w;
560                 pla[3]+=map_font.ch-1;
561                 pla[6]=pla[4]=area->g_x;        /* x_wert to */
562                 pla[7]=pla[5]=y;        /* y_wert to */
563                 pla[6]+=w;
564                 pla[7]+=map_font.ch-1;
565                 back.g_h=map_font.ch;
566                 for(i=starty;i<stopy;i++,y+=map_font.ch,pla[1]+=map_font.ch,pla[3]+=map_font.ch,pla[5]+=map_font.ch,pla[7]+=map_font.ch){
567                         back.g_y=y;
568                         my_color_area(&back,BLACK);
569                         tmp=map_glyphs[i][stop];
570                         map_glyphs[i][stop]=0;
571                         (*v_mtext)(x_handle,x,y,&map_glyphs[i][start]);
572                         map_glyphs[i][stop]=tmp;
573                         vro_cpyfm(x_handle, S_OR_D, pla, &FontCol_Bild, screen);
574                 }
575         }else{
576                 v_set_mode(MD_REPLACE);
577                 pla[2]=pla[0]=scroll_map.px_hpos+area->g_x-win->work.g_x;
578                 pla[3]=pla[1]=scroll_map.px_vpos+area->g_y-win->work.g_y;
579                 pla[2]+=w;
580                 pla[3]+=h;
581                 pla[6]=pla[4]=area->g_x;        /* x_wert to */
582                 pla[7]=pla[5]=area->g_y;        /* y_wert to */
583                 pla[6]+=w;
584                 pla[7]+=h;
585                 vro_cpyfm(x_handle, S_ONLY, pla, &Map_bild, screen);
586         }
587
588         if(draw_cursor){
589                 v_set_line(curs_col,1,1,0,0);
590                 pla[0]=pla[2]=win->work.g_x+scroll_map.px_hline*(map_cursx-scroll_map.hpos);
591                 pla[1]=pla[3]=win->work.g_y+scroll_map.px_vline*(map_cursy-scroll_map.vpos);
592                 pla[2]+=scroll_map.px_hline-1;
593                 pla[3]+=scroll_map.px_vline-1;
594                 v_rect(pla[0],pla[1],pla[2],pla[3]);
595         }
596 }
597
598 static int draw_titel(PARMBLK *pb){
599         static int pla[8];
600         GRECT work=*(GRECT *) &pb->pb_x;
601
602         if(rc_intersect((GRECT *)&pb->pb_xc,&work)){
603                 pla[0]=pla[1]=0;
604                 pla[2]=pb->pb_w-1;
605                 pla[3]=pb->pb_h-1;
606                 pla[6]=pla[4]=pb->pb_x; /* x_wert to */
607                 pla[7]=pla[5]=pb->pb_y; /* y_wert to */
608                 pla[6]+=pb->pb_w-1;
609                 pla[7]+=pb->pb_h-1;
610
611                 vro_cpyfm(x_handle, S_ONLY, pla, &Titel_bild, screen);
612         }
613
614         return(0);
615 }
616
617 static int draw_lines(PARMBLK *pb){
618         GRECT area=*(GRECT *) &pb->pb_x;
619
620         if(rc_intersect((GRECT *)&pb->pb_xc,&area)){
621                 char **ptr;
622                 int x=pb->pb_x,y=pb->pb_y,start_line=(area.g_y-y);
623
624                 v_set_mode((text_font.cw&7)==0 && text_font.prop==0 ? MD_REPLACE : MD_TRANS);
625
626 /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4])      */
627                 v_set_text(text_font.id,text_font.size,BLACK,0,0,NULL);
628                 start_line /= text_font.ch;
629                 y+=start_line*text_font.ch;
630                 x-=(int)scroll_menu.px_hpos;
631                 ptr=&text_lines[start_line+=scroll_menu.vpos];
632                 start_line = min((area.g_y-y+area.g_h+text_font.ch-1)/text_font.ch,Anz_text_lines-start_line);
633                 area.g_h=text_font.ch;
634                 Vsync();
635 /*              x=(x+7) & ~7;*/
636                 for(;--start_line>=0;y+=text_font.ch){
637                         area.g_y=y;
638                         my_clear_area(&area);
639                         if(**ptr-1){
640                                 v_set_text(FAIL,0,BLUE,0x01,0,NULL);
641                                 (*v_mtext)(x_handle,x,y,(*ptr++)+1);
642                                 v_set_text(FAIL,0,BLACK,0x00,0,NULL);
643                         }else
644                                 (*v_mtext)(x_handle,x,y,(*ptr++)+1);
645                 }
646         }
647         return(0);
648 }
649
650 static int draw_rip(PARMBLK *pb){
651         GRECT area=*(GRECT *) &pb->pb_x;
652         if(rc_intersect((GRECT *)&pb->pb_xc,&area)){
653                 char **ptr;
654                 int x=pb->pb_x,y=pb->pb_y,start_line=(area.g_y-y), chardim[4], pla[8],i;
655                 v_set_mode(MD_REPLACE);
656 /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4])      */
657                 v_set_text(text_font.id,text_font.size,BLACK,0,0,chardim);
658                 start_line /= text_font.ch;
659                 y+=start_line*text_font.ch;
660                 x-=scroll_menu.px_hpos;
661                 ptr=&text_lines[start_line+=scroll_menu.vpos];
662                 start_line = min((area.g_y-y+area.g_h+text_font.ch-1)/text_font.ch,Anz_text_lines-start_line);
663                 area.g_h=text_font.ch;
664                 Vsync();
665                 x=(x+7) & ~7;
666                 for(;--start_line>=0;y+=text_font.ch){
667                         area.g_y=y;
668                         my_clear_area(&area);
669                         if(**ptr-1){
670                                 v_set_text(FAIL,0,BLUE,0x01,0,NULL);
671                                 (*v_mtext)(x_handle,x,y,(*ptr++)+1);
672                                 v_set_text(FAIL,0,BLACK,0x00,0,NULL);
673                         }else
674                                 (*v_mtext)(x_handle,x,y,(*ptr++)+1);
675                 }
676                 pla[0]=pla[1]=0;
677                 pla[2]=min(pb->pb_w-1,Rip_bild.fd_w-1);
678                 pla[3]=min(pb->pb_h-1,Rip_bild.fd_h-1);
679                 pla[6]=pla[4]=pb->pb_x+(pb->pb_w-Rip_bild.fd_w)/2;      /* x_wert to */
680                 pla[7]=pla[5]=pb->pb_y; /* y_wert to */
681                 pla[6]+=pla[2];
682                 pla[7]+=pla[3];
683                 vro_cpyfm(x_handle, S_ONLY, pla, &Rip_bild, screen);
684                 v_set_mode(MD_TRANS);
685                 vst_alignment(x_handle,1,5,&i,&i);
686                 pla[5]+=64;
687                 for(i=0;i<7;i++,pla[5]+=chardim[3]){
688                         v_set_text(text_font.id,(i==0 || i==6) ? text_font.size : 12,WHITE,1,0,chardim);
689                         (*v_mtext)(x_handle,pla[4]+157,pla[5],rip_line[i]);
690                         v_set_text(text_font.id,(i==0 || i==6) ? text_font.size : 12,BLACK,0,0,chardim);
691                         (*v_mtext)(x_handle,pla[4]+157,pla[5],rip_line[i]);
692                 }
693                 vst_alignment(x_handle,0,5,&i,&i);
694         }
695         return(0);
696 }
697
698 static int draw_msgline(PARMBLK *pb){
699         GRECT area=*(GRECT *) &pb->pb_x;
700
701         if(rc_intersect((GRECT *)&pb->pb_xc,&area)){
702                 int x=pb->pb_x, y=pb->pb_y+(msg_vis-1)*msg_font.ch, foo, i;
703                 char **ptr=&message_line[msg_pos], tmp;
704                 int startx, stopx, starty, stopy;
705
706                 x=(x+7) & ~7;   /* Byte alignment speeds output up */
707
708                 v_set_mode(MD_REPLACE);
709
710 /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4])      */
711                 v_set_text(msg_font.id,msg_font.size,FAIL, FAIL,0,NULL);
712                 vst_alignment(x_handle,0,5,&foo,&foo);
713                 stopy=min(msg_pos,msg_vis);
714 /*              Vsync();*/
715                 startx=(area.g_x-x)/msg_font.cw-1;      /* MAR 06.02.2001 -- because italic covers the next char */
716                 Max(&startx,0);
717                 stopx=(area.g_x+area.g_w+msg_font.cw-x-1)/msg_font.cw;
718                 x+=startx*msg_font.cw;
719                 for(i=0;i<stopy;i++,y-=msg_font.ch,ptr--){
720                         if(message_age[msg_pos-i])
721                                 v_set_text(FAIL,0,BLACK,0,0,NULL);
722                         else
723                                 v_set_text(FAIL,0,LBLACK,4,0,NULL);
724                         tmp=(*ptr)[stopx];
725                         (*ptr)[stopx]=0;
726                         (*v_mtext)(x_handle,x,y,&(*ptr)[startx]);
727                         (*ptr)[stopx]=tmp;
728                 }
729         }
730         return(0);
731 }
732
733 static int draw_status(PARMBLK *pb){
734         GRECT area=*(GRECT *) &pb->pb_x;
735
736         area.g_x+=2*status_font.cw-2;
737         area.g_w-=2*status_font.cw-2;
738         if(rc_intersect((GRECT *)&pb->pb_xc,&area)){
739                 int x=pb->pb_x, y=pb->pb_y, startx, stopx, starty, stopy, i;
740                 char tmp;
741
742 /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4])      */
743                 v_set_mode(MD_REPLACE);
744                 v_set_text(status_font.id,status_font.size,BLACK,0,0,NULL);
745                 x = (x+2*status_font.cw+6) & ~7;
746
747                 startx=(area.g_x-x)/status_font.cw;
748                 starty=(area.g_y-y)/status_font.ch;
749                 stopx=(area.g_x+area.g_w+status_font.ch-1-x)/status_font.cw;
750                 stopy=(area.g_y+area.g_h+status_font.ch-1-y)/status_font.ch;
751                 Max(&startx,0); /* MAR -- Hmm, area.g_x could end up 1 below x */
752                 Max(&stopx,0);
753                 x+=startx*status_font.cw;
754                 y+=starty*status_font.ch;
755 /*              Vsync();*/
756                 area.g_h=status_font.ch;
757                 for(i=starty;i<min(2,stopy);i++,area.g_y+=status_font.ch,y+=status_font.ch){
758                 my_clear_area(&area);
759                         tmp=status_line[i][stopx];
760                         status_line[i][stopx]=0;
761                         (*v_mtext)(x_handle,x,y,&status_line[i][startx]);
762                         status_line[i][stopx]=tmp;
763                 }
764         }
765         return(0);
766 }
767
768 static int draw_inventory(PARMBLK *pb){
769         GRECT area=*(GRECT *) &pb->pb_x;
770
771         if(rc_intersect((GRECT *)&pb->pb_xc,&area)){
772                 int gl, i, x=pb->pb_x, y=pb->pb_y,start_line=area.g_y-y;
773                 Gem_menu_item *it;
774
775                 v_set_mode(MD_REPLACE);
776                 v_set_text(menu_font.id,menu_font.size,BLACK,0,0,NULL);
777
778                 start_line /= menu_font.ch;
779                 y+=start_line*menu_font.ch;
780                 x-=scroll_menu.px_hpos;
781                 start_line+=scroll_menu.vpos;
782
783                 for(it=invent_list,i=start_line; --i>=0 && it; it=it->Gmi_next);
784
785                 i = min((area.g_y-y+area.g_h+menu_font.ch-1)/menu_font.ch,Anz_inv_lines-start_line);
786
787                 Vsync();
788                 area.g_h=menu_font.ch;
789
790                 for(;(--i>=0) && it;it=it->Gmi_next,y+=menu_font.ch){
791                         if(it->Gmi_attr)
792                                 v_set_text(FAIL,FALSE,BLUE,1,FAIL,NULL);        /* Bold */
793                         else
794                                 v_set_text(FAIL,FALSE,BLACK,0,FAIL,NULL);
795
796                         area.g_y=y;
797                         my_clear_area(&area);
798                         if((gl=it->Gmi_glyph) != no_glyph){
799                                 int pla[8], h=min(menu_font.ch,Tile_heigth)-1;
800
801                                 pla[0]=pla[2]=(gl%Tiles_per_line)*Tile_width;   /* x_wert from */
802                                 pla[1]=pla[3]=(gl/Tiles_per_line)*Tile_heigth;  /* y_wert from */
803                                 pla[4]=pla[6]=x;                                /* x_wert to */
804                                 pla[5]=pla[7]=y;                                /* y_wert to */
805                                 pla[2]+=Tile_width-1;
806                                 pla[3]+=h;
807                                 pla[6]+=Tile_heigth-1;
808                                 pla[7]+=h;
809
810                                 vro_cpyfm(x_handle,S_ONLY,pla,&Tile_bilder,screen);
811                         }
812                         if(it->Gmi_identifier)
813                                 it->Gmi_str[2]=it->Gmi_selected ? (it->Gmi_count == -1L ? '+' : '#') : '-';
814                         (*v_mtext)(x_handle,(x+23) & ~7,y,it->Gmi_str);
815                 }
816         }
817         return(0);
818 }
819
820 static int draw_prompt(PARMBLK *pb){
821         GRECT area=*(GRECT *) &pb->pb_x;
822
823         if(rc_intersect((GRECT *)&pb->pb_xc,&area)){
824                 char **ptr=(char **)pb->pb_parm;
825                 int x=pb->pb_x, y=pb->pb_y, chardim[4];
826
827 /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4])      */
828                 v_set_mode(MD_TRANS);
829                 v_set_text(ibm_font_id,ibm_font,WHITE,0,0,chardim);
830                 Vsync();
831                 if(planes<4){
832                         int pxy[4];
833                         v_set_fill(BLACK,2,4,0);
834                         rc_grect_to_array(&area,pxy);
835                         v_bar(x_handle,pxy);
836                 }else
837                         my_color_area(&area,LWHITE);
838                 (*v_mtext)(x_handle,x,y,*(ptr++));
839                 if(*ptr)
840                         (*v_mtext)(x_handle,x,y+chardim[3],*ptr);
841         }
842         return(0);
843 }
844
845 static USERBLK ub_lines={draw_lines, 0L}, ub_msg={draw_msgline, 0L},
846                                         ub_inventory={draw_inventory, 0L}, ub_titel={draw_titel, 0L},
847                                         ub_status={draw_status, 0L}, ub_prompt={draw_prompt, 0L};
848
849 /**************************** rsc_funktionen *****************************/
850
851 void my_close_dialog(DIAINFO *dialog,boolean shrink_box){
852         close_dialog(dialog,shrink_box);
853         Event_Timer(0,0,TRUE);
854 }
855
856 void
857 mar_get_rsc_tree(obj_number, z_ob_obj)
858 int obj_number;
859 OBJECT **z_ob_obj;
860 {
861    rsrc_gaddr( R_TREE, obj_number, z_ob_obj );
862         fix_objects(*z_ob_obj,SCALING,0,0);
863 }
864
865 void mar_clear_map(void);
866
867 void
868 img_error(errnumber)
869 int errnumber;
870 {
871         char buf[BUFSZ];
872
873         switch(errnumber){
874         case ERR_HEADER :
875                 sprintf(buf,"%s","[1][ Image Header | corrupt. ][ Oops ]");
876                 break;
877         case ERR_ALLOC :
878                 sprintf(buf,"%s","[1][ Not enough | memory for | an image. ][ Oops ]");
879                 break;
880         case ERR_FILE :
881                 sprintf(buf,"%s","[1][ The Image-file | is not available ][ Oops ]");
882                 break;
883         case ERR_DEPACK :
884                 sprintf(buf,"%s","[1][ The Image-file | is corrupt ][ Oops ]");
885                 break;
886         case ERR_COLOR :
887                 sprintf(buf,"%s","[1][ Number of colors | not supported ][ Oops ]");
888                 break;
889         default:
890                 sprintf(buf,"[1][ img_error | strange error | number: %i ][ Hmm ]",errnumber);
891                 break;
892         }
893         form_alert(1,buf);
894 }
895
896 void mar_change_button_char(OBJECT *z_ob, int nr, char ch){
897         *ob_get_text(z_ob,nr,0)=ch;
898         ob_set_hotkey(z_ob,nr,ch);
899 }
900
901 void
902 mar_set_dir_keys()
903 {
904         static int mi_numpad=FAIL;
905         char mcmd[]="bjnh.lyku", npcmd[]="123456789", *p_cmd;
906
907         if(mi_numpad!=mar_iflags_numpad()){
908                 OBJECT *z_ob=zz_oblist[DIRECTION];
909                 int i;
910                 mi_numpad=mar_iflags_numpad();
911                 ob_set_hotkey(z_ob,DIRDOWN,'>');
912                 ob_set_hotkey(z_ob,DIRUP,'<');
913                 p_cmd= mi_numpad ? npcmd : mcmd;
914                 for(i=0;i<9;i++)
915                         mar_change_button_char(z_ob,DIR1+2*i,p_cmd[i]);
916         }
917 }
918
919 extern int total_tiles_used;    /* tile.c */
920
921 int
922 mar_gem_init()
923 {
924         int i, bild_fehler=FALSE, fsize;
925         char *fname;
926         static MITEM wish_workaround= {FAIL,key(0,'J'),K_CTRL,W_CYCLE,FAIL};
927         OBJECT *z_ob;
928
929         if((i=open_rsc("gem_rsc.rsc",NULL,md,md,md,0,0,0))<=0){
930                 graf_mouse(M_OFF,NULL);
931                 if(i<0)
932                         form_alert(1,"[3][| Fatal Error | File: GEM_RSC.RSC | not found. ][ grumble ]");
933                 else
934                         form_alert(1,"[3][| Fatal Error | GEM initialisation | failed. ][ a pity ]");
935                 return(0);
936         }
937         if(planes<1 || planes>8){
938                 form_alert(1,"[3][ Color-depth | not supported, | try 2-256 colors. ][ Ok ]");
939                 return(0);
940         }
941         MouseBee();
942
943         /* MAR -- 17.Mar 2002 NVDI 3.0 or better uses v_ftext */
944         v_mtext= speedo==3 ? &v_ftext : &v_gtext;
945         for(i=0;i<NHICON;i++)
946                 mar_get_rsc_tree(i, &zz_oblist[i]);
947
948         z_ob=zz_oblist[ABOUT];
949         ob_hide(z_ob,OKABOUT,TRUE);
950         ob_draw_dialog(z_ob,0,0,0,0);
951
952         mar_get_font(NHW_MESSAGE,&fname,&fsize);
953         mar_set_font(NHW_MESSAGE,fname,fsize);
954         mar_get_font(NHW_MAP,&fname,&fsize);
955         mar_set_font(NHW_MAP,fname,fsize);
956         mar_get_font(NHW_STATUS,&fname,&fsize);
957         mar_set_font(NHW_STATUS,fname,fsize);
958         mar_get_font(NHW_MENU,&fname,&fsize);
959         mar_set_font(NHW_MENU,fname,fsize);
960         mar_get_font(NHW_TEXT,&fname,&fsize);
961         mar_set_font(NHW_TEXT,fname,fsize);
962         msg_anz=mar_get_msg_history();
963         mar_set_msg_visible(mar_get_msg_visible());
964         msg_width=min(max_w/msg_font.cw-3,MSGLEN);
965
966         if(max_w/status_font.cw<COLNO-1)
967                 mar_set_fontbyid(NHW_STATUS,small_font_id,-small_font);
968         status_w=min(max_w/status_font.cw-3,MSGLEN);
969
970         if(planes>0 && planes<9){
971                 normal_palette=(short *)m_alloc(3*colors*sizeof(short));
972                 get_colors(x_handle,normal_palette, colors);
973         }
974
975 loadimg:
976         bild_fehler=depack_img(Tilefile?Tilefile:(planes>=4)?"NH16.IMG":"NH2.IMG",&tile_image);
977         if(bild_fehler){
978                 z_ob=zz_oblist[ABOUT];
979                 ob_undraw_dialog(z_ob,0,0,0,0);
980                 ob_hide(z_ob,OKABOUT,FALSE);
981                 img_error(bild_fehler);
982                 return(0);
983         }
984         if(tile_image.img_w%Tile_width || tile_image.img_h%Tile_heigth){
985                 Tilefile=NULL;
986                 Tile_width=Tile_heigth=16;
987                 printf("size didn't match.\n");
988                 goto loadimg;
989         }
990         if((tile_image.img_w/Tile_width)*(tile_image.img_h/Tile_heigth)<total_tiles_used){
991                 Tilefile=NULL;
992                 Tile_width=Tile_heigth=16;
993                 printf("Too few Tiles in Image.\n");
994                 goto loadimg;
995         }
996         Tiles_per_line=tile_image.img_w/Tile_width;
997
998         if(planes>=4){
999                 if(tile_image.planes>1)
1000                         img_set_colors(x_handle, tile_image.palette, tile_image.planes);
1001 #if 0
1002                 else{
1003                         int mypalette[]={};
1004                         img_set_colors(x_handle, mypalette, 4);
1005                 }
1006 #endif
1007         }
1008
1009         mfdb(&Tile_bilder, (int *)tile_image.addr, tile_image.img_w, tile_image.img_h, 1, tile_image.planes);
1010         transform_img(&Tile_bilder);
1011
1012         mfdb(&Map_bild,NULL,(COLNO-1)*Tile_width, ROWNO*Tile_heigth, 0, planes);
1013         mfdb(&FontCol_Bild,NULL,(COLNO-1)*map_font.cw, ROWNO*map_font.ch, 0, planes);
1014         Map_bild.fd_addr=(int *)m_alloc(mfdb_size(&Map_bild)>mfdb_size(&FontCol_Bild)?mfdb_size(&Map_bild):mfdb_size(&FontCol_Bild));
1015         FontCol_Bild.fd_addr=Map_bild.fd_addr;
1016
1017         mfdb(&Pet_Mark,pet_mark_data,8, 7, 1, 1);
1018         vr_trnfm(x_handle,&Pet_Mark,&Pet_Mark);
1019
1020         mfdb(&Black_bild,NULL,16, 32, 1, 1);    /* MAR -- 17.Mar 2002 that should cover the biggest map-font */
1021         Black_bild.fd_addr=(int *)m_alloc(mfdb_size(&Black_bild));
1022         memset(Black_bild.fd_addr,255,mfdb_size(&Black_bild));
1023         vr_trnfm(x_handle,&Black_bild,&Black_bild);
1024
1025         for(i=0;i<MAXWIN;i++){
1026                 Gem_nhwindow[i].gw_window=NULL;
1027                 Gem_nhwindow[i].gw_type=0;
1028                 Gem_nhwindow[i].gw_dirty=TRUE;
1029         }
1030
1031         memset(&scroll_menu,0,sizeof(scroll_menu));
1032         scroll_menu.scroll=AUTO_SCROLL;
1033         scroll_menu.obj=LINESLIST;
1034         scroll_menu.px_hline=menu_font.cw;
1035         scroll_menu.px_vline=menu_font.ch;
1036         scroll_menu.hscroll=
1037         scroll_menu.vscroll=1;
1038         scroll_menu.tbar_d=2*gr_ch-2;
1039
1040         mar_set_dir_keys();
1041
1042         memset(&scroll_map,0,sizeof(scroll_map));
1043         scroll_map.scroll=AUTO_SCROLL;
1044         scroll_map.obj=ROOT;
1045         scroll_map.px_hline=mar_set_tile_mode(FAIL)?Tile_width:map_font.cw;
1046         scroll_map.px_vline=mar_set_tile_mode(FAIL)?Tile_heigth:map_font.ch;
1047         scroll_map.hsize=COLNO-1;
1048         scroll_map.vsize=ROWNO;
1049         scroll_map.hpage=8;
1050         scroll_map.vpage=8;
1051         scroll_map.hscroll=1;
1052         scroll_map.vscroll=1;
1053
1054         /* dial_options( round, niceline, standard, return_default, background, nonselectable,
1055                 always_keys, toMouse, clipboard, hz);   */
1056         dial_options(TRUE,TRUE,FALSE,RETURN_DEFAULT,AES_BACK,TRUE,KEY_ALWAYS,FALSE,TRUE,3);
1057         /*      dial_colors( dial_pattern, dial_color, dial_frame, hotkey, alert, cycle_button,
1058                 check_box, radio_button, arrow, cycle_backgrnd, check_backgrnd, radio_backgrnd,
1059                 arrow_backgrnd, edit_3d, draw_3d)       */
1060         if(planes<4)
1061                 dial_colors(4,BLACK,WHITE,RED,RED,WHITE,BLACK,BLACK,BLACK,FAIL,FAIL,FAIL,FAIL,TRUE,TRUE);
1062         else
1063                 dial_colors(7,LWHITE,BLACK,RED,RED,BLACK,BLACK,BLACK,BLACK,WHITE,WHITE,WHITE,WHITE,TRUE,TRUE);
1064
1065         /* void MenuItems(MITEM *close,MITEM *closeall,MITEM *cycle,MITEM *invcycle,
1066                 MITEM *globcycle,MITEM *full,MITEM *bottom,MITEM *iconify,MITEM *iconify_all,
1067                 MITEM *menu,int menu_cnt) */
1068         /* Ctrl-W ist normaly bound to cycle */
1069         MenuItems(NULL,NULL,&wish_workaround,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
1070
1071         menu_install(zz_oblist[MENU],TRUE);
1072
1073         z_ob=zz_oblist[ABOUT];
1074         ob_undraw_dialog(z_ob,0,0,0,0);
1075         ob_hide(z_ob,OKABOUT,FALSE);
1076
1077         return(1);
1078 }
1079
1080 /************************* mar_exit_nhwindows *******************************/
1081
1082 void
1083 mar_exit_nhwindows()
1084 {
1085         int i;
1086
1087         for(i=MAXWIN;--i>=0;)
1088                 if(Gem_nhwindow[i].gw_type)
1089                         mar_destroy_nhwindow(i);
1090
1091         if(normal_palette){
1092                 img_set_colors(x_handle,normal_palette,tile_image.planes);
1093                 null_free(normal_palette);
1094         }
1095         test_free(tile_image.palette);
1096         test_free(tile_image.addr);
1097         test_free(titel_image.palette);
1098         test_free(titel_image.addr);
1099 }
1100
1101 /************************* mar_curs *******************************/
1102
1103 void
1104 mar_curs(x,y)
1105 int x, y;
1106 {
1107         Min(&dirty_map_area.g_x,x);
1108         Min(&dirty_map_area.g_y,y);
1109         Max(&dirty_map_area.g_w,x);
1110         Max(&dirty_map_area.g_h,y);
1111         Min(&dirty_map_area.g_x,map_cursx);
1112         Min(&dirty_map_area.g_y,map_cursy);
1113         Max(&dirty_map_area.g_w,map_cursx);
1114         Max(&dirty_map_area.g_h,map_cursy);
1115
1116         map_cursx=x;
1117         map_cursy=y;
1118
1119         if(WIN_MAP!=WIN_ERR)
1120                 Gem_nhwindow[WIN_MAP].gw_dirty=TRUE;
1121 }
1122
1123 void mar_cliparound(void);
1124 void mar_map_curs_weiter(void)
1125 {
1126         static int once=TRUE;
1127
1128         if(once){
1129                 redraw_window(Gem_nhwindow[WIN_STATUS].gw_window,NULL);
1130                 redraw_window(Gem_nhwindow[WIN_MESSAGE].gw_window,NULL);
1131                 once=FALSE;
1132         }
1133         mar_curs(map_cursx+1,map_cursy);
1134         mar_cliparound();
1135 }
1136
1137 /************************* about *******************************/
1138
1139 void
1140 mar_about()
1141 {
1142         xdialog(zz_oblist[ABOUT], md, NULL, NULL, DIA_CENTERED, FALSE, DIALOG_MODE);
1143         Event_Timer(0,0,TRUE);
1144 }
1145
1146 /************************* ask_name *******************************/
1147
1148 char *
1149 mar_ask_name()
1150 {
1151         OBJECT *z_ob=zz_oblist[NAMEGET];
1152         int bild_fehler;
1153         char who_are_you[] = "Who are you? ";
1154
1155         bild_fehler=depack_img(planes<4 ? "TITLE2.IMG" : "TITLE.IMG", &titel_image);
1156         if(bild_fehler ){       /* MAR -- this isn't lethal */
1157                 ob_set_text(z_ob,NETHACKPICTURE,"missing title.img.");
1158         }else{
1159                 mfdb(&Titel_bild, (int *)titel_image.addr, titel_image.img_w, titel_image.img_h, 1, titel_image.planes);
1160                 transform_img(&Titel_bild);
1161                 z_ob[NETHACKPICTURE].ob_type=G_USERDEF;
1162                 z_ob[NETHACKPICTURE].ob_spec.userblk=&ub_titel;
1163         }
1164
1165         ob_clear_edit(z_ob);
1166         xdialog(z_ob,who_are_you, NULL, NULL, DIA_CENTERED, FALSE, DIALOG_MODE);
1167         Event_Timer(0,0,TRUE);
1168
1169         test_free(titel_image.palette);
1170         test_free(titel_image.addr);
1171         test_free(Titel_bild.fd_addr);
1172         return(ob_get_text(z_ob,PLNAME,0));
1173 }
1174
1175 /************************* more *******************************/
1176
1177 void
1178 send_key(int key)
1179 {
1180         int buf[8];
1181
1182         buf[3]=0;       /* No Shift/Ctrl/Alt */
1183         buf[4]=key;
1184         AvSendMsg(ap_id,AV_SENDKEY,buf);
1185 }
1186
1187 void
1188 send_return()
1189 {
1190         send_key(key(SCANRET,0));
1191 }
1192
1193 int
1194 K_Init(xev,availiable)
1195 XEVENT *xev;
1196 int availiable;
1197 {
1198         xev=xev;
1199         return(MU_KEYBD&availiable);
1200 }
1201
1202 int
1203 KM_Init(xev,availiable)
1204 XEVENT *xev;
1205 int availiable;
1206 {
1207         xev=xev;
1208         return((MU_KEYBD|MU_MESAG)&availiable);
1209 }
1210
1211 int
1212 M_Init(xev,availiable)
1213 XEVENT *xev;
1214 int availiable;
1215 {
1216         xev=xev;
1217         return(MU_MESAG&availiable);
1218 }
1219
1220 #define More_Init K_Init
1221
1222 int
1223 More_Handler(xev)
1224 XEVENT *xev;
1225 {
1226         int ev=xev->ev_mwich;
1227
1228         if(ev&MU_KEYBD){
1229                 char ch=(char)(xev->ev_mkreturn&0x00FF);
1230                 DIAINFO *dinf;
1231                 WIN *w;
1232
1233                 switch(ch){
1234                 case '\033':    /* no more more more */
1235                 case ' ':
1236                         if((w=get_top_window()) && (dinf=(DIAINFO *)w->dialog) && dinf->di_tree==zz_oblist[PAGER]){
1237                                 if(ch=='\033')
1238                                         mar_esc_pressed=TRUE;
1239                                 send_return();
1240                         break;
1241                         }
1242                         /* Fall thru */
1243                 default:
1244                         ev &= ~MU_KEYBD;        /* unknown key */
1245                         break;
1246                 }
1247         }
1248         return(ev);
1249 }
1250
1251 void
1252 mar_more()
1253 {
1254         if(!mar_esc_pressed){
1255                 OBJECT *z_ob=zz_oblist[PAGER];
1256                 WIN *p_w;
1257
1258                 Event_Handler(More_Init,More_Handler);
1259                 dial_colors(7,RED,BLACK,RED,RED,BLACK,BLACK,BLACK,BLACK,WHITE,WHITE,WHITE,WHITE,TRUE,TRUE);
1260                 if(WIN_MESSAGE!=WIN_ERR && (p_w=Gem_nhwindow[WIN_MESSAGE].gw_window)){
1261                         z_ob->ob_x=p_w->work.g_x;
1262                         z_ob->ob_y=p_w->curr.g_y+p_w->curr.g_h+gr_ch;
1263                 }
1264                 xdialog(z_ob,NULL, NULL, NULL, DIA_LASTPOS, FALSE, DIALOG_MODE);
1265                 Event_Timer(0,0,TRUE);
1266                 Event_Handler(NULL,NULL);
1267
1268                 if(planes<4)
1269                         dial_colors(4,BLACK,WHITE,RED,RED,WHITE,BLACK,BLACK,BLACK,FAIL,FAIL,FAIL,FAIL,TRUE,TRUE);
1270                 else
1271                         dial_colors(7,LWHITE,BLACK,RED,RED,BLACK,BLACK,BLACK,BLACK,WHITE,WHITE,WHITE,WHITE,TRUE,TRUE);
1272         }
1273 }
1274
1275 /************************* Gem_start_menu *******************************/
1276 void
1277 Gem_start_menu(win)
1278 winid win;
1279 {
1280         win=win;
1281         if(invent_list){
1282                 Gem_menu_item *curr, *next;
1283
1284                 for(curr=invent_list;curr;curr=next){
1285                         next=curr->Gmi_next;
1286                         free(curr->Gmi_str);
1287                         free(curr);
1288                 }
1289         }
1290         invent_list=NULL;
1291         Anz_inv_lines=0;
1292         Inv_breite=16;
1293 }
1294
1295 /************************* mar_add_menu *******************************/
1296
1297 void
1298 mar_add_menu(win, item)
1299 winid win;
1300 Gem_menu_item *item;
1301 {
1302         win=win;
1303         item->Gmi_next = invent_list;
1304         invent_list = item;
1305         Anz_inv_lines++;
1306 }
1307
1308 void
1309 mar_reverse_menu()
1310 {
1311         Gem_menu_item *next, *head = 0, *curr=invent_list;
1312
1313         while (curr) {
1314                 next = curr->Gmi_next;
1315                 curr->Gmi_next = head;
1316                 head = curr;
1317                 curr = next;
1318         }
1319         invent_list=head;
1320 }
1321
1322 void
1323 mar_set_accelerators()
1324 {
1325         char ch='a';
1326         Gem_menu_item *curr;
1327
1328         for(curr=invent_list;curr;curr=curr->Gmi_next){
1329                 int extent[8];
1330                 v_set_text(menu_font.id,menu_font.size,BLACK,0,0,NULL);
1331                 vqt_extent(x_handle,curr->Gmi_str,extent);
1332                 Max(&Inv_breite,extent[4]+Tile_width+menu_font.cw);
1333                 if(ch && curr->Gmi_accelerator==0 && curr->Gmi_identifier){
1334                         curr->Gmi_accelerator=ch;
1335                         curr->Gmi_str[0]=ch;
1336                         if(ch=='z') ch='A';
1337                         else if(ch=='Z') ch=0;
1338                         else ch++;
1339                 }
1340         }
1341 }
1342
1343 Gem_menu_item *
1344 mar_hol_inv()
1345 {
1346         return(invent_list);
1347 }
1348
1349 /************************* mar_putstr_text *********************/
1350
1351 void mar_raw_print(const char *);
1352
1353 void mar_set_text_to_rip(winid w){
1354         use_rip=TRUE;
1355 }
1356 void
1357 mar_putstr_text(winid window, int attr, const char *str)
1358 {
1359         static int zeilen_frei=0;
1360         int breite;
1361         char *ptr;
1362
1363         window=window;
1364         if(!text_lines){
1365                 text_lines=(char **)m_alloc(12*sizeof(char *));
1366                 zeilen_frei=12;
1367         }
1368         if(!zeilen_frei){
1369                 text_lines=(char **)realloc(text_lines,(Anz_text_lines+12)*sizeof(char *));
1370                 zeilen_frei=12;
1371         }
1372         if(!text_lines){
1373                 mar_raw_print("No room for Text");
1374                 return;
1375         }
1376
1377         if(str)
1378                 breite=strlen(str);
1379         Min(&breite,80);
1380         ptr=text_lines[Anz_text_lines]=(char *)m_alloc(breite*sizeof(char)+2);
1381         *ptr=(char)(attr+1);    /* avoid 0 */
1382         strncpy(ptr+1,str,breite);
1383         ptr[breite+1]=0;
1384         Anz_text_lines++;
1385         zeilen_frei--;
1386 }
1387
1388 int
1389 mar_set_inv_win(Anzahl, Breite)
1390 int Anzahl, Breite;
1391 {
1392         OBJECT *z_ob=zz_oblist[LINES];
1393         int retval=WIN_DIAL|MODAL|NO_ICONIFY;
1394
1395         scroll_menu.hsize=0;
1396         scroll_menu.vpage= (desk.g_h-3*gr_ch)/scroll_menu.px_vline;
1397         if(Anzahl>scroll_menu.vpage){
1398                 retval |= WD_VSLIDER;
1399                 if(Breite>max_w-3*scroll_menu.px_hline){
1400                         retval|=WD_HSLIDER;
1401                         scroll_menu.hpage=(max_w-3*scroll_menu.px_hline)/scroll_menu.px_hline;
1402                         scroll_menu.hpos=0;
1403                         scroll_menu.hsize=Breite/scroll_menu.px_hline;
1404                         scroll_menu.vpage=(desk.g_h-4*gr_ch-1)/scroll_menu.px_vline;
1405                 }
1406                 Anzahl=scroll_menu.vpage;
1407         }else{
1408                 if(Breite>max_w-scroll_menu.px_hline){
1409                         retval|=WD_HSLIDER;
1410                         scroll_menu.hpage=(max_w-scroll_menu.px_hline)/scroll_menu.px_hline;
1411                         scroll_menu.hpos=0;
1412                         scroll_menu.hsize=Breite/scroll_menu.px_hline;
1413                         scroll_menu.vpage= (desk.g_h-4*gr_ch-1)/scroll_menu.px_vline;
1414                         if(Anzahl>scroll_menu.vpage){
1415                                 retval |= WD_VSLIDER;
1416                                 Anzahl=scroll_menu.vpage;
1417                         }
1418                 }
1419                 scroll_menu.vpage=Anzahl;
1420         }
1421         if((scroll_menu.hmax=scroll_menu.hsize-scroll_menu.hpage)<0)
1422                 scroll_menu.hmax=0;
1423         if((scroll_menu.vmax=scroll_menu.vsize-scroll_menu.vpage)<0)
1424                 scroll_menu.vmax=0;
1425
1426         /* left/right/up 2 pixel border down 2gr_ch toolbar */
1427         z_ob[ROOT].ob_width=z_ob[LINESLIST].ob_width=Breite;
1428         z_ob[ROOT].ob_height=
1429         z_ob[QLINE].ob_y=
1430         z_ob[LINESLIST].ob_height=scroll_menu.px_vline*Anzahl;
1431         z_ob[QLINE].ob_y+=gr_ch/2;
1432         z_ob[ROOT].ob_width+=4;
1433         z_ob[ROOT].ob_height+=2*gr_ch+2;
1434
1435         return(retval);
1436 }
1437
1438 /************************* mar_status_dirty *******************************/
1439
1440 void
1441 mar_status_dirty()
1442 {
1443         int ccol;
1444
1445         ccol=mar_hp_query();
1446
1447         if(ccol<2)      curs_col=WHITE;         /* 50-100% : 0 */
1448         else if(ccol<3) curs_col=YELLOW;                /* 33-50% : 6 */
1449         else if(ccol<5) curs_col=LYELLOW;               /* 20-33% : 14*/
1450         else if(ccol<10)        curs_col=RED;           /* 10-20% : 2 */
1451         else    curs_col=MAGENTA;               /* <10% : 7*/
1452 }
1453
1454 /************************* mar_add_message *******************************/
1455
1456 void
1457 mar_add_message(str)
1458 const char *str;
1459 {
1460         int i, mesg_hist=mar_get_msg_history();
1461         char *tmp, *rest, buf[TBUFSZ];
1462
1463         if(WIN_MESSAGE == WIN_ERR)
1464                 return;
1465
1466         if(!mar_message_pause){
1467                 mar_message_pause=TRUE;
1468                 messages_pro_zug=0;
1469                 msg_pos=msg_max;
1470         }
1471
1472         if(msg_max>mesg_hist-2){
1473                 msg_max=mesg_hist-2;
1474                 msg_pos--;
1475                 if(msg_pos<0) msg_pos=0;
1476                 tmp=message_line[0];
1477                 for(i=0;i<mesg_hist-1;i++){
1478                         message_line[i]=message_line[i+1];
1479                         message_age[i]=message_age[i+1];
1480                 }
1481                 message_line[mesg_hist-1]=tmp;
1482         }
1483         strcpy(toplines,str);
1484         messages_pro_zug++;
1485         msg_max++;
1486
1487         if((int)strlen(toplines)>=msg_width){
1488                 int pos=msg_width;
1489                 tmp=toplines+msg_width;
1490                 while(*tmp!=' ' && pos>=0){
1491                         tmp--;
1492                         pos--;
1493                 }
1494                 if(pos<=0) pos=msg_width;       /* Mar -- Oops, what a word :-) */
1495                 message_age[msg_max]=TRUE;
1496                 strncpy(message_line[msg_max],toplines,pos);
1497                 message_line[msg_max][pos]=0;
1498                 rest=strcpy(buf,toplines+pos);
1499         }else{
1500                 message_age[msg_max]=TRUE;
1501                 strncpy(message_line[msg_max],toplines,msg_width);
1502                 rest=0;
1503         }
1504
1505         Gem_nhwindow[WIN_MESSAGE].gw_dirty=TRUE;
1506         if(messages_pro_zug>=mesg_hist){ /* MAR -- Greater then should never happen */
1507                 messages_pro_zug=mesg_hist;
1508                 mar_display_nhwindow(WIN_MESSAGE);
1509         }
1510
1511         if(rest)
1512                 mar_add_message(rest);
1513 }
1514
1515 /************************* mar_add_status_str *******************************/
1516
1517 void
1518 mar_add_status_str(str,line)
1519 const char *str;
1520 int line;
1521 {
1522         int i,last_diff=-1;
1523         GRECT area={0,line*status_font.ch,status_font.cw,status_font.ch};
1524         for(i=0;(i<status_w-2) && str[i];i++)
1525                 if(str[i]!=status_line[line][i]){
1526                         if(last_diff==-1) area.g_x=i*status_font.cw;
1527                         else area.g_w+=status_font.cw;
1528                         last_diff=i;
1529                         status_line[line][i]=str[i];
1530                 }else if(last_diff>=0){
1531                         add_dirty_rect(dr_stat,&area);
1532                         last_diff=-1;
1533                         area.g_w=status_font.cw;
1534                 }
1535                 for(;i<status_w-1;i++){
1536                         if(status_line[line][i]){
1537                                 if(last_diff==-1) area.g_x=i*status_font.cw;
1538                                 else area.g_w+=status_font.cw;
1539                                 last_diff=i;
1540                         }
1541                         status_line[line][i]=0;
1542                 }
1543         if(last_diff>=0)
1544                 add_dirty_rect(dr_stat,&area);
1545 }
1546
1547 /************************* mar_set_menu_title *******************************/
1548
1549 void
1550 mar_set_menu_title(str)
1551 const char *str;
1552 {
1553         test_free(Menu_title);  /* just in case */
1554         Menu_title=mar_copy_of(str ? str : nullstr);
1555 }
1556
1557 /************************* mar_set_menu_type *******************************/
1558
1559 void
1560 mar_set_menu_type(how)
1561 int how;
1562 {
1563         Inv_how=how;
1564 }
1565
1566 /************************* Inventory Utils *******************************/
1567
1568 void
1569 set_all_on_page(start, page)
1570 int start, page;
1571 {
1572         Gem_menu_item *curr;
1573
1574         if(start<0 || page<0)
1575                 return;
1576
1577         for(curr=invent_list; start--&&curr; curr=curr->Gmi_next);
1578         for(; page--&&curr; curr=curr->Gmi_next)
1579                 if (curr->Gmi_identifier && !curr->Gmi_selected)
1580                         curr->Gmi_selected = TRUE;
1581 }
1582
1583 void
1584 unset_all_on_page(start, page)
1585 int start, page;
1586 {
1587         Gem_menu_item *curr;
1588
1589         if(start<0 || page<0)
1590                 return;
1591
1592         for(curr=invent_list; start--&&curr; curr=curr->Gmi_next);
1593         for(; page--&&curr; curr=curr->Gmi_next)
1594                 if (curr->Gmi_identifier && curr->Gmi_selected) {
1595                         curr->Gmi_selected = FALSE;
1596                         curr->Gmi_count = -1L;
1597                 }
1598 }
1599
1600 void
1601 invert_all_on_page(start, page, acc)
1602 int start, page;
1603 char acc;
1604 {
1605         Gem_menu_item *curr;
1606
1607         if(start<0 || page<0)
1608                 return;
1609
1610         for(curr=invent_list; start--&&curr; curr=curr->Gmi_next);
1611         for(; page--&&curr; curr=curr->Gmi_next)
1612                 if (curr->Gmi_identifier && (acc == 0 || curr->Gmi_groupacc == acc)) {
1613                         if (curr->Gmi_selected) {
1614                                 curr->Gmi_selected = FALSE;
1615                                 curr->Gmi_count = -1L;
1616                         } else
1617                                 curr->Gmi_selected = TRUE;
1618                 }
1619 }
1620
1621 /************************* Inv_Handler and Inv_Init *******************************/
1622
1623 int scroll_top_dialog(char ch){
1624         WIN *w;
1625         DIAINFO *dinf;
1626
1627         if((w=get_top_window()) && (dinf=(DIAINFO *)w->dialog) && dinf->di_tree==zz_oblist[LINES]){
1628                 switch(ch){
1629                 case ' ':
1630                         if(scroll_menu.vpos==scroll_menu.vmax){
1631                                 send_return();
1632                                 break;
1633                         }
1634                         /* Fall thru */
1635                 case MENU_NEXT_PAGE:
1636                         scroll_window(w,PAGE_DOWN,NULL);
1637                         break;
1638                 case MENU_PREVIOUS_PAGE:
1639                         scroll_window(w,PAGE_UP,NULL);
1640                         break;
1641                 case MENU_FIRST_PAGE:
1642                         scroll_window(w,WIN_START,NULL);
1643                         break;
1644                 case MENU_LAST_PAGE:
1645                         scroll_window(w,WIN_END,NULL);
1646                         break;
1647                 default:
1648                         return(FALSE);
1649                 }
1650                 return(TRUE);
1651         }
1652         return(FALSE);
1653 }
1654
1655 #define Text_Init KM_Init
1656
1657 int
1658 Text_Handler(xev)
1659 XEVENT *xev;
1660 {
1661         int ev=xev->ev_mwich;
1662
1663         if(ev&MU_MESAG){
1664                 int *buf=xev->ev_mmgpbuf, y_wo, i;
1665                 if(*buf==FONT_CHANGED){
1666                         if(buf[3]>=0){
1667                                 mar_set_fontbyid(NHW_TEXT,buf[4],buf[5]);
1668                                 FontAck(buf[1],1);
1669                         }
1670                 }
1671         }
1672         if(ev&MU_KEYBD){
1673                 char ch=(char)(xev->ev_mkreturn&0x00FF);
1674
1675                 if(!scroll_top_dialog(ch))
1676                         switch(ch){
1677                         case '\033':
1678                                 send_return();  /* just closes the textwin */
1679                                 break;
1680                         case C('c'):
1681                                 clipbrd_save(text_lines,Anz_text_lines,xev->ev_mmokstate&K_SHIFT,FALSE);
1682                                 break;
1683                         default:
1684                                 ev &= ~MU_KEYBD;        /* unknown key */
1685                                 break;
1686                         }
1687         }
1688         return(ev);
1689 }
1690
1691 #define Inv_Init KM_Init
1692
1693 static long count=0;
1694 int
1695 Inv_Handler(xev)
1696 XEVENT *xev;
1697 {
1698         int ev=xev->ev_mwich;
1699         Gem_menu_item *it;
1700         GRECT area;
1701         OBJECT *z_ob=zz_oblist[LINES];
1702
1703         ob_pos(z_ob,LINESLIST,&area);
1704         if(ev&MU_MESAG){
1705                 int *buf=xev->ev_mmgpbuf, y_wo, i;
1706
1707                 if(*buf==FONT_CHANGED){
1708                         if(buf[3]>=0){
1709                                 mar_set_fontbyid(NHW_MENU,buf[4],buf[5]);
1710                                 FontAck(buf[1],1);
1711                         }
1712                 }else
1713                 if(*buf==OBJC_CHANGED && buf[3]==LINESLIST){
1714                         ob_undostate(z_ob,LINESLIST,SELECTED);
1715                         mouse(NULL,&y_wo);
1716                         y_wo=(y_wo-area.g_y)/menu_font.ch+scroll_menu.vpos;
1717                         for(it=invent_list,i=0;i<y_wo && it;it=it->Gmi_next,i++);
1718                         if(it->Gmi_identifier){
1719                                 it->Gmi_selected=!it->Gmi_selected;
1720                                 it->Gmi_count= count==0L ? -1L : count;
1721                                 count = 0L;
1722                                 if(Inv_how!=PICK_ANY){
1723                                         /*my_close_dialog(Inv_dialog,TRUE);*/
1724                                         send_return();
1725                                 }else{
1726                                         area.g_x=(area.g_x+23+2*menu_font.cw) & ~7;
1727                                         area.g_w=menu_font.cw;
1728                                         area.g_h=menu_font.ch;
1729                                         area.g_y+=(y_wo-scroll_menu.vpos)*menu_font.ch;
1730                                         ob_draw_chg(Inv_dialog,LINESLIST,&area,FAIL);
1731                                 }       /* how != PICK_ANY */
1732                         }       /* identifier */
1733                 }else   /* LINESLIST changed */
1734                         ev &= ~MU_MESAG;        /* unknown message not used */
1735         }       /* MU_MESAG */
1736
1737         if(ev&MU_KEYBD){
1738                 char ch=(char)(xev->ev_mkreturn&0x00FF);
1739
1740                 if(!scroll_top_dialog(ch)){
1741                         switch(ch){
1742                         case '0':       /* special 0 is also groupaccelerator for balls */
1743                                 if(count<=0)
1744                                         goto find_acc;
1745                         case '1': case '2': case '3': case '4':
1746                         case '5': case '6': case '7': case '8': case '9':
1747                                 if(Inv_how==PICK_NONE)
1748                                         goto find_acc;
1749                                 count = (count * 10L) + (long) (ch - '0');
1750                                 break;
1751                         case '\033':    /* cancel - from counting or loop */
1752                                 if(count>0L)
1753                                 count=0L;
1754                                 else{
1755                                         unset_all_on_page(0, (int)scroll_menu.vsize);
1756                                         my_close_dialog(Inv_dialog,TRUE);
1757                                         return(ev);
1758                                 }
1759                                 break;
1760                         case '\0':              /* finished (commit) */
1761                         case '\n':
1762                         case '\r':
1763                                 break;
1764                         case MENU_SELECT_PAGE:
1765                                 if(Inv_how==PICK_NONE)
1766                                         goto find_acc;
1767                                 if (Inv_how == PICK_ANY)
1768                                         set_all_on_page((int)scroll_menu.vpos, scroll_menu.vpage);
1769                                 break;
1770                         case MENU_SELECT_ALL:
1771                                 if(Inv_how==PICK_NONE)
1772                                         goto find_acc;
1773                                 if (Inv_how == PICK_ANY)
1774                                         set_all_on_page(0, (int)scroll_menu.vsize);
1775                                 break;
1776                         case MENU_UNSELECT_PAGE:
1777                                 unset_all_on_page((int)scroll_menu.vpos, scroll_menu.vpage);
1778                                 break;
1779                         case MENU_UNSELECT_ALL:
1780                                 unset_all_on_page(0, (int)scroll_menu.vsize);
1781                                 break;
1782                         case MENU_INVERT_PAGE:
1783                                 if(Inv_how==PICK_NONE)
1784                                         goto find_acc;
1785                                 if (Inv_how == PICK_ANY)
1786                                         invert_all_on_page((int)scroll_menu.vpos, scroll_menu.vpage, 0);
1787                                 break;
1788                         case MENU_INVERT_ALL:
1789                                 if(Inv_how==PICK_NONE)
1790                                         goto find_acc;
1791                                 if (Inv_how == PICK_ANY)
1792                                         invert_all_on_page(0, (int)scroll_menu.vsize, 0);
1793                                 break;
1794                         case MENU_SEARCH:
1795                                 if(Inv_how!=PICK_NONE){
1796                                         char buf[BUFSZ];
1797                                         Gem_getlin("Search for:",buf);
1798                                         if(!*buf || buf[0]=='\033')
1799                                                 break;
1800                                         for(it=invent_list;it;it=it->Gmi_next){
1801                                                 if(it->Gmi_identifier && strstr(it->Gmi_str,buf)){
1802                                                         it->Gmi_selected=TRUE;
1803                                                         if(Inv_how!=PICK_ANY){
1804                                                                 my_close_dialog(Inv_dialog,FALSE);
1805                                                                 break;
1806                                                         }
1807                                                 }
1808                                         }
1809                                 }
1810                                 break;
1811                         case C('c'):
1812                                 clipbrd_save(invent_list,Anz_inv_lines,xev->ev_mmokstate&K_SHIFT,TRUE);
1813                                 break;
1814                         default:
1815                         find_acc:
1816                                 if(Inv_how==PICK_NONE)
1817                                         my_close_dialog(Inv_dialog,TRUE);
1818                                 else
1819                                         for(it=invent_list;it;it=it->Gmi_next){
1820                                                 if(it->Gmi_identifier && (it->Gmi_accelerator==ch || it->Gmi_groupacc==ch)){
1821                                                         it->Gmi_selected=!it->Gmi_selected;
1822                                                         it->Gmi_count= count==0L ? -1L : count;
1823                                                         count = 0L;
1824                                                         if(Inv_how!=PICK_ANY)
1825                                                                 my_close_dialog(Inv_dialog,TRUE);
1826                                                 }
1827                                         }
1828                                 break;
1829                         }       /* end switch(ch) */
1830                         if(Inv_how==PICK_ANY){
1831                                 area.g_x=(area.g_x+23+2*menu_font.cw) & ~7;
1832                                 area.g_w=menu_font.cw;
1833                                 ob_draw_chg(Inv_dialog,LINESLIST,&area,FAIL);
1834                         }
1835                 }       /* !scroll_Inv_dialog */
1836         }       /* MU_KEYBD */
1837
1838         if(Inv_how==PICK_ANY){
1839                 ob_set_text(Inv_dialog->di_tree,QLINE,strCancel);
1840                 for(it=invent_list;it;it=it->Gmi_next)
1841                         if(it->Gmi_identifier && it->Gmi_selected){
1842                                 ob_set_text(Inv_dialog->di_tree,QLINE,strOk);
1843                                 break;
1844                         }
1845                 ob_draw_chg(Inv_dialog,QLINE,NULL,FAIL);
1846         }
1847         return(ev);
1848 }
1849
1850 /************************* draw_window *******************************/
1851
1852 static void
1853 mar_draw_window( first, win, area)
1854 int first;
1855 WIN *win;
1856 GRECT *area;
1857 {
1858         OBJECT *obj=(OBJECT *)win->para;
1859
1860         if(obj){
1861                 if(first){
1862                 obj->ob_x=win->work.g_x;
1863                 obj->ob_y=win->work.g_y;
1864                 }
1865                 if(area==NULL)
1866                         area=&(win->work);
1867                 objc_draw(obj, ROOT, MAX_DEPTH, area->g_x, area->g_y, area->g_w, area->g_h);
1868         }
1869 }
1870
1871 /************************* mar_display_nhwindow *******************************/
1872
1873 void redraw_winwork(WIN *w,GRECT *area){
1874         area->g_x+=w->work.g_x;
1875         area->g_y+=w->work.g_y;
1876         redraw_window(w,area);
1877 }
1878 void mar_menu_set_slider(WIN *p_win){
1879         if(p_win){
1880                 SCROLL *sc=p_win->scroll;
1881
1882                 if(!sc)
1883                         return;
1884
1885                 if(p_win->gadgets&HSLIDE){
1886                         long hsize=1000l;
1887
1888                         if(sc->hsize>0 && sc->hpage>0){
1889                                 hsize *= sc->hpage;
1890                                 hsize /= sc->hsize;
1891                         }
1892                         window_slider(p_win,HOR_SLIDER,0,(int)hsize);
1893                 }
1894                 if(p_win->gadgets&VSLIDE){
1895                         long vsize=1000l;
1896
1897                         if(sc->vsize>0 && sc->vpage>0){
1898                                 vsize *= sc->vpage;
1899                                 vsize /= sc->vsize;
1900                         }
1901                         window_slider(p_win,VERT_SLIDER,0,(int)vsize);
1902                 }
1903         }
1904 }
1905
1906 void recalc_msg_win(GRECT *area){
1907         OBJECT *z_ob;
1908         z_ob=zz_oblist[MSGWIN];
1909         z_ob[MSGLINES].ob_spec.userblk=&ub_msg;
1910         z_ob[MSGLINES].ob_width=
1911         z_ob[ROOT].ob_width=            (msg_width+3)*msg_font.cw;
1912         z_ob[MSGLINES].ob_width-=z_ob[UPMSG].ob_width;
1913         z_ob[ROOT].ob_height=
1914         z_ob[GRABMSGWIN].ob_height=
1915         z_ob[MSGLINES].ob_height=msg_vis*msg_font.ch;
1916         z_ob[DNMSG].ob_y=z_ob[GRABMSGWIN].ob_height-z_ob[DNMSG].ob_height;
1917         window_border(0,0,0,z_ob->ob_width,z_ob->ob_height, area);
1918 }
1919 void recalc_status_win(GRECT *area){
1920         OBJECT *z_ob;
1921         z_ob=zz_oblist[STATUSLINE];
1922         z_ob[ROOT].ob_type=G_USERDEF;
1923         z_ob[ROOT].ob_spec.userblk=&ub_status;
1924         z_ob[ROOT].ob_width=(status_w+2)*status_font.cw;
1925         z_ob[ROOT].ob_height=
1926         z_ob[GRABSTATUS].ob_height=2*status_font.ch;
1927         z_ob[GRABSTATUS].ob_width=2*status_font.cw-2;
1928         window_border(0,0,0,z_ob->ob_width,z_ob->ob_height,area);
1929 }
1930 void calc_std_winplace(int which, GRECT *place){
1931         static int todo=TRUE;
1932         static GRECT me, ma, st;
1933
1934         if(todo || which<0){
1935                 OBJECT *z_ob;
1936                 int map_h_off, foo;
1937
1938                 /* First the messagewin */
1939                 recalc_msg_win(&me);
1940
1941                 /* Now the map */
1942                 wind_calc(WC_BORDER,MAP_GADGETS,0,0,scroll_map.px_hline*(COLNO-1),scroll_map.px_vline*ROWNO,&foo,&foo,&foo,&map_h_off);
1943                 map_h_off-=scroll_map.px_vline*ROWNO;
1944                 window_border(MAP_GADGETS,0,0,scroll_map.px_hline*(COLNO-1),scroll_map.px_vline*ROWNO, &ma);
1945
1946                 /* Next the statuswin */
1947                 recalc_status_win(&st);
1948
1949                 /* And last but not least a final test */
1950                 ma.g_h=map_h_off+scroll_map.px_vline*ROWNO;
1951                 while(me.g_h+ma.g_h+st.g_h>=desk.g_h)
1952                         ma.g_h-=scroll_map.px_vline;
1953                 /* stack the windows */
1954                 ma.g_y=me.g_y=st.g_y=desk.g_y;
1955                 if(status_align){
1956                         ma.g_y+=st.g_h;
1957                         if(msg_align){
1958                                 st.g_y+=me.g_h;
1959                                 ma.g_y+=me.g_h;
1960                         }else{
1961                                 me.g_y+=st.g_h+ma.g_h;
1962                         }
1963                 }else{
1964                         if(msg_align){
1965                                 ma.g_y+=me.g_h;
1966                         }else{
1967                                 me.g_y+=ma.g_h;
1968                         }
1969                         st.g_y+=me.g_h+ma.g_h;
1970                 }
1971
1972                 if(which) todo=FALSE;
1973         }
1974         switch(which){
1975         case NHW_MESSAGE:
1976                 *place=me;
1977                 break;
1978         case NHW_MAP:
1979                 *place=ma;
1980                 break;
1981         case NHW_STATUS:
1982                 *place=st;
1983                 break;
1984         default:
1985                 break;
1986         }
1987 }
1988
1989 void
1990 mar_display_nhwindow(wind)
1991 winid wind;
1992 {
1993         DIAINFO *dlg_info;
1994         OBJECT *z_ob;
1995         int d_exit=W_ABANDON, i, breite, mar_di_mode, tmp_magx=magx;
1996         GRECT g_mapmax, area;
1997         char *tmp_button;
1998         struct gw *p_Gw;
1999
2000         if(wind == WIN_ERR)     return;
2001
2002         p_Gw=&Gem_nhwindow[wind];
2003         switch(p_Gw->gw_type){
2004         case NHW_TEXT:
2005                 if(WIN_MESSAGE != WIN_ERR && Gem_nhwindow[WIN_MESSAGE].gw_window)
2006                         mar_display_nhwindow(WIN_MESSAGE);
2007                 z_ob=zz_oblist[LINES];
2008                 scroll_menu.vsize=Anz_text_lines;
2009                 scroll_menu.vpos=0;
2010                 if(use_rip){
2011                         if(!depack_img(planes<4 ? "RIP2.IMG" : "RIP.IMG", &rip_image)){
2012                                 mfdb(&Rip_bild, (int *)rip_image.addr, rip_image.img_w, rip_image.img_h, 1, rip_image.planes);
2013                                 transform_img(&Rip_bild);
2014                         }
2015                         ub_lines.ub_code=draw_rip;
2016                 }else
2017                         ub_lines.ub_code=draw_lines;
2018                 z_ob[LINESLIST].ob_spec.userblk=&ub_lines;
2019                 breite=16;
2020                 v_set_text(text_font.id,text_font.size,BLACK,0,0,NULL);
2021                 for(i=0;i<Anz_text_lines;i++){
2022                         int eout[8];
2023                         vqt_extent(x_handle,text_lines[i],eout);
2024                         Max(&breite,eout[4]);
2025                 }
2026                 scroll_menu.px_vline=text_font.ch;
2027                 scroll_menu.px_hline=text_font.cw;
2028                 mar_di_mode=mar_set_inv_win(Anz_text_lines, breite);
2029                 tmp_button=ob_get_text(z_ob,QLINE,0);
2030                 ob_set_text(z_ob,QLINE,strOk);
2031                 ob_undoflag(z_ob,LINESLIST,TOUCHEXIT);
2032                 Event_Handler(Text_Init,Text_Handler);
2033                 if((dlg_info=open_dialog(z_ob,strText, NULL, NULL, mar_ob_mapcenter(z_ob), FALSE, mar_di_mode, FAIL, NULL, NULL))!=NULL){
2034                         WIN *ptr_win=dlg_info->di_win;
2035
2036                         ptr_win->scroll=&scroll_menu;
2037                         mar_menu_set_slider(ptr_win);
2038                         WindowItems(ptr_win,SCROLL_KEYS,scroll_keys);
2039                         if((d_exit=X_Form_Do(NULL))!=W_ABANDON){
2040                                 my_close_dialog(dlg_info,FALSE);
2041                                 if(d_exit!=W_CLOSED)
2042                                         ob_undostate(z_ob,d_exit&NO_CLICK,SELECTED);
2043                         }
2044                 }
2045                 Event_Handler(NULL,NULL);
2046                 ob_set_text(z_ob,QLINE,tmp_button);
2047                 break;
2048         case NHW_MENU:
2049                 if(WIN_MESSAGE != WIN_ERR && Gem_nhwindow[WIN_MESSAGE].gw_window)
2050                         mar_display_nhwindow(WIN_MESSAGE);
2051                 z_ob=zz_oblist[LINES];
2052                 scroll_menu.vsize=Anz_inv_lines;
2053                 scroll_menu.vpos=0;
2054                 z_ob[LINESLIST].ob_spec.userblk=&ub_inventory;
2055                 if((Menu_title)&&(wind!=WIN_INVEN))     /* because I sets no Menu_title */
2056                         Max(&Inv_breite,gr_cw*strlen(Menu_title)+16);
2057                 scroll_menu.px_vline=menu_font.ch;
2058                 scroll_menu.px_hline=menu_font.cw;
2059                 mar_di_mode=mar_set_inv_win(Anz_inv_lines, Inv_breite, NHW_MENU);
2060                 tmp_button=ob_get_text(z_ob,QLINE,0);
2061                 ob_set_text(z_ob,QLINE,Inv_how!=PICK_NONE ? strCancel : strOk );
2062                 ob_doflag(z_ob,LINESLIST,TOUCHEXIT);
2063                 Event_Handler(Inv_Init, Inv_Handler);
2064                 if((Inv_dialog=open_dialog(z_ob,(wind==WIN_INVEN) ? "Inventory" : (Menu_title ? Menu_title : "Staun"), NULL, NULL, mar_ob_mapcenter(z_ob), FALSE, mar_di_mode, FAIL, NULL, NULL))!=NULL){
2065                         WIN *ptr_win=Inv_dialog->di_win;
2066
2067                         ptr_win->scroll=&scroll_menu;
2068                         mar_menu_set_slider(ptr_win);
2069                         WindowItems(ptr_win,SCROLL_KEYS,scroll_keys);
2070                         do{
2071                                 int y_wo,x_wo,ru_w=1,ru_h=1;
2072                                 GRECT oarea;
2073                                 Gem_menu_item *it;
2074                                 d_exit=X_Form_Do(NULL);
2075                                 if((d_exit&NO_CLICK)==LINESLIST){
2076                                         ob_pos(z_ob,LINESLIST,&oarea);
2077                                         if(mouse(&x_wo,&y_wo) && Inv_how==PICK_ANY){
2078                                                 graf_rt_rubberbox(FALSE,x_wo,y_wo,FAIL,FAIL,&oarea,&ru_w,&ru_h,NULL);
2079                                                 invert_all_on_page((int)((y_wo-oarea.g_y)/menu_font.ch+scroll_menu.vpos),(ru_h+menu_font.ch-1)/menu_font.ch,0);
2080                                         }else{
2081                                                 for(it=invent_list,i=0;i<((y_wo-oarea.g_y)/menu_font.ch+scroll_menu.vpos) && it;it=it->Gmi_next,i++);
2082                                                 if(it && it->Gmi_identifier){
2083                                                         it->Gmi_selected=!it->Gmi_selected;
2084                                                         it->Gmi_count= count==0L ? -1L : count;
2085                                                         count = 0L;
2086                                                         if(Inv_how!=PICK_ANY)
2087                                                                 break;
2088                                                 }       /* identifier */
2089                                         }
2090                                         oarea.g_x=(oarea.g_x+23+2*menu_font.cw) & ~7;
2091                                         oarea.g_y=y_wo-(y_wo-oarea.g_y)%menu_font.ch;
2092                                         oarea.g_w=menu_font.cw;
2093                                         oarea.g_h=((ru_h+menu_font.ch-1)/menu_font.ch)*menu_font.ch;
2094                                         ob_draw_chg(Inv_dialog,LINESLIST,&oarea,FAIL);
2095                                 }
2096                                 if(Inv_how==PICK_ANY){
2097                                         ob_set_text(Inv_dialog->di_tree,QLINE,strCancel);
2098                                         for(it=invent_list;it;it=it->Gmi_next)
2099                                                 if(it->Gmi_identifier && it->Gmi_selected){
2100                                                         ob_set_text(Inv_dialog->di_tree,QLINE,strOk);
2101                                                         break;
2102                                                 }
2103                                         ob_draw_chg(Inv_dialog,QLINE,NULL,FAIL);
2104                                 }
2105                         }while((d_exit&NO_CLICK)==LINESLIST);
2106                         if(d_exit!=W_ABANDON){
2107                                 my_close_dialog(Inv_dialog,FALSE);
2108                                 if(d_exit!=W_CLOSED)
2109                                         ob_undostate(z_ob,d_exit&NO_CLICK,SELECTED);
2110                         }
2111                 }
2112                 Event_Handler(NULL,NULL);
2113                 ob_set_text(z_ob,QLINE,tmp_button);
2114                 break;
2115         case NHW_MAP:
2116                 if(p_Gw->gw_window==NULL){
2117                         calc_std_winplace(NHW_MAP,&p_Gw->gw_place);
2118                         window_border(MAP_GADGETS,0,0,Tile_width*(COLNO-1),Tile_heigth*ROWNO, &g_mapmax);
2119                         p_Gw->gw_window=open_window(md, md, NULL, zz_oblist[NHICON], MAP_GADGETS, TRUE, 128, 128, &g_mapmax, &p_Gw->gw_place, &scroll_map, win_draw_map, NULL, XM_TOP|XM_BOTTOM|XM_SIZE);
2120                         WindowItems(p_Gw->gw_window,SCROLL_KEYS-1,scroll_keys); /* ClrHome centers on u */
2121                         mar_clear_map();
2122                 }
2123                 if(p_Gw->gw_dirty){
2124                         area.g_x=p_Gw->gw_window->work.g_x+scroll_map.px_hline*(dirty_map_area.g_x-scroll_map.hpos);
2125                         area.g_y=p_Gw->gw_window->work.g_y+scroll_map.px_vline*(dirty_map_area.g_y-scroll_map.vpos);
2126                         area.g_w=(dirty_map_area.g_w-dirty_map_area.g_x+1)*scroll_map.px_hline;
2127                         area.g_h=(dirty_map_area.g_h-dirty_map_area.g_y+1)*scroll_map.px_vline;
2128
2129                         redraw_window(p_Gw->gw_window,&area);
2130
2131                         dirty_map_area.g_x=COLNO-1;
2132                         dirty_map_area.g_y=ROWNO;
2133                         dirty_map_area.g_w=
2134                         dirty_map_area.g_h=0;
2135                 }
2136                 break;
2137         case NHW_MESSAGE:
2138                 if(p_Gw->gw_window==NULL){
2139                         calc_std_winplace(NHW_MESSAGE,&p_Gw->gw_place);
2140                         z_ob=zz_oblist[MSGWIN];
2141                         magx=0; /* MAR -- Fake E_GEM to remove Backdropper */
2142                         p_Gw->gw_window=open_window(NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, &p_Gw->gw_place, NULL, mar_draw_window, z_ob, XM_TOP|XM_BOTTOM|XM_SIZE);
2143                         magx=tmp_magx;
2144                         window_size(p_Gw->gw_window,&p_Gw->gw_window->curr);
2145                         p_Gw->gw_dirty=TRUE;
2146                 }
2147
2148                 if(p_Gw->gw_dirty){
2149                         ob_pos(zz_oblist[MSGWIN],MSGLINES,&area);
2150                         while(messages_pro_zug>3){
2151                                 messages_pro_zug-=3;
2152                                 msg_pos+=3;
2153                                 redraw_window(p_Gw->gw_window,&area);
2154                                 mar_more();
2155                         }
2156                         msg_pos+=messages_pro_zug;
2157                         messages_pro_zug=0;
2158                         if(msg_pos>msg_max) msg_pos=msg_max;
2159                         redraw_window(p_Gw->gw_window,&area);
2160                         mar_message_pause=FALSE;
2161                 }
2162                 break;
2163         case NHW_STATUS:
2164                 if(p_Gw->gw_window==NULL){
2165                         z_ob=zz_oblist[STATUSLINE];
2166                         calc_std_winplace(NHW_STATUS,&p_Gw->gw_place);
2167                         magx=0; /* MAR -- Fake E_GEM to remove Backdropper */
2168                         p_Gw->gw_window=open_window(NULL, NULL, NULL, NULL, 0, FALSE, 0, 0, NULL, &p_Gw->gw_place, NULL, mar_draw_window, z_ob, XM_TOP|XM_BOTTOM|XM_SIZE);
2169                         magx=tmp_magx;
2170                         /* Because 2*status_font.ch is smaller then e_gem expects the minimum win_height */
2171                         p_Gw->gw_window->min_h=z_ob[ROOT].ob_height;
2172                         window_size(p_Gw->gw_window,&p_Gw->gw_place);
2173                         p_Gw->gw_dirty=TRUE;
2174                         add_dirty_rect(dr_stat,&p_Gw->gw_place);
2175                 }
2176                 while(get_dirty_rect(dr_stat,&area)){
2177                         area.g_x=(area.g_x+p_Gw->gw_window->work.g_x+2*status_font.cw+6)&~7;
2178                         area.g_y+=p_Gw->gw_window->work.g_y;
2179                         redraw_window(p_Gw->gw_window,&area);
2180                 }
2181                 break;
2182         default:
2183                 if(p_Gw->gw_dirty)
2184                         redraw_window(p_Gw->gw_window,NULL);
2185         }
2186         p_Gw->gw_dirty=FALSE;
2187 }
2188
2189 /************************* create_window *******************************/
2190
2191 int mar_hol_win_type(window)
2192 winid   window;
2193 {
2194         return(Gem_nhwindow[window].gw_type);
2195 }
2196
2197 winid
2198 mar_create_window(type)
2199 int type;
2200 {
2201         winid newid;
2202         static char name[]="Gem";
2203         int i;
2204         struct gw *p_Gw=&Gem_nhwindow[0];
2205
2206         for(newid = 0; p_Gw->gw_type && newid < MAXWIN; newid++, p_Gw++);
2207
2208         switch(type){
2209         case NHW_MESSAGE:
2210                 message_line=(char **)m_alloc(msg_anz*sizeof(char *));
2211                 message_age=(int *)m_alloc(msg_anz*sizeof(int));
2212                 for(i=0;i<msg_anz;i++){
2213                         message_age[i]=FALSE;
2214                         message_line[i]=(char *)m_alloc((MSGLEN+1)*sizeof(char));
2215                         *message_line[i]=0;
2216                 }
2217                 dr_msg=new_dirty_rect(10);
2218                 if (!dr_msg) panic("Memory allocation failure (dr_msg)");
2219                 break;
2220         case NHW_STATUS:
2221                 status_line=(char **)m_alloc(2*sizeof(char *));
2222                 for(i=0;i<2;i++){
2223                         status_line[i]=(char *)m_alloc(status_w*sizeof(char));
2224                         memset(status_line[i],0,status_w);
2225                 }
2226                 dr_stat=new_dirty_rect(10);
2227                 if (!dr_stat) panic("Memory allocation failure (dr_stat)");
2228                 break;
2229         case NHW_MAP:
2230                 map_glyphs=(char **)m_alloc((long)ROWNO*sizeof(char *));
2231                 for(i=0;i<ROWNO;i++){
2232                         map_glyphs[i]=(char *)m_alloc((long)COLNO*sizeof(char));
2233                         *map_glyphs[i]=map_glyphs[i][COLNO-1]=0;
2234                 }
2235                 dr_map=new_dirty_rect(10);
2236                 if (!dr_map) panic("Memory allocation failure (dr_map)");
2237
2238                 mar_clear_map();
2239                 break;
2240         case NHW_MENU:
2241         case NHW_TEXT:  /* They are no more treated as dialog */
2242                 break;
2243         default:
2244                 p_Gw->gw_window=open_window("Sonst", name, NULL, NULL, NAME|MOVER|CLOSER, 0, 0, 0, NULL, &p_Gw->gw_place, NULL, NULL, NULL, XM_TOP|XM_BOTTOM|XM_SIZE);
2245                 break;
2246         }
2247
2248         p_Gw->gw_type=type;
2249
2250         return(newid);
2251 }
2252
2253 void
2254 mar_change_menu_2_text(win)
2255 winid win;
2256 {
2257         Gem_nhwindow[win].gw_type=NHW_TEXT;
2258 }
2259
2260 /************************* mar_clear_map *******************************/
2261
2262 void
2263 mar_clear_map()
2264 {
2265         int pla[8];
2266         int x,y;
2267
2268         pla[0]=pla[1]=pla[4]=pla[5]=0;
2269         pla[2]=pla[6]=scroll_map.px_hline*(COLNO-1)-1;
2270         pla[3]=pla[7]=scroll_map.px_vline*ROWNO-1;
2271         for(y=0;y<ROWNO;y++) for(x=0;x<COLNO-1;x++)
2272                 map_glyphs[y][x]=' ';
2273         vro_cpyfm(x_handle, ALL_BLACK,pla,&Tile_bilder,&Map_bild);      /* MAR -- 17.Mar 2002 Hmm, what if FontCol_Bild is bigger? */
2274         if(WIN_MAP != WIN_ERR && Gem_nhwindow[WIN_MAP].gw_window)
2275                 redraw_window(Gem_nhwindow[WIN_MAP].gw_window,NULL);
2276 }
2277
2278 /************************* destroy_window *******************************/
2279
2280 void
2281 mar_destroy_nhwindow(window)
2282 winid window;
2283 {
2284         int i;
2285
2286         switch(Gem_nhwindow[window].gw_type){
2287         case NHW_TEXT:
2288                 for(i=0;i<Anz_text_lines;i++)
2289                         free(text_lines[i]);
2290                 null_free(text_lines);
2291                 Anz_text_lines=0;
2292                 use_rip=FALSE;
2293                 break;
2294         case NHW_MENU:
2295                 Gem_start_menu(window); /* delete invent_list */
2296                 test_free(Menu_title);
2297                 break;
2298         case 0: /* No window available, probably an error message? */
2299                 break;
2300         default:
2301                 close_window( Gem_nhwindow[window].gw_window, 0 );
2302                 break;
2303         }
2304         Gem_nhwindow[window].gw_window=NULL;
2305         Gem_nhwindow[window].gw_type=0;
2306         Gem_nhwindow[window].gw_dirty=FALSE;
2307
2308         if(window==WIN_MAP){
2309                 for(i=0;i<ROWNO;i++){
2310                         free(map_glyphs[i]);
2311                 }
2312                 null_free(map_glyphs);
2313                 WIN_MAP=WIN_ERR;
2314         }
2315         if(window==WIN_STATUS){
2316                 for(i=0;i<2;i++)
2317                         free(status_line[i]);
2318                 null_free(status_line);
2319                 WIN_STATUS=WIN_ERR;
2320         }
2321         if(window==WIN_MESSAGE){
2322                 for(i=0;i<msg_anz;i++)
2323                         free(message_line[i]);
2324                 null_free(message_line);
2325                 null_free(message_age);
2326                 WIN_MESSAGE=WIN_ERR;
2327         }
2328         if(window==WIN_INVEN)
2329                 WIN_INVEN=WIN_ERR;
2330 }
2331
2332 /************************* nh_poskey *******************************/
2333
2334 void mar_set_margin(int m){
2335         Max(&m,0);
2336         Min(&m,min(ROWNO,COLNO));       /* MAR 16.Mar 2002 -- the larger the less sense */
2337         scroll_margin=m;
2338 }
2339 void
2340 mar_cliparound()
2341 {
2342         if(WIN_MAP!=WIN_ERR && Gem_nhwindow[WIN_MAP].gw_window){
2343                 int     breite=scroll_margin>0 ? scroll_margin : max(scroll_map.hpage/4,1),
2344                                 hoehe=scroll_margin>0 ? scroll_margin : max(scroll_map.vpage/4,1),
2345                                 adjust_needed;
2346                 adjust_needed=FALSE;
2347                 if ((map_cursx < scroll_map.hpos + breite) || (map_cursx >= scroll_map.hpos + scroll_map.hpage - breite)){
2348                         scroll_map.hpos=map_cursx - scroll_map.hpage/2;
2349                         adjust_needed=TRUE;
2350                 }
2351                 if ((map_cursy < scroll_map.vpos + hoehe) || (map_cursy >= scroll_map.vpos + scroll_map.vpage - hoehe)){
2352                         scroll_map.vpos=map_cursy - scroll_map.vpage/2;
2353                         adjust_needed=TRUE;
2354                 }
2355                 if(adjust_needed)
2356                         scroll_window(Gem_nhwindow[WIN_MAP].gw_window,WIN_SCROLL,NULL);
2357         }
2358 }
2359
2360 void
2361 mar_update_value()
2362 {
2363         if(WIN_MESSAGE!=WIN_ERR){
2364                 mar_message_pause=FALSE;
2365                 mar_esc_pressed=FALSE;
2366                 mar_display_nhwindow(WIN_MESSAGE);
2367         }
2368
2369         if(WIN_MAP!=WIN_ERR)
2370                 mar_cliparound();
2371
2372         if(WIN_STATUS!=WIN_ERR){
2373                 mar_check_hilight_status();
2374                 mar_display_nhwindow(WIN_STATUS);
2375         }
2376 }
2377
2378 int
2379 Main_Init(xev,availiable)
2380 XEVENT *xev;
2381 int availiable;
2382 {
2383         xev->ev_mb1mask=
2384         xev->ev_mb1state=1;
2385         xev->ev_mb1clicks=
2386         xev->ev_mb2clicks=
2387         xev->ev_mb2mask=
2388         xev->ev_mb2state=2;
2389         return((MU_KEYBD|MU_BUTTON1|MU_BUTTON2|MU_MESAG)&availiable);
2390 }
2391
2392 /*
2393  * return a key, or 0, in which case a mouse button was pressed
2394  * mouse events should be returned as character postitions in the map window.
2395  */
2396 /*ARGSUSED*/
2397 int
2398 mar_nh_poskey(x, y, mod)
2399     int *x, *y, *mod;
2400 {
2401         static XEVENT xev;
2402         int retval, ev;
2403
2404         xev.ev_mflags=Main_Init(&xev,0xFFFF);
2405         ev=Event_Multi(&xev);
2406
2407         retval=FAIL;
2408
2409         if(ev&MU_KEYBD){
2410                 char ch = xev.ev_mkreturn&0x00FF;
2411                 char scan = (xev.ev_mkreturn & 0xff00) >> 8;
2412                 int shift = xev.ev_mmokstate;
2413                 const struct pad *kpad;
2414
2415                 /* Translate keypad keys */
2416                 if (iskeypad(scan)) {
2417                         kpad = mar_iflags_numpad()==1 ? numpad : keypad;
2418                         if (shift & K_SHIFT)
2419                                 ch = kpad[scan - KEYPADLO].shift;
2420                         else if (shift & K_CTRL){
2421                                 if(scan>=0x67 && scan<=0x6f && scan!=0x6b){
2422                                         send_key(kpad[scan - KEYPADLO].normal);
2423                                         ch = 'g';
2424                                 }else{
2425                                 ch = kpad[scan - KEYPADLO].cntrl;
2426                                 }
2427                         }else
2428                                 ch = kpad[scan - KEYPADLO].normal;
2429                 }
2430                 if(scan==SCANHOME)
2431                         mar_cliparound();
2432                 else if(scan == SCANF1)
2433                         retval='h';
2434                 else if(scan == SCANF2){
2435                         mar_set_tile_mode(!mar_set_tile_mode(FAIL));
2436                         retval=C('l');  /* trigger full-redraw */
2437                 }else if(scan == SCANF3){
2438                         draw_cursor=!draw_cursor;
2439                         mar_curs(map_cursx,map_cursy);
2440                         mar_display_nhwindow(WIN_MAP);
2441                 }else if(scan == SCANF4){       /* Font-Selector */
2442                         if(!CallFontSelector(0,FAIL,FAIL,FAIL,FAIL)){
2443                                 xalert(1,1,X_ICN_ALERT,NULL,SYS_MODAL,BUTTONS_RIGHT,TRUE,"Hello","Fontselector not available!",NULL);
2444                         }
2445                 }else if(!ch && shift&K_CTRL && scan==-57){
2446                         /* MAR -- nothing ignore Ctrl-Alt-Clr/Home == MagiC's restore screen */
2447                 }else{
2448                         if(!ch)
2449                                 ch=(char)M(tolower(scan_2_ascii(xev.ev_mkreturn,shift)));
2450                         if(((int)ch)==-128)
2451                                 ch='\033';
2452                         retval=ch;
2453                 }
2454         }
2455
2456         if(ev&MU_BUTTON1 || ev&MU_BUTTON2){
2457                 int ex=xev.ev_mmox, ey=xev.ev_mmoy;
2458                 WIN *akt_win=window_find(ex,ey);
2459
2460                 if(WIN_MAP != WIN_ERR && akt_win==Gem_nhwindow[WIN_MAP].gw_window){
2461                         *x=max(min((ex-akt_win->work.g_x)/scroll_map.px_hline+scroll_map.hpos,COLNO-1),0)+1;
2462                         *y=max(min((ey-akt_win->work.g_y)/scroll_map.px_vline+scroll_map.vpos,ROWNO),0);
2463                         *mod=xev.ev_mmobutton;
2464                         retval=0;
2465                 }else if(WIN_STATUS != WIN_ERR && akt_win==Gem_nhwindow[WIN_STATUS].gw_window){
2466                         move_win(akt_win);
2467                 }else if(WIN_MESSAGE != WIN_ERR && akt_win==Gem_nhwindow[WIN_MESSAGE].gw_window){
2468                         message_handler(ex,ey);
2469                 }
2470         }
2471
2472         if(ev&MU_MESAG){
2473                 int *buf=xev.ev_mmgpbuf;
2474                 char *str;
2475                 OBJECT *z_ob=zz_oblist[MENU];
2476
2477            switch(*buf) {
2478                 case MN_SELECTED :
2479                         menu_tnormal(z_ob,buf[3],TRUE); /* unselect menu header */
2480                         str=ob_get_text(z_ob,buf[4],0);
2481                         str+=strlen(str)-2;
2482                         switch(*str){
2483                         case ' ':       /* just that command */
2484                                 retval=str[1];
2485                                 break;
2486                         case '\005':    /* Alt command */
2487                         case '\007':
2488                                 retval=M(str[1]);
2489                                 break;
2490                         case '^':       /* Ctrl command */
2491                                 retval=C(str[1]);
2492                                 break;
2493                         case 'f':       /* Func Key */
2494                                 switch(str[1]){
2495                                 case '1':
2496                                         retval='h';
2497                                         break;
2498                                 case '2':
2499                                         mar_set_tile_mode(!mar_set_tile_mode(FAIL));
2500                                         retval=C('l');  /* trigger full-redraw */
2501                                         break;
2502                                 case '3':
2503                                         draw_cursor=!draw_cursor;
2504                                         mar_curs(map_cursx,map_cursy);
2505                                         mar_display_nhwindow(WIN_MAP);
2506                                         break;
2507                                 default:
2508                                 }
2509                                 break;
2510                         default:
2511                                 mar_about();
2512                                 break;
2513                         }
2514                         break;  /* MN_SELECTED */
2515                 case WM_CLOSED:
2516                         WindowHandler(W_ICONIFYALL,NULL,NULL);
2517                         break;
2518                 case AP_TERM:
2519                         retval='S';
2520                         break;
2521                 case FONT_CHANGED:
2522                         if(buf[3]>=0){
2523                                 if(buf[3]==Gem_nhwindow[WIN_MESSAGE].gw_window->handle){
2524                                         mar_set_fontbyid(NHW_MESSAGE,buf[4],buf[5]);
2525                                         mar_display_nhwindow(WIN_MESSAGE);
2526                                 }else if(buf[3]==Gem_nhwindow[WIN_MAP].gw_window->handle){
2527                                         mar_set_fontbyid(NHW_MAP,buf[4],buf[5]);
2528                                         mar_display_nhwindow(WIN_MAP);
2529                                 }else if(buf[3]==Gem_nhwindow[WIN_STATUS].gw_window->handle){
2530                                         mar_set_fontbyid(NHW_STATUS,buf[4],buf[5]);
2531                                         mar_display_nhwindow(WIN_STATUS);
2532                                 }
2533                                 FontAck(buf[1],1);
2534                         }
2535                         break;
2536                 default:
2537                         break;
2538                 }
2539         }       /* MU_MESAG */
2540
2541         if(retval==FAIL)
2542                 retval=mar_nh_poskey(x,y,mod);
2543
2544         return(retval);
2545 }
2546
2547 int
2548 Gem_nh_poskey(x, y, mod)
2549     int *x, *y, *mod;
2550 {
2551         mar_update_value();
2552         return(mar_nh_poskey(x, y, mod));
2553 }
2554
2555 void
2556 Gem_delay_output()
2557 {
2558         Event_Timer(50,0,FALSE);        /* wait 50ms */
2559 }
2560
2561 int
2562 Gem_doprev_message()
2563 {
2564         if(msg_pos>2){
2565                 msg_pos--;
2566         if(WIN_MESSAGE != WIN_ERR)
2567                 Gem_nhwindow[WIN_MESSAGE].gw_dirty=TRUE;
2568         mar_display_nhwindow(WIN_MESSAGE);
2569         }
2570         return(0);
2571 }
2572
2573 /************************* print_glyph *******************************/
2574
2575 int mar_set_rogue(int);
2576
2577 int
2578 mar_set_tile_mode(tiles)
2579 int tiles;
2580 {
2581         static int tile_mode=TRUE;
2582         static GRECT prev;
2583         WIN *z_w=WIN_MAP!=WIN_ERR ? Gem_nhwindow[WIN_MAP].gw_window : NULL;
2584
2585         if(tiles<0)
2586                 return(tile_mode);
2587         else if(!z_w)
2588                 tile_mode=tiles;
2589         else if(tile_mode==tiles || (mar_set_rogue(FAIL) && tiles))
2590                         return(FAIL);
2591         else{
2592                 GRECT tmp;
2593
2594                 tile_mode=tiles;
2595                 scroll_map.px_hline= tiles ? Tile_width : map_font.cw;
2596                 scroll_map.px_vline= tiles ? Tile_heigth : map_font.ch;
2597                 window_border(MAP_GADGETS,0,0,scroll_map.px_hline*(COLNO-1),scroll_map.px_vline*ROWNO, &tmp);
2598                 z_w->max.g_w=tmp.g_w;
2599                 z_w->max.g_h=tmp.g_h;
2600                 if(tiles)
2601                         z_w->curr=prev;
2602                 else
2603                         prev=z_w->curr;
2604
2605                 window_reinit(z_w,md,md,NULL,FALSE,FALSE);
2606         }
2607         return(FAIL);
2608 }
2609
2610 int
2611 mar_set_rogue(what)
2612 int what;
2613 {
2614         static int rogue=FALSE, prev_mode=TRUE;
2615
2616         if(what<0) return(rogue);
2617         if(what!=rogue){
2618                 rogue=what;
2619                 if(rogue){
2620                         prev_mode=mar_set_tile_mode(FAIL);
2621                         mar_set_tile_mode(FALSE);
2622                 }else
2623                         mar_set_tile_mode(prev_mode);
2624         }
2625         return(FAIL);
2626 }
2627
2628 void
2629 mar_add_pet_sign(window,x,y)
2630 winid window;
2631 int x, y;
2632 {
2633         if(window != WIN_ERR && window==WIN_MAP){
2634                 static int pla[8]={0,0,7,7,0,0,0,0}, colindex[2]={RED,WHITE};
2635
2636                 pla[4]=pla[6]=scroll_map.px_hline*x;
2637                 pla[5]=pla[7]=scroll_map.px_vline*y;
2638                 pla[6]+=7;
2639                 pla[7]+=6;
2640                 vrt_cpyfm(x_handle,MD_TRANS,pla,&Pet_Mark,&Map_bild,colindex);
2641         }
2642 }
2643
2644 void
2645 mar_print_glyph(window, x, y, gl)
2646 winid window;
2647 int x, y, gl;
2648 {
2649         if(window != WIN_ERR && window==WIN_MAP){
2650         static int pla[8];
2651
2652                         pla[2]=pla[0]=(gl%Tiles_per_line)*Tile_width;
2653                         pla[3]=pla[1]=(gl/Tiles_per_line)*Tile_heigth;
2654                         pla[2]+=Tile_width-1;
2655                         pla[3]+=Tile_heigth-1;
2656                         pla[6]=pla[4]=Tile_width*x;     /* x_wert to */
2657                         pla[7]=pla[5]=Tile_heigth*y;    /* y_wert to */
2658                         pla[6]+=Tile_width-1;
2659                         pla[7]+=Tile_heigth-1;
2660
2661                         vro_cpyfm(x_handle, gl!=-1 ? S_ONLY : ALL_BLACK, pla, &Tile_bilder, &Map_bild);
2662                 }
2663         }
2664
2665 void
2666 mar_print_char(window, x, y, ch, col)
2667 winid window;
2668 int x, y;
2669 char ch;
2670 int col;
2671 {
2672         if(window != WIN_ERR && window==WIN_MAP){
2673                 static int gem_color[16]={ 9, 2,11,10, 4, 7, 8, 15,0,14, 3, 6, 5, 13,15, 0};
2674                 int pla[8], colindex[2];
2675
2676                 map_glyphs[y][x]=ch;
2677
2678                 pla[0]=
2679                 pla[1]=0;
2680                 pla[2]=map_font.cw-1;
2681                 pla[3]=map_font.ch-1;
2682                 pla[6]=pla[4]=map_font.cw*x;
2683                 pla[7]=pla[5]=map_font.ch*y;
2684                 pla[6]+=map_font.cw-1;
2685                 pla[7]+=map_font.ch-1;
2686                 colindex[0]=gem_color[col];
2687                 colindex[1]=WHITE;
2688                 vrt_cpyfm(x_handle,MD_REPLACE,pla,&Black_bild,&FontCol_Bild,colindex);
2689         }
2690 }
2691
2692 /************************* getlin *******************************/
2693
2694 void
2695 Gem_getlin(ques, input)
2696 const char *ques;
2697 char *input;
2698 {
2699         OBJECT *z_ob=zz_oblist[LINEGET];
2700         int d_exit, length;
2701         char *pr[2], *tmp;
2702
2703         if(WIN_MESSAGE != WIN_ERR && Gem_nhwindow[WIN_MESSAGE].gw_window)
2704                 mar_display_nhwindow(WIN_MESSAGE);
2705
2706         z_ob[LGPROMPT].ob_type=G_USERDEF;
2707         z_ob[LGPROMPT].ob_spec.userblk=&ub_prompt;
2708         z_ob[LGPROMPT].ob_height=2*gr_ch;
2709
2710         length=z_ob[LGPROMPT].ob_width/gr_cw;
2711         if(strlen(ques)>length){
2712                 tmp=ques+length;
2713                 while(*tmp!=' ' && tmp>=ques){
2714                         tmp--;
2715                 }
2716                 if(tmp<=ques) tmp=ques+length;  /* Mar -- Oops, what a word :-) */
2717                 pr[0]=ques;
2718                 *tmp=0;
2719                 pr[1]=++tmp;
2720         }else{
2721                 pr[0]=ques;
2722                 pr[1]=NULL;
2723         }
2724         ub_prompt.ub_parm=(long)pr;
2725
2726         ob_clear_edit(z_ob);
2727         d_exit=xdialog(z_ob, nullstr, NULL, NULL, mar_ob_mapcenter(z_ob), FALSE, DIALOG_MODE);
2728         Event_Timer(0,0,TRUE);
2729
2730         if(d_exit==W_CLOSED || d_exit==W_ABANDON || (d_exit&NO_CLICK)==QLG){
2731                 *input='\033';
2732                 input[1]=0;
2733         }else
2734                 strncpy(input,ob_get_text(z_ob,LGREPLY, 0),length);
2735 }
2736
2737 /************************* ask_direction *******************************/
2738
2739 #define Dia_Init K_Init
2740
2741 int
2742 Dia_Handler(xev)
2743 XEVENT *xev;
2744 {
2745         int ev=xev->ev_mwich;
2746         char ch=(char)(xev->ev_mkreturn&0x00FF);
2747
2748         if(ev&MU_KEYBD){
2749                 WIN *w;
2750                 DIAINFO *dinf;
2751
2752                 switch(ch){
2753                 case 's':
2754                         send_key((int)(mar_iflags_numpad() ? '5' : '.'));
2755                         break;
2756                 case '.':
2757                         send_key('5');  /* MAR -- '.' is a button if numpad isn't set */
2758                         break;
2759                 case '\033':    /*ESC*/
2760                         if((w=get_top_window()) && (dinf=(DIAINFO *)w->dialog) && dinf->di_tree==zz_oblist[DIRECTION]){
2761                                 my_close_dialog(dinf,FALSE);
2762                                 break;
2763                         }
2764                         /* Fall thru */
2765                 default:
2766                         ev &= ~MU_KEYBD;        /* let the dialog handle it */
2767                         break;
2768                 }
2769         }
2770         return(ev);
2771 }
2772
2773 int
2774 mar_ask_direction()
2775 {
2776         int d_exit;
2777         OBJECT *z_ob=zz_oblist[DIRECTION];
2778
2779         Event_Handler(Dia_Init,Dia_Handler);
2780         mar_set_dir_keys();
2781         d_exit=xdialog(z_ob, nullstr, NULL, NULL, mar_ob_mapcenter(z_ob), FALSE, DIALOG_MODE);
2782         Event_Timer(0,0,TRUE);
2783         Event_Handler(NULL,NULL);
2784
2785         if(d_exit==W_CLOSED || d_exit==W_ABANDON)
2786                 return('\033');
2787         if((d_exit&NO_CLICK)==DIRDOWN)
2788                 return('>');
2789         if((d_exit&NO_CLICK)==DIRUP)
2790                 return('<');
2791         if((d_exit&NO_CLICK)==(DIR1+8)) /* 5 or . */
2792                 return('.');
2793         return(*ob_get_text(z_ob,d_exit&NO_CLICK,0));
2794 }
2795
2796 /************************* yn_function *******************************/
2797
2798
2799 #define any_init M_Init
2800
2801 static int
2802 any_handler(xev)
2803 XEVENT *xev;
2804 {
2805         int ev=xev->ev_mwich;
2806
2807         if(ev&MU_MESAG){
2808                 int *buf=xev->ev_mmgpbuf;
2809
2810                 if(*buf==OBJC_EDITED)
2811                         my_close_dialog(*(DIAINFO **)&buf[4], FALSE);
2812                 else
2813                         ev &= ~MU_MESAG;
2814         }
2815         return(ev);
2816 }
2817
2818 int
2819 send_yn_esc(char ch)
2820 {
2821         static char esc_char=0;
2822
2823         if(ch<0){
2824                 if(esc_char){
2825                         send_key((int)esc_char);
2826                         return(TRUE);
2827                 }
2828                 return(FALSE);
2829         }else
2830                 esc_char=ch;
2831         return(TRUE);
2832 }
2833
2834 #define single_init K_Init
2835
2836 static int
2837 single_handler(xev)
2838 XEVENT *xev;
2839 {
2840         int ev=xev->ev_mwich;
2841
2842         if(ev&MU_KEYBD){
2843                 char ch=(char)xev->ev_mkreturn&0x00FF;
2844                 WIN *w;
2845                 DIAINFO *dinf;
2846
2847                 switch(ch){
2848                 case ' ':
2849                         send_return();
2850                         break;
2851                 case '\033':
2852                         if((w=get_top_window()) && (dinf=(DIAINFO *)w->dialog) && dinf->di_tree==zz_oblist[YNCHOICE]){
2853                                 if(!send_yn_esc(FAIL))
2854                                         my_close_dialog(dinf,FALSE);
2855                                 break;
2856                         }
2857                         /* Fall thru */
2858                 default:
2859                         ev &= ~MU_MESAG;
2860                 }
2861         }
2862         return(ev);
2863 }
2864
2865 char
2866 Gem_yn_function(query,resp, def)
2867 const char *query,*resp;
2868 char def;
2869 {
2870         OBJECT *z_ob=zz_oblist[YNCHOICE];
2871         int d_exit, i, len;
2872         long anzahl;
2873         char *tmp;
2874         const char *ptr;
2875
2876         if(WIN_MESSAGE != WIN_ERR && Gem_nhwindow[WIN_MESSAGE].gw_window)
2877                 mar_display_nhwindow(WIN_MESSAGE);
2878
2879         /* if query for direction the special dialog */
2880         if(strstr(query,"irect"))
2881                 return(mar_ask_direction());
2882
2883         len=min(strlen(query),(max_w-8*gr_cw)/gr_cw);
2884         z_ob[ROOT].ob_width=(len+8)*gr_cw;
2885         z_ob[YNPROMPT].ob_width=gr_cw*len+8;
2886         tmp=ob_get_text(z_ob,YNPROMPT,0);
2887         ob_set_text(z_ob,YNPROMPT,mar_copy_of(query));
2888
2889         if(resp){       /* single inputs */
2890                 ob_hide(z_ob,SOMECHARS,FALSE);
2891                 ob_hide(z_ob,ANYCHAR,TRUE);
2892
2893                 if(strchr(resp,'q')) send_yn_esc('q');
2894                 else if(strchr(resp,'n')) send_yn_esc('n');
2895                 else send_yn_esc(def);  /* strictly def should be returned, but in trad. I it's 0 */
2896
2897                 if(strchr(resp,'#')){   /* count possible */
2898                         ob_hide(z_ob,YNOK,FALSE);
2899                         ob_hide(z_ob,COUNT,FALSE);
2900                 }else{  /* no count */
2901                         ob_hide(z_ob,YNOK,TRUE);
2902                         ob_hide(z_ob,COUNT,TRUE);
2903                 }
2904
2905                 if((anzahl=(long)strchr(resp,'\033'))){
2906                         anzahl-=(long)resp;
2907                 }else{
2908                         anzahl=strlen(resp);
2909                 }
2910                 for(i=0,ptr=resp;i<2*anzahl;i+=2,ptr++){
2911                         ob_hide(z_ob,YN1+i,FALSE);
2912                         mar_change_button_char(z_ob,YN1+i,*ptr);
2913                         ob_undoflag(z_ob,YN1+i,DEFAULT);
2914                         if(*ptr==def)
2915                                 ob_doflag(z_ob,YN1+i,DEFAULT);
2916                 }
2917
2918                 z_ob[SOMECHARS].ob_width=z_ob[YN1+i].ob_x+8;
2919                 z_ob[SOMECHARS].ob_height=z_ob[YN1+i].ob_y+gr_ch+gr_ch/2;
2920                 Max((int *)&z_ob[ROOT].ob_width,z_ob[SOMECHARS].ob_width+4*gr_cw);
2921                 z_ob[ROOT].ob_height=z_ob[SOMECHARS].ob_height+4*gr_ch;
2922                 if(strchr(resp,'#'))
2923                         z_ob[ROOT].ob_height=z_ob[YNOK].ob_y+2*gr_ch;
2924
2925                 for(i+=YN1;i<(YNN+1);i+=2){
2926                         ob_hide(z_ob,i,TRUE);
2927                 }
2928                 Event_Handler(single_init,single_handler);
2929         }else{  /* any input */
2930                 ob_hide(z_ob,SOMECHARS,TRUE);
2931                 ob_hide(z_ob,ANYCHAR,FALSE);
2932                 ob_hide(z_ob,YNOK,TRUE);
2933                 ob_hide(z_ob,COUNT,TRUE);
2934                 z_ob[ANYCHAR].ob_height=2*gr_ch;
2935                 z_ob[CHOSENCH].ob_y=
2936                 z_ob[CHOSENCH+1].ob_y=gr_ch/2;
2937                 z_ob[ROOT].ob_width=max(z_ob[YNPROMPT].ob_width+z_ob[YNPROMPT].ob_x,z_ob[ANYCHAR].ob_width+z_ob[ANYCHAR].ob_x)+2*gr_cw;
2938                 z_ob[ROOT].ob_height=z_ob[ANYCHAR].ob_height+z_ob[ANYCHAR].ob_y+gr_ch/2;
2939                 *ob_get_text(z_ob,CHOSENCH,0)='?';
2940                 Event_Handler(any_init,any_handler);
2941         }
2942
2943         d_exit=xdialog(z_ob, nullstr, NULL, NULL, mar_ob_mapcenter(z_ob), FALSE, DIALOG_MODE);
2944         Event_Timer(0,0,TRUE);
2945         Event_Handler(NULL,NULL);
2946         /* display of count is missing (through the core too) */
2947
2948         free(ob_get_text(z_ob,YNPROMPT,0));
2949         ob_set_text(z_ob,YNPROMPT,tmp);
2950
2951         if(resp && (d_exit==W_CLOSED || d_exit==W_ABANDON))
2952                 return('\033');
2953         if((d_exit&NO_CLICK)==YNOK){
2954                 yn_number=atol(ob_get_text(z_ob,COUNT,0));
2955                 return('#');
2956         }
2957         if(!resp)
2958                 return(*ob_get_text(z_ob,CHOSENCH,0));
2959         return(*ob_get_text(z_ob,d_exit&NO_CLICK,0));
2960 }
2961
2962 /*
2963  * Allocate a copy of the given string.  If null, return a string of
2964  * zero length.
2965  *
2966  * This is an exact duplicate of copy_of() in X11/winmenu.c.
2967  */
2968 static char *
2969 mar_copy_of(s)
2970     const char *s;
2971 {
2972     if (!s) s = nullstr;
2973     return strcpy((char *) m_alloc((unsigned) (strlen(s) + 1)), s);
2974 }
2975
2976 const char *strRP="raw_print", *strRPB="raw_print_bold";
2977
2978 void
2979 mar_raw_print(str)
2980 const char *str;
2981 {
2982                 xalert(1,FAIL,X_ICN_INFO,NULL,APPL_MODAL,BUTTONS_CENTERED,TRUE,strRP,str,NULL);
2983 }
2984
2985 void
2986 mar_raw_print_bold(str)
2987 const char *str;
2988 {
2989         char buf[BUFSZ];
2990
2991         sprintf(buf,"!%s",str);
2992         xalert(1,FAIL,X_ICN_INFO,NULL,APPL_MODAL,BUTTONS_CENTERED,TRUE,strRPB,buf,NULL);
2993 }
2994
2995 /*wingem1.c*/