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