1 /* NetHack 3.6 windows.c $NHDT-Date: 1575245096 2019/12/02 00:04:56 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.60 $ */
2 /* Copyright (c) D. Cohrs, 1993. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "hack.h"
6 #ifdef TTY_GRAPHICS
7 #include "wintty.h"
8 #endif
9 #ifdef CURSES_GRAPHICS
10 extern struct window_procs curses_procs;
11 #endif
12 #ifdef X11_GRAPHICS
13 /* Cannot just blindly include winX.h without including all of X11 stuff
14 and must get the order of include files right. Don't bother. */
15 extern struct window_procs X11_procs;
16 extern void FDECL(win_X11_init, (int));
17 #endif
18 #ifdef QT_GRAPHICS
19 extern struct window_procs Qt_procs;
20 #endif
21 #ifdef GEM_GRAPHICS
22 #include "wingem.h"
23 #endif
24 #ifdef MAC
25 extern struct window_procs mac_procs;
26 #endif
27 #ifdef BEOS_GRAPHICS
28 extern struct window_procs beos_procs;
29 extern void FDECL(be_win_init, (int));
30 FAIL /* be_win_init doesn't exist? XXX*/
31 #endif
32 #ifdef AMIGA_INTUITION
33 extern struct window_procs amii_procs;
34 extern struct window_procs amiv_procs;
35 extern void FDECL(ami_wininit_data, (int));
36 #endif
37 #ifdef WIN32_GRAPHICS
38 extern struct window_procs win32_procs;
39 #endif
40 #ifdef GNOME_GRAPHICS
41 #include "winGnome.h"
42 extern struct window_procs Gnome_procs;
43 #endif
44 #ifdef MSWIN_GRAPHICS
45 extern struct window_procs mswin_procs;
46 #endif
47 #ifdef WINCHAIN
48 extern struct window_procs chainin_procs;
49 extern void FDECL(chainin_procs_init, (int));
50 extern void *FDECL(chainin_procs_chain, (int, int, void *, void *, void *));
51
52 extern struct chain_procs chainout_procs;
53 extern void FDECL(chainout_procs_init, (int));
54 extern void *FDECL(chainout_procs_chain, (int, int, void *, void *, void *));
55
56 extern struct chain_procs trace_procs;
57 extern void FDECL(trace_procs_init, (int));
58 extern void *FDECL(trace_procs_chain, (int, int, void *, void *, void *));
59 #endif
60
61 STATIC_DCL void FDECL(def_raw_print, (const char *s));
62 STATIC_DCL void NDECL(def_wait_synch);
63
64 #ifdef DUMPLOG
65 STATIC_DCL winid FDECL(dump_create_nhwindow, (int));
66 STATIC_DCL void FDECL(dump_clear_nhwindow, (winid));
67 STATIC_DCL void FDECL(dump_display_nhwindow, (winid, BOOLEAN_P));
68 STATIC_DCL void FDECL(dump_destroy_nhwindow, (winid));
69 STATIC_DCL void FDECL(dump_start_menu, (winid));
70 STATIC_DCL void FDECL(dump_add_menu, (winid, int, const ANY_P *, CHAR_P,
71 CHAR_P, int, const char *, BOOLEAN_P));
72 STATIC_DCL void FDECL(dump_end_menu, (winid, const char *));
73 STATIC_DCL int FDECL(dump_select_menu, (winid, int, MENU_ITEM_P **));
74 STATIC_DCL void FDECL(dump_putstr, (winid, int, const char *));
75 #endif /* DUMPLOG */
76
77 #ifdef HANGUPHANDLING
78 volatile
79 #endif
80 NEARDATA struct window_procs windowprocs;
81
82 #ifdef WINCHAIN
83 #define CHAINR(x) , x
84 #else
85 #define CHAINR(x)
86 #endif
87
88 static struct win_choices {
89 struct window_procs *procs;
90 void FDECL((*ini_routine), (int)); /* optional (can be 0) */
91 #ifdef WINCHAIN
92 void *FDECL((*chain_routine), (int, int, void *, void *, void *));
93 #endif
94 } winchoices[] = {
95 #ifdef TTY_GRAPHICS
96 { &tty_procs, win_tty_init CHAINR(0) },
97 #endif
98 #ifdef CURSES_GRAPHICS
99 { &curses_procs, 0 },
100 #endif
101 #ifdef X11_GRAPHICS
102 { &X11_procs, win_X11_init CHAINR(0) },
103 #endif
104 #ifdef QT_GRAPHICS
105 { &Qt_procs, 0 CHAINR(0) },
106 #endif
107 #ifdef GEM_GRAPHICS
108 { &Gem_procs, win_Gem_init CHAINR(0) },
109 #endif
110 #ifdef MAC
111 { &mac_procs, 0 CHAINR(0) },
112 #endif
113 #ifdef BEOS_GRAPHICS
114 { &beos_procs, be_win_init CHAINR(0) },
115 #endif
116 #ifdef AMIGA_INTUITION
117 { &amii_procs,
118 ami_wininit_data CHAINR(0) }, /* Old font version of the game */
119 { &amiv_procs,
120 ami_wininit_data CHAINR(0) }, /* Tile version of the game */
121 #endif
122 #ifdef WIN32_GRAPHICS
123 { &win32_procs, 0 CHAINR(0) },
124 #endif
125 #ifdef GNOME_GRAPHICS
126 { &Gnome_procs, 0 CHAINR(0) },
127 #endif
128 #ifdef MSWIN_GRAPHICS
129 { &mswin_procs, 0 CHAINR(0) },
130 #endif
131 #ifdef WINCHAIN
132 { &chainin_procs, chainin_procs_init, chainin_procs_chain },
133 { (struct window_procs *) &chainout_procs, chainout_procs_init,
134 chainout_procs_chain },
135
136 { (struct window_procs *) &trace_procs, trace_procs_init,
137 trace_procs_chain },
138 #endif
139 { 0, 0 CHAINR(0) } /* must be last */
140 };
141
142 #ifdef WINCHAIN
143 struct winlink {
144 struct winlink *nextlink;
145 struct win_choices *wincp;
146 void *linkdata;
147 };
148 /* NB: this chain does not contain the terminal real window system pointer */
149
150 static struct winlink *chain = 0;
151
152 static struct winlink *
wl_new()153 wl_new()
154 {
155 struct winlink *wl = (struct winlink *) alloc(sizeof *wl);
156
157 wl->nextlink = 0;
158 wl->wincp = 0;
159 wl->linkdata = 0;
160
161 return wl;
162 }
163
164 static void
wl_addhead(struct winlink * wl)165 wl_addhead(struct winlink *wl)
166 {
167 wl->nextlink = chain;
168 chain = wl;
169 }
170
171 static void
wl_addtail(struct winlink * wl)172 wl_addtail(struct winlink *wl)
173 {
174 struct winlink *p = chain;
175
176 if (!chain) {
177 chain = wl;
178 return;
179 }
180 while (p->nextlink) {
181 p = p->nextlink;
182 }
183 p->nextlink = wl;
184 return;
185 }
186 #endif /* WINCHAIN */
187
188 static struct win_choices *last_winchoice = 0;
189
190 boolean
genl_can_suspend_no(VOID_ARGS)191 genl_can_suspend_no(VOID_ARGS)
192 {
193 return FALSE;
194 }
195
196 boolean
genl_can_suspend_yes(VOID_ARGS)197 genl_can_suspend_yes(VOID_ARGS)
198 {
199 return TRUE;
200 }
201
202 STATIC_OVL
203 void
def_raw_print(s)204 def_raw_print(s)
205 const char *s;
206 {
207 puts(s);
208 }
209
210 STATIC_OVL
211 void
def_wait_synch(VOID_ARGS)212 def_wait_synch(VOID_ARGS)
213 {
214 /* Config file error handling routines
215 * call wait_sync() without checking to
216 * see if it actually has a value,
217 * leading to spectacular violations
218 * when you try to execute address zero.
219 * The existence of this allows early
220 * processing to have something to execute
221 * even though it essentially does nothing
222 */
223 return;
224 }
225
226 #ifdef WINCHAIN
227 static struct win_choices *
win_choices_find(s)228 win_choices_find(s)
229 const char *s;
230 {
231 register int i;
232
233 for (i = 0; winchoices[i].procs; i++) {
234 if (!strcmpi(s, winchoices[i].procs->name)) {
235 return &winchoices[i];
236 }
237 }
238 return (struct win_choices *) 0;
239 }
240 #endif
241
242 void
choose_windows(s)243 choose_windows(s)
244 const char *s;
245 {
246 int i;
247 char *tmps = 0;
248
249 for (i = 0; winchoices[i].procs; i++) {
250 if ('+' == winchoices[i].procs->name[0])
251 continue;
252 if ('-' == winchoices[i].procs->name[0])
253 continue;
254 if (!strcmpi(s, winchoices[i].procs->name)) {
255 windowprocs = *winchoices[i].procs;
256
257 if (last_winchoice && last_winchoice->ini_routine)
258 (*last_winchoice->ini_routine)(WININIT_UNDO);
259 if (winchoices[i].ini_routine)
260 (*winchoices[i].ini_routine)(WININIT);
261 last_winchoice = &winchoices[i];
262 return;
263 }
264 }
265
266 if (!windowprocs.win_raw_print)
267 windowprocs.win_raw_print = def_raw_print;
268 if (!windowprocs.win_wait_synch)
269 /* early config file error processing routines call this */
270 windowprocs.win_wait_synch = def_wait_synch;
271
272 if (!winchoices[0].procs) {
273 raw_printf("No window types supported?");
274 nh_terminate(EXIT_FAILURE);
275 }
276 /* 50: arbitrary, no real window_type names are anywhere near that long;
277 used to prevent potential raw_printf() overflow if user supplies a
278 very long string (on the order of 1200 chars) on the command line
279 (config file options can't get that big; they're truncated at 1023) */
280 #define WINDOW_TYPE_MAXLEN 50
281 if (strlen(s) >= WINDOW_TYPE_MAXLEN) {
282 tmps = (char *) alloc(WINDOW_TYPE_MAXLEN);
283 (void) strncpy(tmps, s, WINDOW_TYPE_MAXLEN - 1);
284 tmps[WINDOW_TYPE_MAXLEN - 1] = '\0';
285 s = tmps;
286 }
287 #undef WINDOW_TYPE_MAXLEN
288
289 if (!winchoices[1].procs) {
290 config_error_add(
291 "Window type %s not recognized. The only choice is: %s",
292 s, winchoices[0].procs->name);
293 } else {
294 char buf[BUFSZ];
295 boolean first = TRUE;
296
297 buf[0] = '\0';
298 for (i = 0; winchoices[i].procs; i++) {
299 if ('+' == winchoices[i].procs->name[0])
300 continue;
301 if ('-' == winchoices[i].procs->name[0])
302 continue;
303 Sprintf(eos(buf), "%s%s",
304 first ? "" : ", ", winchoices[i].procs->name);
305 first = FALSE;
306 }
307 config_error_add("Window type %s not recognized. Choices are: %s",
308 s, buf);
309 }
310 if (tmps)
311 free((genericptr_t) tmps) /*, tmps = 0*/ ;
312
313 if (windowprocs.win_raw_print == def_raw_print
314 || WINDOWPORT("safe-startup"))
315 nh_terminate(EXIT_SUCCESS);
316 }
317
318 #ifdef WINCHAIN
319 void
addto_windowchain(s)320 addto_windowchain(s)
321 const char *s;
322 {
323 register int i;
324
325 for (i = 0; winchoices[i].procs; i++) {
326 if ('+' != winchoices[i].procs->name[0])
327 continue;
328 if (!strcmpi(s, winchoices[i].procs->name)) {
329 struct winlink *p = wl_new();
330
331 p->wincp = &winchoices[i];
332 wl_addtail(p);
333 /* NB: The ini_routine() will be called during commit. */
334 return;
335 }
336 }
337
338 windowprocs.win_raw_print = def_raw_print;
339
340 raw_printf("Window processor %s not recognized. Choices are:", s);
341 for (i = 0; winchoices[i].procs; i++) {
342 if ('+' != winchoices[i].procs->name[0])
343 continue;
344 raw_printf(" %s", winchoices[i].procs->name);
345 }
346
347 nh_terminate(EXIT_FAILURE);
348 }
349
350 void
commit_windowchain()351 commit_windowchain()
352 {
353 struct winlink *p;
354 int n;
355 int wincap, wincap2;
356
357 if (!chain)
358 return;
359
360 /* Save wincap* from the real window system - we'll restore it below. */
361 wincap = windowprocs.wincap;
362 wincap2 = windowprocs.wincap2;
363
364 /* add -chainin at head and -chainout at tail */
365 p = wl_new();
366 p->wincp = win_choices_find("-chainin");
367 if (!p->wincp) {
368 raw_printf("Can't locate processor '-chainin'");
369 exit(EXIT_FAILURE);
370 }
371 wl_addhead(p);
372
373 p = wl_new();
374 p->wincp = win_choices_find("-chainout");
375 if (!p->wincp) {
376 raw_printf("Can't locate processor '-chainout'");
377 exit(EXIT_FAILURE);
378 }
379 wl_addtail(p);
380
381 /* Now alloc() init() similar to Objective-C. */
382 for (n = 1, p = chain; p; n++, p = p->nextlink) {
383 p->linkdata = (*p->wincp->chain_routine)(WINCHAIN_ALLOC, n, 0, 0, 0);
384 }
385
386 for (n = 1, p = chain; p; n++, p = p->nextlink) {
387 if (p->nextlink) {
388 (void) (*p->wincp->chain_routine)(WINCHAIN_INIT, n, p->linkdata,
389 p->nextlink->wincp->procs,
390 p->nextlink->linkdata);
391 } else {
392 (void) (*p->wincp->chain_routine)(WINCHAIN_INIT, n, p->linkdata,
393 last_winchoice->procs, 0);
394 }
395 }
396
397 /* Restore the saved wincap* values. We do it here to give the
398 * ini_routine()s a chance to change or check them. */
399 chain->wincp->procs->wincap = wincap;
400 chain->wincp->procs->wincap2 = wincap2;
401
402 /* Call the init procs. Do not re-init the terminal real win. */
403 p = chain;
404 while (p->nextlink) {
405 if (p->wincp->ini_routine) {
406 (*p->wincp->ini_routine)(WININIT);
407 }
408 p = p->nextlink;
409 }
410
411 /* Install the chain into window procs very late so ini_routine()s
412 * can raw_print on error. */
413 windowprocs = *chain->wincp->procs;
414
415 p = chain;
416 while (p) {
417 struct winlink *np = p->nextlink;
418 free(p);
419 p = np; /* assignment, not proof */
420 }
421 }
422 #endif /* WINCHAIN */
423
424 /*
425 * tty_message_menu() provides a means to get feedback from the
426 * --More-- prompt; other interfaces generally don't need that.
427 */
428 /*ARGSUSED*/
429 char
genl_message_menu(let,how,mesg)430 genl_message_menu(let, how, mesg)
431 char let UNUSED;
432 int how UNUSED;
433 const char *mesg;
434 {
435 pline("%s", mesg);
436 return 0;
437 }
438
439 /*ARGSUSED*/
440 void
genl_preference_update(pref)441 genl_preference_update(pref)
442 const char *pref UNUSED;
443 {
444 /* window ports are expected to provide
445 their own preference update routine
446 for the preference capabilities that
447 they support.
448 Just return in this genl one. */
449 return;
450 }
451
452 char *
genl_getmsghistory(init)453 genl_getmsghistory(init)
454 boolean init UNUSED;
455 {
456 /* window ports can provide
457 their own getmsghistory() routine to
458 preserve message history between games.
459 The routine is called repeatedly from
460 the core save routine, and the window
461 port is expected to successively return
462 each message that it wants saved, starting
463 with the oldest message first, finishing
464 with the most recent.
465 Return null pointer when finished.
466 */
467 return (char *) 0;
468 }
469
470 void
genl_putmsghistory(msg,is_restoring)471 genl_putmsghistory(msg, is_restoring)
472 const char *msg;
473 boolean is_restoring;
474 {
475 /* window ports can provide
476 their own putmsghistory() routine to
477 load message history from a saved game.
478 The routine is called repeatedly from
479 the core restore routine, starting with
480 the oldest saved message first, and
481 finishing with the latest.
482 The window port routine is expected to
483 load the message recall buffers in such
484 a way that the ordering is preserved.
485 The window port routine should make no
486 assumptions about how many messages are
487 forthcoming, nor should it assume that
488 another message will follow this one,
489 so it should keep all pointers/indexes
490 intact at the end of each call.
491 */
492
493 /* this doesn't provide for reloading the message window with the
494 previous session's messages upon restore, but it does put the quest
495 message summary lines there by treating them as ordinary messages */
496 if (!is_restoring)
497 pline("%s", msg);
498 return;
499 }
500
501 #ifdef HANGUPHANDLING
502 /*
503 * Dummy windowing scheme used to replace current one with no-ops
504 * in order to avoid all terminal I/O after hangup/disconnect.
505 */
506
507 static int NDECL(hup_nhgetch);
508 static char FDECL(hup_yn_function, (const char *, const char *, CHAR_P));
509 static int FDECL(hup_nh_poskey, (int *, int *, int *));
510 static void FDECL(hup_getlin, (const char *, char *));
511 static void FDECL(hup_init_nhwindows, (int *, char **));
512 static void FDECL(hup_exit_nhwindows, (const char *));
513 static winid FDECL(hup_create_nhwindow, (int));
514 static int FDECL(hup_select_menu, (winid, int, MENU_ITEM_P **));
515 static void FDECL(hup_add_menu, (winid, int, const anything *, CHAR_P, CHAR_P,
516 int, const char *, BOOLEAN_P));
517 static void FDECL(hup_end_menu, (winid, const char *));
518 static void FDECL(hup_putstr, (winid, int, const char *));
519 static void FDECL(hup_print_glyph, (winid, XCHAR_P, XCHAR_P, int, int));
520 static void FDECL(hup_outrip, (winid, int, time_t));
521 static void FDECL(hup_curs, (winid, int, int));
522 static void FDECL(hup_display_nhwindow, (winid, BOOLEAN_P));
523 static void FDECL(hup_display_file, (const char *, BOOLEAN_P));
524 #ifdef CLIPPING
525 static void FDECL(hup_cliparound, (int, int));
526 #endif
527 #ifdef CHANGE_COLOR
528 static void FDECL(hup_change_color, (int, long, int));
529 #ifdef MAC
530 static short FDECL(hup_set_font_name, (winid, char *));
531 #endif
532 static char *NDECL(hup_get_color_string);
533 #endif /* CHANGE_COLOR */
534 static void FDECL(hup_status_update, (int, genericptr_t, int, int, int,
535 unsigned long *));
536
537 static int NDECL(hup_int_ndecl);
538 static void NDECL(hup_void_ndecl);
539 static void FDECL(hup_void_fdecl_int, (int));
540 static void FDECL(hup_void_fdecl_winid, (winid));
541 static void FDECL(hup_void_fdecl_constchar_p, (const char *));
542
543 static struct window_procs hup_procs = {
544 "hup", 0L, 0L,
545 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
546 hup_init_nhwindows,
547 hup_void_ndecl, /* player_selection */
548 hup_void_ndecl, /* askname */
549 hup_void_ndecl, /* get_nh_event */
550 hup_exit_nhwindows, hup_void_fdecl_constchar_p, /* suspend_nhwindows */
551 hup_void_ndecl, /* resume_nhwindows */
552 hup_create_nhwindow, hup_void_fdecl_winid, /* clear_nhwindow */
553 hup_display_nhwindow, hup_void_fdecl_winid, /* destroy_nhwindow */
554 hup_curs, hup_putstr, hup_putstr, /* putmixed */
555 hup_display_file, hup_void_fdecl_winid, /* start_menu */
556 hup_add_menu, hup_end_menu, hup_select_menu, genl_message_menu,
557 hup_void_ndecl, /* update_inventory */
558 hup_void_ndecl, /* mark_synch */
559 hup_void_ndecl, /* wait_synch */
560 #ifdef CLIPPING
561 hup_cliparound,
562 #endif
563 #ifdef POSITIONBAR
564 (void FDECL((*), (char *))) hup_void_fdecl_constchar_p,
565 /* update_positionbar */
566 #endif
567 hup_print_glyph,
568 hup_void_fdecl_constchar_p, /* raw_print */
569 hup_void_fdecl_constchar_p, /* raw_print_bold */
570 hup_nhgetch, hup_nh_poskey, hup_void_ndecl, /* nhbell */
571 hup_int_ndecl, /* doprev_message */
572 hup_yn_function, hup_getlin, hup_int_ndecl, /* get_ext_cmd */
573 hup_void_fdecl_int, /* number_pad */
574 hup_void_ndecl, /* delay_output */
575 #ifdef CHANGE_COLOR
576 hup_change_color,
577 #ifdef MAC
578 hup_void_fdecl_int, /* change_background */
579 hup_set_font_name,
580 #endif
581 hup_get_color_string,
582 #endif /* CHANGE_COLOR */
583 hup_void_ndecl, /* start_screen */
584 hup_void_ndecl, /* end_screen */
585 hup_outrip, genl_preference_update, genl_getmsghistory,
586 genl_putmsghistory,
587 hup_void_ndecl, /* status_init */
588 hup_void_ndecl, /* status_finish */
589 genl_status_enablefield, hup_status_update,
590 genl_can_suspend_no,
591 };
592
593 static void FDECL((*previnterface_exit_nhwindows), (const char *)) = 0;
594
595 /* hangup has occurred; switch to no-op user interface */
596 void
nhwindows_hangup()597 nhwindows_hangup()
598 {
599 char *FDECL((*previnterface_getmsghistory), (BOOLEAN_P)) = 0;
600
601 #ifdef ALTMETA
602 /* command processor shouldn't look for 2nd char after seeing ESC */
603 iflags.altmeta = FALSE;
604 #endif
605
606 /* don't call exit_nhwindows() directly here; if a hangup occurs
607 while interface code is executing, exit_nhwindows could knock
608 the interface's active data structures out from under itself */
609 if (iflags.window_inited
610 && windowprocs.win_exit_nhwindows != hup_exit_nhwindows)
611 previnterface_exit_nhwindows = windowprocs.win_exit_nhwindows;
612
613 /* also, we have to leave the old interface's getmsghistory()
614 in place because it will be called while saving the game */
615 if (windowprocs.win_getmsghistory != hup_procs.win_getmsghistory)
616 previnterface_getmsghistory = windowprocs.win_getmsghistory;
617
618 windowprocs = hup_procs;
619
620 if (previnterface_getmsghistory)
621 windowprocs.win_getmsghistory = previnterface_getmsghistory;
622 }
623
624 static void
hup_exit_nhwindows(lastgasp)625 hup_exit_nhwindows(lastgasp)
626 const char *lastgasp;
627 {
628 /* core has called exit_nhwindows(); call the previous interface's
629 shutdown routine now; xxx_exit_nhwindows() needs to call other
630 xxx_ routines directly rather than through windowprocs pointers */
631 if (previnterface_exit_nhwindows) {
632 lastgasp = 0; /* don't want exit routine to attempt extra output */
633 (*previnterface_exit_nhwindows)(lastgasp);
634 previnterface_exit_nhwindows = 0;
635 }
636 iflags.window_inited = 0;
637 }
638
639 static int
hup_nhgetch(VOID_ARGS)640 hup_nhgetch(VOID_ARGS)
641 {
642 return '\033'; /* ESC */
643 }
644
645 /*ARGSUSED*/
646 static char
hup_yn_function(prompt,resp,deflt)647 hup_yn_function(prompt, resp, deflt)
648 const char *prompt UNUSED, *resp UNUSED;
649 char deflt;
650 {
651 if (!deflt)
652 deflt = '\033';
653 return deflt;
654 }
655
656 /*ARGSUSED*/
657 static int
hup_nh_poskey(x,y,mod)658 hup_nh_poskey(x, y, mod)
659 int *x UNUSED, *y UNUSED, *mod UNUSED;
660 {
661 return '\033';
662 }
663
664 /*ARGSUSED*/
665 static void
hup_getlin(prompt,outbuf)666 hup_getlin(prompt, outbuf)
667 const char *prompt UNUSED;
668 char *outbuf;
669 {
670 Strcpy(outbuf, "\033");
671 }
672
673 /*ARGSUSED*/
674 static void
hup_init_nhwindows(argc_p,argv)675 hup_init_nhwindows(argc_p, argv)
676 int *argc_p UNUSED;
677 char **argv UNUSED;
678 {
679 iflags.window_inited = 1;
680 }
681
682 /*ARGUSED*/
683 static winid
hup_create_nhwindow(type)684 hup_create_nhwindow(type)
685 int type UNUSED;
686 {
687 return WIN_ERR;
688 }
689
690 /*ARGSUSED*/
691 static int
hup_select_menu(window,how,menu_list)692 hup_select_menu(window, how, menu_list)
693 winid window UNUSED;
694 int how UNUSED;
695 struct mi **menu_list UNUSED;
696 {
697 return -1;
698 }
699
700 /*ARGSUSED*/
701 static void
hup_add_menu(window,glyph,identifier,sel,grpsel,attr,txt,preselected)702 hup_add_menu(window, glyph, identifier, sel, grpsel, attr, txt, preselected)
703 winid window UNUSED;
704 int glyph UNUSED, attr UNUSED;
705 const anything *identifier UNUSED;
706 char sel UNUSED, grpsel UNUSED;
707 const char *txt UNUSED;
708 boolean preselected UNUSED;
709 {
710 return;
711 }
712
713 /*ARGSUSED*/
714 static void
hup_end_menu(window,prompt)715 hup_end_menu(window, prompt)
716 winid window UNUSED;
717 const char *prompt UNUSED;
718 {
719 return;
720 }
721
722 /*ARGSUSED*/
723 static void
hup_putstr(window,attr,text)724 hup_putstr(window, attr, text)
725 winid window UNUSED;
726 int attr UNUSED;
727 const char *text UNUSED;
728 {
729 return;
730 }
731
732 /*ARGSUSED*/
733 static void
hup_print_glyph(window,x,y,glyph,bkglyph)734 hup_print_glyph(window, x, y, glyph, bkglyph)
735 winid window UNUSED;
736 xchar x UNUSED, y UNUSED;
737 int glyph UNUSED;
738 int bkglyph UNUSED;
739 {
740 return;
741 }
742
743 /*ARGSUSED*/
744 static void
hup_outrip(tmpwin,how,when)745 hup_outrip(tmpwin, how, when)
746 winid tmpwin UNUSED;
747 int how UNUSED;
748 time_t when UNUSED;
749 {
750 return;
751 }
752
753 /*ARGSUSED*/
754 static void
hup_curs(window,x,y)755 hup_curs(window, x, y)
756 winid window UNUSED;
757 int x UNUSED, y UNUSED;
758 {
759 return;
760 }
761
762 /*ARGSUSED*/
763 static void
hup_display_nhwindow(window,blocking)764 hup_display_nhwindow(window, blocking)
765 winid window UNUSED;
766 boolean blocking UNUSED;
767 {
768 return;
769 }
770
771 /*ARGSUSED*/
772 static void
hup_display_file(fname,complain)773 hup_display_file(fname, complain)
774 const char *fname UNUSED;
775 boolean complain UNUSED;
776 {
777 return;
778 }
779
780 #ifdef CLIPPING
781 /*ARGSUSED*/
782 static void
hup_cliparound(x,y)783 hup_cliparound(x, y)
784 int x UNUSED, y UNUSED;
785 {
786 return;
787 }
788 #endif
789
790 #ifdef CHANGE_COLOR
791 /*ARGSUSED*/
792 static void
hup_change_color(color,rgb,reverse)793 hup_change_color(color, rgb, reverse)
794 int color, reverse;
795 long rgb;
796 {
797 return;
798 }
799
800 #ifdef MAC
801 /*ARGSUSED*/
802 static short
hup_set_font_name(window,fontname)803 hup_set_font_name(window, fontname)
804 winid window;
805 char *fontname;
806 {
807 return 0;
808 }
809 #endif /* MAC */
810
811 static char *
hup_get_color_string(VOID_ARGS)812 hup_get_color_string(VOID_ARGS)
813 {
814 return (char *) 0;
815 }
816 #endif /* CHANGE_COLOR */
817
818 /*ARGSUSED*/
819 static void
hup_status_update(idx,ptr,chg,pc,color,colormasks)820 hup_status_update(idx, ptr, chg, pc, color, colormasks)
821 int idx UNUSED;
822 genericptr_t ptr UNUSED;
823 int chg UNUSED, pc UNUSED, color UNUSED;
824 unsigned long *colormasks UNUSED;
825
826 {
827 return;
828 }
829
830 /*
831 * Non-specific stubs.
832 */
833
834 static int
hup_int_ndecl(VOID_ARGS)835 hup_int_ndecl(VOID_ARGS)
836 {
837 return -1;
838 }
839
840 static void
hup_void_ndecl(VOID_ARGS)841 hup_void_ndecl(VOID_ARGS)
842 {
843 return;
844 }
845
846 /*ARGUSED*/
847 static void
hup_void_fdecl_int(arg)848 hup_void_fdecl_int(arg)
849 int arg UNUSED;
850 {
851 return;
852 }
853
854 /*ARGUSED*/
855 static void
hup_void_fdecl_winid(window)856 hup_void_fdecl_winid(window)
857 winid window UNUSED;
858 {
859 return;
860 }
861
862 /*ARGUSED*/
863 static void
hup_void_fdecl_constchar_p(string)864 hup_void_fdecl_constchar_p(string)
865 const char *string UNUSED;
866 {
867 return;
868 }
869
870 #endif /* HANGUPHANDLING */
871
872
873 /****************************************************************************/
874 /* genl backward compat stuff */
875 /****************************************************************************/
876
877 const char *status_fieldnm[MAXBLSTATS];
878 const char *status_fieldfmt[MAXBLSTATS];
879 char *status_vals[MAXBLSTATS];
880 boolean status_activefields[MAXBLSTATS];
881
882 void
genl_status_init()883 genl_status_init()
884 {
885 int i;
886
887 for (i = 0; i < MAXBLSTATS; ++i) {
888 status_vals[i] = (char *) alloc(MAXCO);
889 *status_vals[i] = '\0';
890 status_activefields[i] = FALSE;
891 status_fieldfmt[i] = (const char *) 0;
892 }
893 /* Use a window for the genl version; backward port compatibility */
894 WIN_STATUS = create_nhwindow(NHW_STATUS);
895 display_nhwindow(WIN_STATUS, FALSE);
896 }
897
898 void
genl_status_finish()899 genl_status_finish()
900 {
901 /* tear down routine */
902 int i;
903
904 /* free alloc'd memory here */
905 for (i = 0; i < MAXBLSTATS; ++i) {
906 if (status_vals[i])
907 free((genericptr_t) status_vals[i]), status_vals[i] = (char *) 0;
908 }
909 }
910
911 void
genl_status_enablefield(fieldidx,nm,fmt,enable)912 genl_status_enablefield(fieldidx, nm, fmt, enable)
913 int fieldidx;
914 const char *nm;
915 const char *fmt;
916 boolean enable;
917 {
918 status_fieldfmt[fieldidx] = fmt;
919 status_fieldnm[fieldidx] = nm;
920 status_activefields[fieldidx] = enable;
921 }
922
923 /* call once for each field, then call with BL_FLUSH to output the result */
924 void
genl_status_update(idx,ptr,chg,percent,color,colormasks)925 genl_status_update(idx, ptr, chg, percent, color, colormasks)
926 int idx;
927 genericptr_t ptr;
928 int chg UNUSED, percent UNUSED, color UNUSED;
929 unsigned long *colormasks UNUSED;
930 {
931 char newbot1[MAXCO], newbot2[MAXCO];
932 long cond, *condptr = (long *) ptr;
933 register int i;
934 unsigned pass, lndelta;
935 enum statusfields idx1, idx2, *fieldlist;
936 char *nb, *text = (char *) ptr;
937
938 static enum statusfields fieldorder[][15] = {
939 /* line one */
940 { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
941 BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
942 BL_FLUSH },
943 /* line two, default order */
944 { BL_LEVELDESC, BL_GOLD,
945 BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
946 BL_XP, BL_EXP, BL_HD,
947 BL_TIME,
948 BL_HUNGER, BL_CAP, BL_CONDITION,
949 BL_FLUSH },
950 /* move time to the end */
951 { BL_LEVELDESC, BL_GOLD,
952 BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
953 BL_XP, BL_EXP, BL_HD,
954 BL_HUNGER, BL_CAP, BL_CONDITION,
955 BL_TIME, BL_FLUSH },
956 /* move experience and time to the end */
957 { BL_LEVELDESC, BL_GOLD,
958 BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
959 BL_HUNGER, BL_CAP, BL_CONDITION,
960 BL_XP, BL_EXP, BL_HD, BL_TIME, BL_FLUSH },
961 /* move level description plus gold and experience and time to end */
962 { BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
963 BL_HUNGER, BL_CAP, BL_CONDITION,
964 BL_LEVELDESC, BL_GOLD, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_FLUSH },
965 };
966
967 /* in case interface is using genl_status_update() but has not
968 specified WC2_FLUSH_STATUS (status_update() for field values
969 is buffered so final BL_FLUSH is needed to produce output) */
970 windowprocs.wincap2 |= WC2_FLUSH_STATUS;
971
972 if (idx >= 0) {
973 if (!status_activefields[idx])
974 return;
975 switch (idx) {
976 case BL_CONDITION:
977 cond = condptr ? *condptr : 0L;
978 nb = status_vals[idx];
979 *nb = '\0';
980 if (cond & BL_MASK_STONE)
981 Strcpy(nb = eos(nb), " Stone");
982 if (cond & BL_MASK_SLIME)
983 Strcpy(nb = eos(nb), " Slime");
984 if (cond & BL_MASK_STRNGL)
985 Strcpy(nb = eos(nb), " Strngl");
986 if (cond & BL_MASK_FOODPOIS)
987 Strcpy(nb = eos(nb), " FoodPois");
988 if (cond & BL_MASK_TERMILL)
989 Strcpy(nb = eos(nb), " TermIll");
990 if (cond & BL_MASK_BLIND)
991 Strcpy(nb = eos(nb), " Blind");
992 if (cond & BL_MASK_DEAF)
993 Strcpy(nb = eos(nb), " Deaf");
994 if (cond & BL_MASK_STUN)
995 Strcpy(nb = eos(nb), " Stun");
996 if (cond & BL_MASK_CONF)
997 Strcpy(nb = eos(nb), " Conf");
998 if (cond & BL_MASK_HALLU)
999 Strcpy(nb = eos(nb), " Hallu");
1000 if (cond & BL_MASK_LEV)
1001 Strcpy(nb = eos(nb), " Lev");
1002 if (cond & BL_MASK_FLY)
1003 Strcpy(nb = eos(nb), " Fly");
1004 if (cond & BL_MASK_RIDE)
1005 Strcpy(nb = eos(nb), " Ride");
1006 break;
1007 default:
1008 Sprintf(status_vals[idx],
1009 status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s",
1010 text ? text : "");
1011 break;
1012 }
1013 return; /* processed one field other than BL_FLUSH */
1014 } /* (idx >= 0, thus not BL_FLUSH, BL_RESET, BL_CHARACTERISTICS) */
1015
1016 /* does BL_RESET require any specific code to ensure all fields ? */
1017
1018 if (!(idx == BL_FLUSH || idx == BL_RESET))
1019 return;
1020
1021 /* We've received BL_FLUSH; time to output the gathered data */
1022 nb = newbot1;
1023 *nb = '\0';
1024 /* BL_FLUSH is the only pseudo-index value we need to check for
1025 in the loop below because it is the only entry used to pad the
1026 end of the fieldorder array. We could stop on any
1027 negative (illegal) index, but this should be fine */
1028 for (i = 0; (idx1 = fieldorder[0][i]) != BL_FLUSH; ++i) {
1029 if (status_activefields[idx1])
1030 Strcpy(nb = eos(nb), status_vals[idx1]);
1031 }
1032 /* if '$' is encoded, buffer length of \GXXXXNNNN is 9 greater than
1033 single char; we want to subtract that 9 when checking display length */
1034 lndelta = (status_activefields[BL_GOLD]
1035 && strstr(status_vals[BL_GOLD], "\\G")) ? 9 : 0;
1036 /* basic bot2 formats groups of second line fields into five buffers,
1037 then decides how to order those buffers based on comparing lengths
1038 of [sub]sets of them to the width of the map; we have more control
1039 here but currently emulate that behavior */
1040 for (pass = 1; pass <= 4; pass++) {
1041 fieldlist = fieldorder[pass];
1042 nb = newbot2;
1043 *nb = '\0';
1044 for (i = 0; (idx2 = fieldlist[i]) != BL_FLUSH; ++i) {
1045 if (status_activefields[idx2]) {
1046 const char *val = status_vals[idx2];
1047
1048 switch (idx2) {
1049 case BL_HP: /* for pass 4, Hp comes first; mungspaces()
1050 will strip the unwanted leading spaces */
1051 case BL_XP: case BL_HD:
1052 case BL_TIME:
1053 Strcpy(nb = eos(nb), " ");
1054 break;
1055 case BL_LEVELDESC:
1056 /* leveldesc has no leading space, so if we've moved
1057 it past the first position, provide one */
1058 if (i != 0)
1059 Strcpy(nb = eos(nb), " ");
1060 break;
1061 /*
1062 * We want " hunger encumbrance conditions"
1063 * or " encumbrance conditions"
1064 * or " hunger conditions"
1065 * or " conditions"
1066 * 'hunger' is either " " or " hunger_text";
1067 * 'encumbrance' is either " " or " encumbrance_text";
1068 * 'conditions' is either "" or " cond1 cond2...".
1069 */
1070 case BL_HUNGER:
1071 /* hunger==" " - keep it, end up with " ";
1072 hunger!=" " - insert space and get " hunger" */
1073 if (strcmp(val, " "))
1074 Strcpy(nb = eos(nb), " ");
1075 break;
1076 case BL_CAP:
1077 /* cap==" " - suppress it, retain " hunger" or " ";
1078 cap!=" " - use it, get " hunger cap" or " cap" */
1079 if (!strcmp(val, " "))
1080 ++val;
1081 break;
1082 default:
1083 break;
1084 }
1085 Strcpy(nb = eos(nb), val); /* status_vals[idx2] */
1086 } /* status_activefields[idx2] */
1087
1088 if (idx2 == BL_CONDITION && pass < 4
1089 && strlen(newbot2) - lndelta > COLNO)
1090 break; /* switch to next order */
1091 } /* i */
1092
1093 if (idx2 == BL_FLUSH) { /* made it past BL_CONDITION */
1094 if (pass > 1)
1095 mungspaces(newbot2);
1096 break;
1097 }
1098 } /* pass */
1099 curs(WIN_STATUS, 1, 0);
1100 putstr(WIN_STATUS, 0, newbot1);
1101 curs(WIN_STATUS, 1, 1);
1102 putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
1103 }
1104
1105 STATIC_VAR struct window_procs dumplog_windowprocs_backup;
1106 STATIC_VAR FILE *dumplog_file;
1107
1108 #ifdef DUMPLOG
1109 STATIC_VAR time_t dumplog_now;
1110
1111 char *
dump_fmtstr(fmt,buf,fullsubs)1112 dump_fmtstr(fmt, buf, fullsubs)
1113 const char *fmt;
1114 char *buf;
1115 boolean fullsubs; /* True -> full substitution for file name, False ->
1116 * partial substitution for '--showpaths' feedback
1117 * where there's no game in progress when executed */
1118 {
1119 const char *fp = fmt;
1120 char *bp = buf;
1121 int slen, len = 0;
1122 char tmpbuf[BUFSZ];
1123 char verbuf[BUFSZ];
1124 long uid;
1125 time_t now;
1126
1127 now = dumplog_now;
1128 uid = (long) getuid();
1129
1130 /*
1131 * Note: %t and %T assume that time_t is a 'long int' number of
1132 * seconds since some epoch value. That's quite iffy.... The
1133 * unit of time might be different and the datum size might be
1134 * some variant of 'long long int'. [Their main purpose is to
1135 * construct a unique file name rather than record the date and
1136 * time; violating the 'long seconds since base-date' assumption
1137 * may or may not interfere with that usage.]
1138 */
1139
1140 while (fp && *fp && len < BUFSZ - 1) {
1141 if (*fp == '%') {
1142 fp++;
1143 switch (*fp) {
1144 default:
1145 goto finish;
1146 case '\0': /* fallthrough */
1147 case '%': /* literal % */
1148 Sprintf(tmpbuf, "%%");
1149 break;
1150 case 't': /* game start, timestamp */
1151 if (fullsubs)
1152 Sprintf(tmpbuf, "%lu", (unsigned long) ubirthday);
1153 else
1154 Strcpy(tmpbuf, "{game start cookie}");
1155 break;
1156 case 'T': /* current time, timestamp */
1157 if (fullsubs)
1158 Sprintf(tmpbuf, "%lu", (unsigned long) now);
1159 else
1160 Strcpy(tmpbuf, "{current time cookie}");
1161 break;
1162 case 'd': /* game start, YYYYMMDDhhmmss */
1163 if (fullsubs)
1164 Sprintf(tmpbuf, "%08ld%06ld",
1165 yyyymmdd(ubirthday), hhmmss(ubirthday));
1166 else
1167 Strcpy(tmpbuf, "{game start date+time}");
1168 break;
1169 case 'D': /* current time, YYYYMMDDhhmmss */
1170 if (fullsubs)
1171 Sprintf(tmpbuf, "%08ld%06ld", yyyymmdd(now), hhmmss(now));
1172 else
1173 Strcpy(tmpbuf, "{current date+time}");
1174 break;
1175 case 'v': /* version, eg. "3.6.5-0" */
1176 Sprintf(tmpbuf, "%s", version_string(verbuf));
1177 break;
1178 case 'u': /* UID */
1179 Sprintf(tmpbuf, "%ld", uid);
1180 break;
1181 case 'n': /* player name */
1182 if (fullsubs)
1183 Sprintf(tmpbuf, "%s", *plname ? plname : "unknown");
1184 else
1185 Strcpy(tmpbuf, "{hero name}");
1186 break;
1187 case 'N': /* first character of player name */
1188 if (fullsubs)
1189 Sprintf(tmpbuf, "%c", *plname ? *plname : 'u');
1190 else
1191 Strcpy(tmpbuf, "{hero initial}");
1192 break;
1193 }
1194 if (fullsubs) {
1195 /* replace potentially troublesome characters (including
1196 <space> even though it might be an acceptable file name
1197 character); user shouldn't be able to get ' ' or '/'
1198 or '\\' into plname[] but play things safe */
1199 (void) strNsubst(tmpbuf, " ", "_", 0);
1200 (void) strNsubst(tmpbuf, "/", "_", 0);
1201 (void) strNsubst(tmpbuf, "\\", "_", 0);
1202 /* note: replacements are only done on field substitutions,
1203 not on the template (from sysconf or DUMPLOG_FILE) */
1204 }
1205
1206 slen = (int) strlen(tmpbuf);
1207 if (len + slen < BUFSZ - 1) {
1208 len += slen;
1209 Sprintf(bp, "%s", tmpbuf);
1210 bp += slen;
1211 if (*fp)
1212 fp++;
1213 } else
1214 break;
1215 } else {
1216 *bp = *fp;
1217 bp++;
1218 fp++;
1219 len++;
1220 }
1221 }
1222 finish:
1223 *bp = '\0';
1224 return buf;
1225 }
1226 #endif /* DUMPLOG */
1227
1228 void
dump_open_log(now)1229 dump_open_log(now)
1230 time_t now;
1231 {
1232 #ifdef DUMPLOG
1233 char buf[BUFSZ];
1234 char *fname;
1235
1236 dumplog_now = now;
1237 #ifdef SYSCF
1238 if (!sysopt.dumplogfile)
1239 return;
1240 fname = dump_fmtstr(sysopt.dumplogfile, buf, TRUE);
1241 #else
1242 fname = dump_fmtstr(DUMPLOG_FILE, buf, TRUE);
1243 #endif
1244 dumplog_file = fopen(fname, "w");
1245 dumplog_windowprocs_backup = windowprocs;
1246
1247 #else /*!DUMPLOG*/
1248 nhUse(now);
1249 #endif /*?DUMPLOG*/
1250 }
1251
1252 void
dump_close_log()1253 dump_close_log()
1254 {
1255 if (dumplog_file) {
1256 (void) fclose(dumplog_file);
1257 dumplog_file = (FILE *) 0;
1258 }
1259 }
1260
1261 void
dump_forward_putstr(win,attr,str,no_forward)1262 dump_forward_putstr(win, attr, str, no_forward)
1263 winid win;
1264 int attr;
1265 const char *str;
1266 int no_forward;
1267 {
1268 if (dumplog_file)
1269 fprintf(dumplog_file, "%s\n", str);
1270 if (!no_forward)
1271 putstr(win, attr, str);
1272 }
1273
1274 /*ARGSUSED*/
1275 STATIC_OVL void
dump_putstr(win,attr,str)1276 dump_putstr(win, attr, str)
1277 winid win UNUSED;
1278 int attr UNUSED;
1279 const char *str;
1280 {
1281 if (dumplog_file)
1282 fprintf(dumplog_file, "%s\n", str);
1283 }
1284
1285 STATIC_OVL winid
dump_create_nhwindow(dummy)1286 dump_create_nhwindow(dummy)
1287 int dummy;
1288 {
1289 return dummy;
1290 }
1291
1292 /*ARGUSED*/
1293 STATIC_OVL void
dump_clear_nhwindow(win)1294 dump_clear_nhwindow(win)
1295 winid win UNUSED;
1296 {
1297 return;
1298 }
1299
1300 /*ARGSUSED*/
1301 STATIC_OVL void
dump_display_nhwindow(win,p)1302 dump_display_nhwindow(win, p)
1303 winid win UNUSED;
1304 boolean p UNUSED;
1305 {
1306 return;
1307 }
1308
1309 /*ARGUSED*/
1310 STATIC_OVL void
dump_destroy_nhwindow(win)1311 dump_destroy_nhwindow(win)
1312 winid win UNUSED;
1313 {
1314 return;
1315 }
1316
1317 /*ARGUSED*/
1318 STATIC_OVL void
dump_start_menu(win)1319 dump_start_menu(win)
1320 winid win UNUSED;
1321 {
1322 return;
1323 }
1324
1325 /*ARGSUSED*/
1326 STATIC_OVL void
dump_add_menu(win,glyph,identifier,ch,gch,attr,str,preselected)1327 dump_add_menu(win, glyph, identifier, ch, gch, attr, str, preselected)
1328 winid win UNUSED;
1329 int glyph;
1330 const anything *identifier UNUSED;
1331 char ch;
1332 char gch UNUSED;
1333 int attr UNUSED;
1334 const char *str;
1335 boolean preselected UNUSED;
1336 {
1337 if (dumplog_file) {
1338 if (glyph == NO_GLYPH)
1339 fprintf(dumplog_file, " %s\n", str);
1340 else
1341 fprintf(dumplog_file, " %c - %s\n", ch, str);
1342 }
1343 }
1344
1345 /*ARGSUSED*/
1346 STATIC_OVL void
dump_end_menu(win,str)1347 dump_end_menu(win, str)
1348 winid win UNUSED;
1349 const char *str;
1350 {
1351 if (dumplog_file) {
1352 if (str)
1353 fprintf(dumplog_file, "%s\n", str);
1354 else
1355 fputs("\n", dumplog_file);
1356 }
1357 }
1358
1359 STATIC_OVL int
dump_select_menu(win,how,item)1360 dump_select_menu(win, how, item)
1361 winid win UNUSED;
1362 int how UNUSED;
1363 menu_item **item;
1364 {
1365 *item = (menu_item *) 0;
1366 return 0;
1367 }
1368
1369 void
dump_redirect(onoff_flag)1370 dump_redirect(onoff_flag)
1371 boolean onoff_flag;
1372 {
1373 if (dumplog_file) {
1374 if (onoff_flag) {
1375 windowprocs.win_create_nhwindow = dump_create_nhwindow;
1376 windowprocs.win_clear_nhwindow = dump_clear_nhwindow;
1377 windowprocs.win_display_nhwindow = dump_display_nhwindow;
1378 windowprocs.win_destroy_nhwindow = dump_destroy_nhwindow;
1379 windowprocs.win_start_menu = dump_start_menu;
1380 windowprocs.win_add_menu = dump_add_menu;
1381 windowprocs.win_end_menu = dump_end_menu;
1382 windowprocs.win_select_menu = dump_select_menu;
1383 windowprocs.win_putstr = dump_putstr;
1384 } else {
1385 windowprocs = dumplog_windowprocs_backup;
1386 }
1387 iflags.in_dumplog = onoff_flag;
1388 } else {
1389 iflags.in_dumplog = FALSE;
1390 }
1391 }
1392
1393 #ifdef TTY_GRAPHICS
1394 #ifdef TEXTCOLOR
1395 #ifdef TOS
1396 extern const char *hilites[CLR_MAX];
1397 #else
1398 extern NEARDATA char *hilites[CLR_MAX];
1399 #endif
1400 #endif
1401 #endif
1402
1403 int
has_color(color)1404 has_color(color)
1405 int color;
1406 {
1407 return (iflags.use_color && windowprocs.name
1408 && (windowprocs.wincap & WC_COLOR) && windowprocs.has_color[color]
1409 #ifdef TTY_GRAPHICS
1410 #if defined(TEXTCOLOR) && defined(TERMLIB) && !defined(NO_TERMS)
1411 && (hilites[color] != 0)
1412 #endif
1413 #endif
1414 );
1415 }
1416
1417 /*windows.c*/
1418