Show control key combos with uppercase alpha
[aNetHack.git] / src / windows.c
blob70c9feee7637973670b1227877e04cebc619b584
1 /* NetHack 3.6 windows.c $NHDT-Date: 1488075979 2017/02/26 02:26:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.39 $ */
2 /* Copyright (c) D. Cohrs, 1993. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #ifdef TTY_GRAPHICS
7 #include "wintty.h"
8 #endif
9 #ifdef X11_GRAPHICS
10 /* Cannot just blindly include winX.h without including all of X11 stuff
11 and must get the order of include files right. Don't bother. */
12 extern struct window_procs X11_procs;
13 extern void FDECL(win_X11_init, (int));
14 #endif
15 #ifdef QT_GRAPHICS
16 extern struct window_procs Qt_procs;
17 #endif
18 #ifdef GEM_GRAPHICS
19 #include "wingem.h"
20 #endif
21 #ifdef MAC
22 extern struct window_procs mac_procs;
23 #endif
24 #ifdef BEOS_GRAPHICS
25 extern struct window_procs beos_procs;
26 extern void FDECL(be_win_init, (int));
27 FAIL /* be_win_init doesn't exist? XXX*/
28 #endif
29 #ifdef AMIGA_INTUITION
30 extern struct window_procs amii_procs;
31 extern struct window_procs amiv_procs;
32 extern void FDECL(ami_wininit_data, (int));
33 #endif
34 #ifdef WIN32_GRAPHICS
35 extern struct window_procs win32_procs;
36 #endif
37 #ifdef GNOME_GRAPHICS
38 #include "winGnome.h"
39 extern struct window_procs Gnome_procs;
40 #endif
41 #ifdef MSWIN_GRAPHICS
42 extern struct window_procs mswin_procs;
43 #endif
44 #ifdef WINCHAIN
45 extern struct window_procs chainin_procs;
46 extern void FDECL(chainin_procs_init, (int));
47 extern void *FDECL(chainin_procs_chain, (int, int, void *, void *, void *));
49 extern struct chain_procs chainout_procs;
50 extern void FDECL(chainout_procs_init, (int));
51 extern void *FDECL(chainout_procs_chain, (int, int, void *, void *, void *));
53 extern struct chain_procs trace_procs;
54 extern void FDECL(trace_procs_init, (int));
55 extern void *FDECL(trace_procs_chain, (int, int, void *, void *, void *));
56 #endif
58 STATIC_DCL void FDECL(def_raw_print, (const char *s));
60 #ifdef HANGUPHANDLING
61 volatile
62 #endif
63 NEARDATA struct window_procs windowprocs;
65 #ifdef WINCHAIN
66 #define CHAINR(x) , x
67 #else
68 #define CHAINR(x)
69 #endif
71 static struct win_choices {
72 struct window_procs *procs;
73 void FDECL((*ini_routine), (int)); /* optional (can be 0) */
74 #ifdef WINCHAIN
75 void *FDECL((*chain_routine), (int, int, void *, void *, void *));
76 #endif
77 } winchoices[] = {
78 #ifdef TTY_GRAPHICS
79 { &tty_procs, win_tty_init CHAINR(0) },
80 #endif
81 #ifdef X11_GRAPHICS
82 { &X11_procs, win_X11_init CHAINR(0) },
83 #endif
84 #ifdef QT_GRAPHICS
85 { &Qt_procs, 0 CHAINR(0) },
86 #endif
87 #ifdef GEM_GRAPHICS
88 { &Gem_procs, win_Gem_init CHAINR(0) },
89 #endif
90 #ifdef MAC
91 { &mac_procs, 0 CHAINR(0) },
92 #endif
93 #ifdef BEOS_GRAPHICS
94 { &beos_procs, be_win_init CHAINR(0) },
95 #endif
96 #ifdef AMIGA_INTUITION
97 { &amii_procs,
98 ami_wininit_data CHAINR(0) }, /* Old font version of the game */
99 { &amiv_procs,
100 ami_wininit_data CHAINR(0) }, /* Tile version of the game */
101 #endif
102 #ifdef WIN32_GRAPHICS
103 { &win32_procs, 0 CHAINR(0) },
104 #endif
105 #ifdef GNOME_GRAPHICS
106 { &Gnome_procs, 0 CHAINR(0) },
107 #endif
108 #ifdef MSWIN_GRAPHICS
109 { &mswin_procs, 0 CHAINR(0) },
110 #endif
111 #ifdef WINCHAIN
112 { &chainin_procs, chainin_procs_init, chainin_procs_chain },
113 { (struct window_procs *) &chainout_procs, chainout_procs_init,
114 chainout_procs_chain },
116 { (struct window_procs *) &trace_procs, trace_procs_init,
117 trace_procs_chain },
118 #endif
119 { 0, 0 CHAINR(0) } /* must be last */
122 #ifdef WINCHAIN
123 struct winlink {
124 struct winlink *nextlink;
125 struct win_choices *wincp;
126 void *linkdata;
128 /* NB: this chain does not contain the terminal real window system pointer */
130 static struct winlink *chain = 0;
132 static struct winlink *
133 wl_new()
135 return calloc(1, sizeof(struct winlink));
137 static void
138 wl_addhead(struct winlink *wl)
140 wl->nextlink = chain;
141 chain = wl;
143 static void
144 wl_addtail(struct winlink *wl)
146 struct winlink *p = chain;
148 if (!chain) {
149 chain = wl;
150 return;
152 while (p->nextlink) {
153 p = p->nextlink;
155 p->nextlink = wl;
156 return;
158 #endif /* WINCHAIN */
160 static struct win_choices *last_winchoice = 0;
162 boolean
163 genl_can_suspend_no(VOID_ARGS)
165 return FALSE;
168 boolean
169 genl_can_suspend_yes(VOID_ARGS)
171 return TRUE;
174 STATIC_OVL
175 void
176 def_raw_print(s)
177 const char *s;
179 puts(s);
182 #ifdef WINCHAIN
183 static struct win_choices *
184 win_choices_find(s)
185 const char *s;
187 register int i;
189 for (i = 0; winchoices[i].procs; i++) {
190 if (!strcmpi(s, winchoices[i].procs->name)) {
191 return &winchoices[i];
194 return (struct win_choices *) 0;
196 #endif
198 void
199 choose_windows(s)
200 const char *s;
202 register int i;
204 for (i = 0; winchoices[i].procs; i++) {
205 if ('+' == winchoices[i].procs->name[0])
206 continue;
207 if ('-' == winchoices[i].procs->name[0])
208 continue;
209 if (!strcmpi(s, winchoices[i].procs->name)) {
210 windowprocs = *winchoices[i].procs;
212 if (last_winchoice && last_winchoice->ini_routine)
213 (*last_winchoice->ini_routine)(WININIT_UNDO);
214 if (winchoices[i].ini_routine)
215 (*winchoices[i].ini_routine)(WININIT);
216 last_winchoice = &winchoices[i];
217 return;
221 if (!windowprocs.win_raw_print)
222 windowprocs.win_raw_print = def_raw_print;
224 if (!winchoices[0].procs) {
225 raw_printf("No window types?");
226 exit(EXIT_FAILURE);
228 if (!winchoices[1].procs) {
229 raw_printf("Window type %s not recognized. The only choice is: %s.",
230 s, winchoices[0].procs->name);
231 } else {
232 raw_printf("Window type %s not recognized. Choices are:", s);
233 for (i = 0; winchoices[i].procs; i++) {
234 if ('+' == winchoices[i].procs->name[0])
235 continue;
236 if ('-' == winchoices[i].procs->name[0])
237 continue;
238 raw_printf(" %s", winchoices[i].procs->name);
242 if (windowprocs.win_raw_print == def_raw_print)
243 terminate(EXIT_SUCCESS);
244 wait_synch();
247 #ifdef WINCHAIN
248 void
249 addto_windowchain(s)
250 const char *s;
252 register int i;
254 for (i = 0; winchoices[i].procs; i++) {
255 if ('+' != winchoices[i].procs->name[0])
256 continue;
257 if (!strcmpi(s, winchoices[i].procs->name)) {
258 struct winlink *p = wl_new();
259 p->wincp = &winchoices[i];
260 wl_addtail(p);
261 /* NB: The ini_routine() will be called during commit. */
262 return;
266 windowprocs.win_raw_print = def_raw_print;
268 raw_printf("Window processor %s not recognized. Choices are:", s);
269 for (i = 0; winchoices[i].procs; i++) {
270 if ('+' != winchoices[i].procs->name[0])
271 continue;
272 raw_printf(" %s", winchoices[i].procs->name);
275 exit(EXIT_FAILURE);
278 void
279 commit_windowchain()
281 struct winlink *p;
282 int n;
283 int wincap, wincap2;
285 if (!chain)
286 return;
288 /* Save wincap* from the real window system - we'll restore it below. */
289 wincap = windowprocs.wincap;
290 wincap2 = windowprocs.wincap2;
292 /* add -chainin at head and -chainout at tail */
293 p = wl_new();
294 p->wincp = win_choices_find("-chainin");
295 if (!p->wincp) {
296 raw_printf("Can't locate processor '-chainin'");
297 exit(EXIT_FAILURE);
299 wl_addhead(p);
301 p = wl_new();
302 p->wincp = win_choices_find("-chainout");
303 if (!p->wincp) {
304 raw_printf("Can't locate processor '-chainout'");
305 exit(EXIT_FAILURE);
307 wl_addtail(p);
309 /* Now alloc() init() similar to Objective-C. */
310 for (n = 1, p = chain; p; n++, p = p->nextlink) {
311 p->linkdata = (*p->wincp->chain_routine)(WINCHAIN_ALLOC, n, 0, 0, 0);
314 for (n = 1, p = chain; p; n++, p = p->nextlink) {
315 if (p->nextlink) {
316 (void) (*p->wincp->chain_routine)(WINCHAIN_INIT, n, p->linkdata,
317 p->nextlink->wincp->procs,
318 p->nextlink->linkdata);
319 } else {
320 (void) (*p->wincp->chain_routine)(WINCHAIN_INIT, n, p->linkdata,
321 last_winchoice->procs, 0);
325 /* Restore the saved wincap* values. We do it here to give the
326 * ini_routine()s a chance to change or check them. */
327 chain->wincp->procs->wincap = wincap;
328 chain->wincp->procs->wincap2 = wincap2;
330 /* Call the init procs. Do not re-init the terminal real win. */
331 p = chain;
332 while (p->nextlink) {
333 if (p->wincp->ini_routine) {
334 (*p->wincp->ini_routine)(WININIT);
336 p = p->nextlink;
339 /* Install the chain into window procs very late so ini_routine()s
340 * can raw_print on error. */
341 windowprocs = *chain->wincp->procs;
343 p = chain;
344 while (p) {
345 struct winlink *np = p->nextlink;
346 free(p);
347 p = np; /* assignment, not proof */
350 #endif /* WINCHAIN */
353 * tty_message_menu() provides a means to get feedback from the
354 * --More-- prompt; other interfaces generally don't need that.
356 /*ARGSUSED*/
357 char
358 genl_message_menu(let, how, mesg)
359 char let UNUSED;
360 int how UNUSED;
361 const char *mesg;
363 pline("%s", mesg);
364 return 0;
367 /*ARGSUSED*/
368 void
369 genl_preference_update(pref)
370 const char *pref UNUSED;
372 /* window ports are expected to provide
373 their own preference update routine
374 for the preference capabilities that
375 they support.
376 Just return in this genl one. */
377 return;
380 char *
381 genl_getmsghistory(init)
382 boolean init UNUSED;
384 /* window ports can provide
385 their own getmsghistory() routine to
386 preserve message history between games.
387 The routine is called repeatedly from
388 the core save routine, and the window
389 port is expected to successively return
390 each message that it wants saved, starting
391 with the oldest message first, finishing
392 with the most recent.
393 Return null pointer when finished.
395 return (char *) 0;
398 void
399 genl_putmsghistory(msg, is_restoring)
400 const char *msg;
401 boolean is_restoring;
403 /* window ports can provide
404 their own putmsghistory() routine to
405 load message history from a saved game.
406 The routine is called repeatedly from
407 the core restore routine, starting with
408 the oldest saved message first, and
409 finishing with the latest.
410 The window port routine is expected to
411 load the message recall buffers in such
412 a way that the ordering is preserved.
413 The window port routine should make no
414 assumptions about how many messages are
415 forthcoming, nor should it assume that
416 another message will follow this one,
417 so it should keep all pointers/indexes
418 intact at the end of each call.
421 /* this doesn't provide for reloading the message window with the
422 previous session's messages upon restore, but it does put the quest
423 message summary lines there by treating them as ordinary messages */
424 if (!is_restoring)
425 pline("%s", msg);
426 return;
429 #ifdef HANGUPHANDLING
431 * Dummy windowing scheme used to replace current one with no-ops
432 * in order to avoid all terminal I/O after hangup/disconnect.
435 static int NDECL(hup_nhgetch);
436 static char FDECL(hup_yn_function, (const char *, const char *, CHAR_P));
437 static int FDECL(hup_nh_poskey, (int *, int *, int *));
438 static void FDECL(hup_getlin, (const char *, char *));
439 static void FDECL(hup_init_nhwindows, (int *, char **));
440 static void FDECL(hup_exit_nhwindows, (const char *));
441 static winid FDECL(hup_create_nhwindow, (int));
442 static int FDECL(hup_select_menu, (winid, int, MENU_ITEM_P **));
443 static void FDECL(hup_add_menu, (winid, int, const anything *, CHAR_P, CHAR_P,
444 int, const char *, BOOLEAN_P));
445 static void FDECL(hup_end_menu, (winid, const char *));
446 static void FDECL(hup_putstr, (winid, int, const char *));
447 static void FDECL(hup_print_glyph, (winid, XCHAR_P, XCHAR_P, int, int));
448 static void FDECL(hup_outrip, (winid, int, time_t));
449 static void FDECL(hup_curs, (winid, int, int));
450 static void FDECL(hup_display_nhwindow, (winid, BOOLEAN_P));
451 static void FDECL(hup_display_file, (const char *, BOOLEAN_P));
452 #ifdef CLIPPING
453 static void FDECL(hup_cliparound, (int, int));
454 #endif
455 #ifdef CHANGE_COLOR
456 static void FDECL(hup_change_color, (int, long, int));
457 #ifdef MAC
458 static short FDECL(hup_set_font_name, (winid, char *));
459 #endif
460 static char *NDECL(hup_get_color_string);
461 #endif /* CHANGE_COLOR */
462 #ifdef STATUS_VIA_WINDOWPORT
463 static void FDECL(hup_status_update, (int, genericptr_t, int, int));
464 #endif
466 static int NDECL(hup_int_ndecl);
467 static void NDECL(hup_void_ndecl);
468 static void FDECL(hup_void_fdecl_int, (int));
469 static void FDECL(hup_void_fdecl_winid, (winid));
470 static void FDECL(hup_void_fdecl_constchar_p, (const char *));
472 static struct window_procs hup_procs = {
473 "hup", 0L, 0L, hup_init_nhwindows,
474 hup_void_ndecl, /* player_selection */
475 hup_void_ndecl, /* askname */
476 hup_void_ndecl, /* get_nh_event */
477 hup_exit_nhwindows, hup_void_fdecl_constchar_p, /* suspend_nhwindows */
478 hup_void_ndecl, /* resume_nhwindows */
479 hup_create_nhwindow, hup_void_fdecl_winid, /* clear_nhwindow */
480 hup_display_nhwindow, hup_void_fdecl_winid, /* destroy_nhwindow */
481 hup_curs, hup_putstr, hup_putstr, /* putmixed */
482 hup_display_file, hup_void_fdecl_winid, /* start_menu */
483 hup_add_menu, hup_end_menu, hup_select_menu, genl_message_menu,
484 hup_void_ndecl, /* update_inventory */
485 hup_void_ndecl, /* mark_synch */
486 hup_void_ndecl, /* wait_synch */
487 #ifdef CLIPPING
488 hup_cliparound,
489 #endif
490 #ifdef POSITIONBAR
491 (void FDECL((*), (char *))) hup_void_fdecl_constchar_p,
492 /* update_positionbar */
493 #endif
494 hup_print_glyph,
495 hup_void_fdecl_constchar_p, /* raw_print */
496 hup_void_fdecl_constchar_p, /* raw_print_bold */
497 hup_nhgetch, hup_nh_poskey, hup_void_ndecl, /* nhbell */
498 hup_int_ndecl, /* doprev_message */
499 hup_yn_function, hup_getlin, hup_int_ndecl, /* get_ext_cmd */
500 hup_void_fdecl_int, /* number_pad */
501 hup_void_ndecl, /* delay_output */
502 #ifdef CHANGE_COLOR
503 hup_change_color,
504 #ifdef MAC
505 hup_void_fdecl_int, /* change_background */
506 hup_set_font_name,
507 #endif
508 hup_get_color_string,
509 #endif /* CHANGE_COLOR */
510 hup_void_ndecl, /* start_screen */
511 hup_void_ndecl, /* end_screen */
512 hup_outrip, genl_preference_update, genl_getmsghistory,
513 genl_putmsghistory,
514 #ifdef STATUS_VIA_WINDOWPORT
515 hup_void_ndecl, /* status_init */
516 hup_void_ndecl, /* status_finish */
517 genl_status_enablefield, hup_status_update,
518 #ifdef STATUS_HILITES
519 genl_status_threshold,
520 #endif
521 #endif /* STATUS_VIA_WINDOWPORT */
522 genl_can_suspend_no,
525 static void FDECL((*previnterface_exit_nhwindows), (const char *)) = 0;
527 /* hangup has occurred; switch to no-op user interface */
528 void
529 nhwindows_hangup()
531 char *FDECL((*previnterface_getmsghistory), (BOOLEAN_P)) = 0;
533 #ifdef ALTMETA
534 /* command processor shouldn't look for 2nd char after seeing ESC */
535 iflags.altmeta = FALSE;
536 #endif
538 /* don't call exit_nhwindows() directly here; if a hangup occurs
539 while interface code is executing, exit_nhwindows could knock
540 the interface's active data structures out from under itself */
541 if (iflags.window_inited
542 && windowprocs.win_exit_nhwindows != hup_exit_nhwindows)
543 previnterface_exit_nhwindows = windowprocs.win_exit_nhwindows;
545 /* also, we have to leave the old interface's getmsghistory()
546 in place because it will be called while saving the game */
547 if (windowprocs.win_getmsghistory != hup_procs.win_getmsghistory)
548 previnterface_getmsghistory = windowprocs.win_getmsghistory;
550 windowprocs = hup_procs;
552 if (previnterface_getmsghistory)
553 windowprocs.win_getmsghistory = previnterface_getmsghistory;
556 static void
557 hup_exit_nhwindows(lastgasp)
558 const char *lastgasp;
560 /* core has called exit_nhwindows(); call the previous interface's
561 shutdown routine now; xxx_exit_nhwindows() needs to call other
562 xxx_ routines directly rather than through windowprocs pointers */
563 if (previnterface_exit_nhwindows) {
564 lastgasp = 0; /* don't want exit routine to attempt extra output */
565 (*previnterface_exit_nhwindows)(lastgasp);
566 previnterface_exit_nhwindows = 0;
568 iflags.window_inited = 0;
571 static int
572 hup_nhgetch(VOID_ARGS)
574 return '\033'; /* ESC */
577 /*ARGSUSED*/
578 static char
579 hup_yn_function(prompt, resp, deflt)
580 const char *prompt UNUSED, *resp UNUSED;
581 char deflt;
583 if (!deflt)
584 deflt = '\033';
585 return deflt;
588 /*ARGSUSED*/
589 static int
590 hup_nh_poskey(x, y, mod)
591 int *x UNUSED, *y UNUSED, *mod UNUSED;
593 return '\033';
596 /*ARGSUSED*/
597 static void
598 hup_getlin(prompt, outbuf)
599 const char *prompt UNUSED;
600 char *outbuf;
602 Strcpy(outbuf, "\033");
605 /*ARGSUSED*/
606 static void
607 hup_init_nhwindows(argc_p, argv)
608 int *argc_p UNUSED;
609 char **argv UNUSED;
611 iflags.window_inited = 1;
614 /*ARGUSED*/
615 static winid
616 hup_create_nhwindow(type)
617 int type UNUSED;
619 return WIN_ERR;
622 /*ARGSUSED*/
623 static int
624 hup_select_menu(window, how, menu_list)
625 winid window UNUSED;
626 int how UNUSED;
627 struct mi **menu_list UNUSED;
629 return -1;
632 /*ARGSUSED*/
633 static void
634 hup_add_menu(window, glyph, identifier, sel, grpsel, attr, txt, preselected)
635 winid window UNUSED;
636 int glyph UNUSED, attr UNUSED;
637 const anything *identifier UNUSED;
638 char sel UNUSED, grpsel UNUSED;
639 const char *txt UNUSED;
640 boolean preselected UNUSED;
642 return;
645 /*ARGSUSED*/
646 static void
647 hup_end_menu(window, prompt)
648 winid window UNUSED;
649 const char *prompt UNUSED;
651 return;
654 /*ARGSUSED*/
655 static void
656 hup_putstr(window, attr, text)
657 winid window UNUSED;
658 int attr UNUSED;
659 const char *text UNUSED;
661 return;
664 /*ARGSUSED*/
665 static void
666 hup_print_glyph(window, x, y, glyph, bkglyph)
667 winid window UNUSED;
668 xchar x UNUSED, y UNUSED;
669 int glyph UNUSED;
670 int bkglyph UNUSED;
672 return;
675 /*ARGSUSED*/
676 static void
677 hup_outrip(tmpwin, how, when)
678 winid tmpwin UNUSED;
679 int how UNUSED;
680 time_t when UNUSED;
682 return;
685 /*ARGSUSED*/
686 static void
687 hup_curs(window, x, y)
688 winid window UNUSED;
689 int x UNUSED, y UNUSED;
691 return;
694 /*ARGSUSED*/
695 static void
696 hup_display_nhwindow(window, blocking)
697 winid window UNUSED;
698 boolean blocking UNUSED;
700 return;
703 /*ARGSUSED*/
704 static void
705 hup_display_file(fname, complain)
706 const char *fname UNUSED;
707 boolean complain UNUSED;
709 return;
712 #ifdef CLIPPING
713 /*ARGSUSED*/
714 static void
715 hup_cliparound(x, y)
716 int x UNUSED, y UNUSED;
718 return;
720 #endif
722 #ifdef CHANGE_COLOR
723 /*ARGSUSED*/
724 static void
725 hup_change_color(color, rgb, reverse)
726 int color, reverse;
727 long rgb;
729 return;
732 #ifdef MAC
733 /*ARGSUSED*/
734 static short
735 hup_set_font_name(window, fontname)
736 winid window;
737 char *fontname;
739 return 0;
741 #endif /* MAC */
743 static char *
744 hup_get_color_string(VOID_ARGS)
746 return (char *) 0;
748 #endif /* CHANGE_COLOR */
750 #ifdef STATUS_VIA_WINDOWPORT
751 /*ARGSUSED*/
752 static void
753 hup_status_update(idx, ptr, chg, percent)
754 int idx UNUSED;
755 genericptr_t ptr UNUSED;
756 int chg UNUSED, percent UNUSED;
758 return;
760 #endif /* STATUS_VIA_WINDOWPORT */
763 * Non-specific stubs.
766 static int
767 hup_int_ndecl(VOID_ARGS)
769 return -1;
772 static void
773 hup_void_ndecl(VOID_ARGS)
775 return;
778 /*ARGUSED*/
779 static void
780 hup_void_fdecl_int(arg)
781 int arg UNUSED;
783 return;
786 /*ARGUSED*/
787 static void
788 hup_void_fdecl_winid(window)
789 winid window UNUSED;
791 return;
794 /*ARGUSED*/
795 static void
796 hup_void_fdecl_constchar_p(string)
797 const char *string UNUSED;
799 return;
802 #endif /* HANGUPHANDLING */
804 #ifdef STATUS_VIA_WINDOWPORT
806 /****************************************************************************/
807 /* genl backward compat stuff */
808 /****************************************************************************/
810 const char *status_fieldnm[MAXBLSTATS];
811 const char *status_fieldfmt[MAXBLSTATS];
812 char *status_vals[MAXBLSTATS];
813 boolean status_activefields[MAXBLSTATS];
814 NEARDATA winid WIN_STATUS;
816 void
817 genl_status_init()
819 int i;
821 for (i = 0; i < MAXBLSTATS; ++i) {
822 status_vals[i] = (char *) alloc(MAXCO);
823 *status_vals[i] = '\0';
824 status_activefields[i] = FALSE;
825 status_fieldfmt[i] = (const char *) 0;
827 /* Use a window for the genl version; backward port compatibility */
828 WIN_STATUS = create_nhwindow(NHW_STATUS);
829 display_nhwindow(WIN_STATUS, FALSE);
832 void
833 genl_status_finish()
835 /* tear down routine */
836 int i;
838 /* free alloc'd memory here */
839 for (i = 0; i < MAXBLSTATS; ++i) {
840 if (status_vals[i])
841 free((genericptr_t) status_vals[i]), status_vals[i] = (char *) 0;
845 void
846 genl_status_enablefield(fieldidx, nm, fmt, enable)
847 int fieldidx;
848 const char *nm;
849 const char *fmt;
850 boolean enable;
852 status_fieldfmt[fieldidx] = fmt;
853 status_fieldnm[fieldidx] = nm;
854 status_activefields[fieldidx] = enable;
857 /* call once for each field, then call with BL_FLUSH to output the result */
858 void
859 genl_status_update(idx, ptr, chg, percent)
860 int idx;
861 genericptr_t ptr;
862 int chg UNUSED, percent UNUSED;
864 char newbot1[MAXCO], newbot2[MAXCO];
865 long cond, *condptr = (long *) ptr;
866 register int i;
867 unsigned pass, lndelta;
868 enum statusfields idx1, idx2, *fieldlist;
869 char *nb, *text = (char *) ptr;
871 static enum statusfields fieldorder[][15] = {
872 /* line one */
873 { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
874 BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
875 BL_FLUSH },
876 /* line two, default order */
877 { BL_LEVELDESC, BL_GOLD,
878 BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
879 BL_XP, BL_EXP, BL_HD,
880 BL_TIME,
881 BL_HUNGER, BL_CAP, BL_CONDITION,
882 BL_FLUSH },
883 /* move time to the end */
884 { BL_LEVELDESC, BL_GOLD,
885 BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
886 BL_XP, BL_EXP, BL_HD,
887 BL_HUNGER, BL_CAP, BL_CONDITION,
888 BL_TIME, BL_FLUSH },
889 /* move experience and time to the end */
890 { BL_LEVELDESC, BL_GOLD,
891 BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
892 BL_HUNGER, BL_CAP, BL_CONDITION,
893 BL_XP, BL_EXP, BL_HD, BL_TIME, BL_FLUSH },
894 /* move level description plus gold and experience and time to end */
895 { BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
896 BL_HUNGER, BL_CAP, BL_CONDITION,
897 BL_LEVELDESC, BL_GOLD, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_FLUSH },
900 if (idx != BL_FLUSH) {
901 if (!status_activefields[idx])
902 return;
903 switch (idx) {
904 case BL_CONDITION:
905 cond = *condptr;
906 nb = status_vals[idx];
907 *nb = '\0';
908 if (cond & BL_MASK_STONE)
909 Strcpy(nb = eos(nb), " Stone");
910 if (cond & BL_MASK_SLIME)
911 Strcpy(nb = eos(nb), " Slime");
912 if (cond & BL_MASK_STRNGL)
913 Strcpy(nb = eos(nb), " Strngl");
914 if (cond & BL_MASK_FOODPOIS)
915 Strcpy(nb = eos(nb), " FoodPois");
916 if (cond & BL_MASK_TERMILL)
917 Strcpy(nb = eos(nb), " TermIll");
918 if (cond & BL_MASK_BLIND)
919 Strcpy(nb = eos(nb), " Blind");
920 if (cond & BL_MASK_DEAF)
921 Strcpy(nb = eos(nb), " Deaf");
922 if (cond & BL_MASK_STUN)
923 Strcpy(nb = eos(nb), " Stun");
924 if (cond & BL_MASK_CONF)
925 Strcpy(nb = eos(nb), " Conf");
926 if (cond & BL_MASK_HALLU)
927 Strcpy(nb = eos(nb), " Hallu");
928 if (cond & BL_MASK_LEV)
929 Strcpy(nb = eos(nb), " Lev");
930 if (cond & BL_MASK_FLY)
931 Strcpy(nb = eos(nb), " Fly");
932 if (cond & BL_MASK_RIDE)
933 Strcpy(nb = eos(nb), " Ride");
934 break;
935 default:
936 Sprintf(status_vals[idx],
937 status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s", text);
938 break;
940 return; /* processed one field other than BL_FLUSH */
941 } /* (idx != BL_FLUSH) */
943 /* We've received BL_FLUSH; time to output the gathered data */
944 nb = newbot1;
945 *nb = '\0';
946 for (i = 0; (idx1 = fieldorder[0][i]) != BL_FLUSH; ++i) {
947 if (status_activefields[idx1])
948 Strcpy(nb = eos(nb), status_vals[idx1]);
950 /* if '$' is encoded, buffer length of \GXXXXNNNN is 9 greater than
951 single char; we want to subtract that 9 when checking display length */
952 lndelta = (status_activefields[BL_GOLD]
953 && strstr(status_vals[BL_GOLD], "\\G")) ? 9 : 0;
954 /* basic bot2 formats groups of second line fields into five buffers,
955 then decides how to order those buffers based on comparing lengths
956 of [sub]sets of them to the width of the map; we have more control
957 here but currently emulate that behavior */
958 for (pass = 1; pass <= 4; pass++) {
959 fieldlist = fieldorder[pass];
960 nb = newbot2;
961 *nb = '\0';
962 for (i = 0; (idx2 = fieldlist[i]) != BL_FLUSH; ++i) {
963 if (status_activefields[idx2]) {
964 const char *val = status_vals[idx2];
966 switch (idx2) {
967 case BL_HP: /* for pass 4, Hp comes first; mungspaces()
968 will strip the unwanted leading spaces */
969 case BL_XP: case BL_HD:
970 case BL_TIME:
971 Strcpy(nb = eos(nb), " ");
972 break;
973 case BL_LEVELDESC:
974 /* leveldesc has no leading space, so if we've moved
975 it past the first position, provide one */
976 if (i != 0)
977 Strcpy(nb = eos(nb), " ");
978 break;
980 * We want " hunger encumbrance conditions"
981 * or " encumbrance conditions"
982 * or " hunger conditions"
983 * or " conditions"
984 * 'hunger' is either " " or " hunger_text";
985 * 'encumbrance' is either " " or " encumbrance_text";
986 * 'conditions' is either "" or " cond1 cond2...".
988 case BL_HUNGER:
989 /* hunger==" " - keep it, end up with " ";
990 hunger!=" " - insert space and get " hunger" */
991 if (strcmp(val, " "))
992 Strcpy(nb = eos(nb), " ");
993 break;
994 case BL_CAP:
995 /* cap==" " - suppress it, retain " hunger" or " ";
996 cap!=" " - use it, get " hunger cap" or " cap" */
997 if (!strcmp(val, " "))
998 ++val;
999 break;
1000 default:
1001 break;
1003 Strcpy(nb = eos(nb), val); /* status_vals[idx2] */
1004 } /* status_activefields[idx2] */
1006 if (idx2 == BL_CONDITION && pass < 4
1007 && strlen(newbot2) - lndelta > COLNO)
1008 break; /* switch to next order */
1009 } /* i */
1011 if (idx2 == BL_FLUSH) { /* made it past BL_CONDITION */
1012 if (pass > 1)
1013 mungspaces(newbot2);
1014 break;
1016 } /* pass */
1017 curs(WIN_STATUS, 1, 0);
1018 putstr(WIN_STATUS, 0, newbot1);
1019 curs(WIN_STATUS, 1, 1);
1020 putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
1023 #ifdef STATUS_HILITES
1024 void
1025 genl_status_threshold(fldidx, thresholdtype, threshold, behavior, under, over)
1026 int fldidx UNUSED, thresholdtype UNUSED;
1027 anything threshold UNUSED;
1028 int behavior UNUSED, under UNUSED, over UNUSED;
1030 return;
1032 #endif /* STATUS_HILITES */
1033 #endif /* STATUS_VIA_WINDOWPORT */
1035 STATIC_VAR struct window_procs dumplog_windowprocs_backup;
1036 STATIC_PTR FILE *dumplog_file;
1038 #ifdef DUMPLOG
1039 STATIC_VAR time_t dumplog_now;
1041 STATIC_DCL char *FDECL(dump_fmtstr, (const char *, char *));
1043 STATIC_OVL char *
1044 dump_fmtstr(fmt, buf)
1045 const char *fmt;
1046 char *buf;
1048 const char *fp = fmt;
1049 char *bp = buf;
1050 int slen, len = 0;
1051 char tmpbuf[BUFSZ];
1052 char verbuf[BUFSZ];
1053 long uid;
1054 time_t now;
1056 now = dumplog_now;
1057 uid = (long) getuid();
1060 * Note: %t and %T assume that time_t is a 'long int' number of
1061 * seconds since some epoch value. That's quite iffy.... The
1062 * unit of time might be different and the datum size might be
1063 * some variant of 'long long int'. [Their main purpose is to
1064 * construct a unique file name rather than record the date and
1065 * time; violating the 'long seconds since base-date' assumption
1066 * may or may not interfere with that usage.]
1069 while (fp && *fp && len < BUFSZ-1) {
1070 if (*fp == '%') {
1071 fp++;
1072 switch (*fp) {
1073 default:
1074 goto finish;
1075 case '\0': /* fallthrough */
1076 case '%': /* literal % */
1077 Sprintf(tmpbuf, "%%");
1078 break;
1079 case 't': /* game start, timestamp */
1080 Sprintf(tmpbuf, "%lu", (unsigned long) ubirthday);
1081 break;
1082 case 'T': /* current time, timestamp */
1083 Sprintf(tmpbuf, "%lu", (unsigned long) now);
1084 break;
1085 case 'd': /* game start, YYYYMMDDhhmmss */
1086 Sprintf(tmpbuf, "%08ld%06ld",
1087 yyyymmdd(ubirthday), hhmmss(ubirthday));
1088 break;
1089 case 'D': /* current time, YYYYMMDDhhmmss */
1090 Sprintf(tmpbuf, "%08ld%06ld", yyyymmdd(now), hhmmss(now));
1091 break;
1092 case 'v': /* version, eg. "3.6.1-0" */
1093 Sprintf(tmpbuf, "%s", version_string(verbuf));
1094 break;
1095 case 'u': /* UID */
1096 Sprintf(tmpbuf, "%ld", uid);
1097 break;
1098 case 'n': /* player name */
1099 Sprintf(tmpbuf, "%s", *plname ? plname : "unknown");
1100 break;
1101 case 'N': /* first character of player name */
1102 Sprintf(tmpbuf, "%c", *plname ? *plname : 'u');
1103 break;
1106 slen = strlen(tmpbuf);
1107 if (len + slen < BUFSZ-1) {
1108 len += slen;
1109 Sprintf(bp, "%s", tmpbuf);
1110 bp += slen;
1111 if (*fp) fp++;
1112 } else
1113 break;
1114 } else {
1115 *bp = *fp;
1116 bp++;
1117 fp++;
1118 len++;
1121 finish:
1122 *bp = '\0';
1123 return buf;
1125 #endif /* DUMPLOG */
1127 void
1128 dump_open_log(now)
1129 time_t now;
1131 #ifdef DUMPLOG
1132 char buf[BUFSZ];
1133 char *fname;
1135 dumplog_now = now;
1136 #ifdef SYSCF
1137 if (!sysopt.dumplogfile)
1138 return;
1139 fname = dump_fmtstr(sysopt.dumplogfile, buf);
1140 #else
1141 fname = dump_fmtstr(DUMPLOG_FILE, buf);
1142 #endif
1143 dumplog_file = fopen(fname, "w");
1144 dumplog_windowprocs_backup = windowprocs;
1146 #else /*!DUMPLOG*/
1147 nhUse(now);
1148 #endif /*?DUMPLOG*/
1151 void
1152 dump_close_log()
1154 if (dumplog_file) {
1155 fclose(dumplog_file);
1156 dumplog_file = NULL;
1160 void
1161 dump_putc(ch)
1162 int ch;
1164 /* Not very efficient, but we mostly don't care. */
1165 if (dumplog_file)
1166 putc(ch, dumplog_file);
1169 void
1170 dump_forward_putstr(win, attr, str, no_forward)
1171 winid win;
1172 int attr;
1173 const char *str;
1174 int no_forward;
1176 if (dumplog_file)
1177 fprintf(dumplog_file, "%s\n", str);
1178 if (!no_forward)
1179 putstr(win, attr, str);
1182 /*ARGSUSED*/
1183 STATIC_OVL void
1184 dump_putstr(win, attr, str)
1185 winid win UNUSED;
1186 int attr UNUSED;
1187 const char *str;
1189 if (dumplog_file)
1190 fprintf(dumplog_file, "%s\n", str);
1193 STATIC_OVL winid
1194 dump_create_nhwindow(dummy)
1195 int dummy;
1197 return dummy;
1200 /*ARGUSED*/
1201 STATIC_OVL void
1202 dump_clear_nhwindow(win)
1203 winid win UNUSED;
1205 return;
1208 /*ARGSUSED*/
1209 STATIC_OVL void
1210 dump_display_nhwindow(win, p)
1211 winid win UNUSED;
1212 boolean p UNUSED;
1214 return;
1217 /*ARGUSED*/
1218 STATIC_OVL void
1219 dump_destroy_nhwindow(win)
1220 winid win UNUSED;
1222 return;
1225 /*ARGUSED*/
1226 STATIC_OVL void
1227 dump_start_menu(win)
1228 winid win UNUSED;
1230 return;
1233 /*ARGSUSED*/
1234 STATIC_OVL void
1235 dump_add_menu(win, glyph, identifier, ch, gch, attr, str, preselected)
1236 winid win UNUSED;
1237 int glyph UNUSED;
1238 const anything *identifier UNUSED;
1239 char ch;
1240 char gch UNUSED;
1241 int attr UNUSED;
1242 const char *str;
1243 boolean preselected UNUSED;
1245 if (dumplog_file) {
1246 if (glyph == NO_GLYPH)
1247 fprintf(dumplog_file, " %s\n", str);
1248 else
1249 fprintf(dumplog_file, " %c - %s\n", ch, str);
1253 /*ARGSUSED*/
1254 STATIC_OVL void
1255 dump_end_menu(win, str)
1256 winid win UNUSED;
1257 const char *str;
1259 if (dumplog_file) {
1260 if (str)
1261 fprintf(dumplog_file, "%s\n", str);
1262 else
1263 fputs("\n", dumplog_file);
1267 STATIC_OVL int
1268 dump_select_menu(win, how, item)
1269 winid win UNUSED;
1270 int how UNUSED;
1271 menu_item **item;
1273 *item = (menu_item *) 0;
1274 return 0;
1277 void
1278 dump_redirect(onoff_flag)
1279 boolean onoff_flag;
1281 if (dumplog_file) {
1282 if (onoff_flag) {
1283 windowprocs.win_create_nhwindow = dump_create_nhwindow;
1284 windowprocs.win_clear_nhwindow = dump_clear_nhwindow;
1285 windowprocs.win_display_nhwindow = dump_display_nhwindow;
1286 windowprocs.win_destroy_nhwindow = dump_destroy_nhwindow;
1287 windowprocs.win_start_menu = dump_start_menu;
1288 windowprocs.win_add_menu = dump_add_menu;
1289 windowprocs.win_end_menu = dump_end_menu;
1290 windowprocs.win_select_menu = dump_select_menu;
1291 windowprocs.win_putstr = dump_putstr;
1292 } else {
1293 windowprocs = dumplog_windowprocs_backup;
1295 iflags.in_dumplog = onoff_flag;
1296 } else {
1297 iflags.in_dumplog = FALSE;
1301 /*windows.c*/