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. */
10 extern struct window_procs curses_procs;
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));
19 extern struct window_procs Qt_procs;
25 extern struct window_procs mac_procs;
28 extern struct window_procs beos_procs;
29 extern void FDECL(be_win_init, (int));
30 FAIL /* be_win_init doesn't exist? XXX*/
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));
38 extern struct window_procs win32_procs;
42 extern struct window_procs Gnome_procs;
45 extern struct window_procs mswin_procs;
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 *));
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 *));
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 *));
61 STATIC_DCL void FDECL(def_raw_print, (const char *s));
62 STATIC_DCL void NDECL(def_wait_synch);
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 *));
80 NEARDATA struct window_procs windowprocs;
88 static struct win_choices {
89 struct window_procs *procs;
90 void FDECL((*ini_routine), (int)); /* optional (can be 0) */
92 void *FDECL((*chain_routine), (int, int, void *, void *, void *));
96 { &tty_procs, win_tty_init CHAINR(0) },
98 #ifdef CURSES_GRAPHICS
102 { &X11_procs, win_X11_init CHAINR(0) },
105 { &Qt_procs, 0 CHAINR(0) },
108 { &Gem_procs, win_Gem_init CHAINR(0) },
111 { &mac_procs, 0 CHAINR(0) },
114 { &beos_procs, be_win_init CHAINR(0) },
116 #ifdef AMIGA_INTUITION
118 ami_wininit_data CHAINR(0) }, /* Old font version of the game */
120 ami_wininit_data CHAINR(0) }, /* Tile version of the game */
122 #ifdef WIN32_GRAPHICS
123 { &win32_procs, 0 CHAINR(0) },
125 #ifdef GNOME_GRAPHICS
126 { &Gnome_procs, 0 CHAINR(0) },
128 #ifdef MSWIN_GRAPHICS
129 { &mswin_procs, 0 CHAINR(0) },
132 { &chainin_procs, chainin_procs_init, chainin_procs_chain },
133 { (struct window_procs *) &chainout_procs, chainout_procs_init,
134 chainout_procs_chain },
136 { (struct window_procs *) &trace_procs, trace_procs_init,
139 { 0, 0 CHAINR(0) } /* must be last */
144 struct winlink *nextlink;
145 struct win_choices *wincp;
148 /* NB: this chain does not contain the terminal real window system pointer */
150 static struct winlink *chain = 0;
152 static struct winlink *
155 struct winlink *wl = (struct winlink *) alloc(sizeof *wl);
165 wl_addhead(struct winlink *wl)
167 wl->nextlink = chain;
172 wl_addtail(struct winlink *wl)
174 struct winlink *p = chain;
180 while (p->nextlink) {
186 #endif /* WINCHAIN */
188 static struct win_choices *last_winchoice = 0;
191 genl_can_suspend_no(VOID_ARGS)
197 genl_can_suspend_yes(VOID_ARGS)
212 def_wait_synch(VOID_ARGS)
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
227 static struct win_choices *
233 for (i = 0; winchoices[i].procs; i++) {
234 if (!strcmpi(s, winchoices[i].procs->name)) {
235 return &winchoices[i];
238 return (struct win_choices *) 0;
249 for (i = 0; winchoices[i].procs; i++) {
250 if ('+' == winchoices[i].procs->name[0])
252 if ('-' == winchoices[i].procs->name[0])
254 if (!strcmpi(s, winchoices[i].procs->name)) {
255 windowprocs = *winchoices[i].procs;
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];
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;
272 if (!winchoices[0].procs) {
273 raw_printf("No window types supported?");
274 nh_terminate(EXIT_FAILURE);
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';
287 #undef WINDOW_TYPE_MAXLEN
289 if (!winchoices[1].procs) {
291 "Window type %s not recognized. The only choice is: %s",
292 s, winchoices[0].procs->name);
295 boolean first = TRUE;
298 for (i = 0; winchoices[i].procs; i++) {
299 if ('+' == winchoices[i].procs->name[0])
301 if ('-' == winchoices[i].procs->name[0])
303 Sprintf(eos(buf), "%s%s",
304 first ? "" : ", ", winchoices[i].procs->name);
307 config_error_add("Window type %s not recognized. Choices are: %s",
311 free((genericptr_t) tmps) /*, tmps = 0*/ ;
313 if (windowprocs.win_raw_print == def_raw_print
314 || WINDOWPORT("safe-startup"))
315 nh_terminate(EXIT_SUCCESS);
325 for (i = 0; winchoices[i].procs; i++) {
326 if ('+' != winchoices[i].procs->name[0])
328 if (!strcmpi(s, winchoices[i].procs->name)) {
329 struct winlink *p = wl_new();
331 p->wincp = &winchoices[i];
333 /* NB: The ini_routine() will be called during commit. */
338 windowprocs.win_raw_print = def_raw_print;
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])
344 raw_printf(" %s", winchoices[i].procs->name);
347 nh_terminate(EXIT_FAILURE);
360 /* Save wincap* from the real window system - we'll restore it below. */
361 wincap = windowprocs.wincap;
362 wincap2 = windowprocs.wincap2;
364 /* add -chainin at head and -chainout at tail */
366 p->wincp = win_choices_find("-chainin");
368 raw_printf("Can't locate processor '-chainin'");
374 p->wincp = win_choices_find("-chainout");
376 raw_printf("Can't locate processor '-chainout'");
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);
386 for (n = 1, p = chain; p; n++, p = p->nextlink) {
388 (void) (*p->wincp->chain_routine)(WINCHAIN_INIT, n, p->linkdata,
389 p->nextlink->wincp->procs,
390 p->nextlink->linkdata);
392 (void) (*p->wincp->chain_routine)(WINCHAIN_INIT, n, p->linkdata,
393 last_winchoice->procs, 0);
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;
402 /* Call the init procs. Do not re-init the terminal real win. */
404 while (p->nextlink) {
405 if (p->wincp->ini_routine) {
406 (*p->wincp->ini_routine)(WININIT);
411 /* Install the chain into window procs very late so ini_routine()s
412 * can raw_print on error. */
413 windowprocs = *chain->wincp->procs;
417 struct winlink *np = p->nextlink;
419 p = np; /* assignment, not proof */
422 #endif /* WINCHAIN */
425 * tty_message_menu() provides a means to get feedback from the
426 * --More-- prompt; other interfaces generally don't need that.
430 genl_message_menu(let, how, mesg)
441 genl_preference_update(pref)
442 const char *pref UNUSED;
444 /* window ports are expected to provide
445 their own preference update routine
446 for the preference capabilities that
448 Just return in this genl one. */
453 genl_getmsghistory(init)
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.
471 genl_putmsghistory(msg, is_restoring)
473 boolean is_restoring;
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.
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 */
501 #ifdef HANGUPHANDLING
503 * Dummy windowing scheme used to replace current one with no-ops
504 * in order to avoid all terminal I/O after hangup/disconnect.
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));
525 static void FDECL(hup_cliparound, (int, int));
528 static void FDECL(hup_change_color, (int, long, int));
530 static short FDECL(hup_set_font_name, (winid, char *));
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,
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 *));
543 static struct window_procs hup_procs = {
545 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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 */
564 (void FDECL((*), (char *))) hup_void_fdecl_constchar_p,
565 /* update_positionbar */
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 */
578 hup_void_fdecl_int, /* change_background */
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,
587 hup_void_ndecl, /* status_init */
588 hup_void_ndecl, /* status_finish */
589 genl_status_enablefield, hup_status_update,
593 static void FDECL((*previnterface_exit_nhwindows), (const char *)) = 0;
595 /* hangup has occurred; switch to no-op user interface */
599 char *FDECL((*previnterface_getmsghistory), (BOOLEAN_P)) = 0;
602 /* command processor shouldn't look for 2nd char after seeing ESC */
603 iflags.altmeta = FALSE;
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;
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;
618 windowprocs = hup_procs;
620 if (previnterface_getmsghistory)
621 windowprocs.win_getmsghistory = previnterface_getmsghistory;
625 hup_exit_nhwindows(lastgasp)
626 const char *lastgasp;
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;
636 iflags.window_inited = 0;
640 hup_nhgetch(VOID_ARGS)
642 return '\033'; /* ESC */
647 hup_yn_function(prompt, resp, deflt)
648 const char *prompt UNUSED, *resp UNUSED;
658 hup_nh_poskey(x, y, mod)
659 int *x UNUSED, *y UNUSED, *mod UNUSED;
666 hup_getlin(prompt, outbuf)
667 const char *prompt UNUSED;
670 Strcpy(outbuf, "\033");
675 hup_init_nhwindows(argc_p, argv)
679 iflags.window_inited = 1;
684 hup_create_nhwindow(type)
692 hup_select_menu(window, how, menu_list)
695 struct mi **menu_list UNUSED;
702 hup_add_menu(window, glyph, identifier, sel, grpsel, attr, txt, preselected)
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;
715 hup_end_menu(window, prompt)
717 const char *prompt UNUSED;
724 hup_putstr(window, attr, text)
727 const char *text UNUSED;
734 hup_print_glyph(window, x, y, glyph, bkglyph)
736 xchar x UNUSED, y UNUSED;
745 hup_outrip(tmpwin, how, when)
755 hup_curs(window, x, y)
757 int x UNUSED, y UNUSED;
764 hup_display_nhwindow(window, blocking)
766 boolean blocking UNUSED;
773 hup_display_file(fname, complain)
774 const char *fname UNUSED;
775 boolean complain UNUSED;
784 int x UNUSED, y UNUSED;
793 hup_change_color(color, rgb, reverse)
803 hup_set_font_name(window, fontname)
812 hup_get_color_string(VOID_ARGS)
816 #endif /* CHANGE_COLOR */
820 hup_status_update(idx, ptr, chg, pc, color, colormasks)
822 genericptr_t ptr UNUSED;
823 int chg UNUSED, pc UNUSED, color UNUSED;
824 unsigned long *colormasks UNUSED;
831 * Non-specific stubs.
835 hup_int_ndecl(VOID_ARGS)
841 hup_void_ndecl(VOID_ARGS)
848 hup_void_fdecl_int(arg)
856 hup_void_fdecl_winid(window)
864 hup_void_fdecl_constchar_p(string)
865 const char *string UNUSED;
870 #endif /* HANGUPHANDLING */
873 /****************************************************************************/
874 /* genl backward compat stuff */
875 /****************************************************************************/
877 const char *status_fieldnm[MAXBLSTATS];
878 const char *status_fieldfmt[MAXBLSTATS];
879 char *status_vals[MAXBLSTATS];
880 boolean status_activefields[MAXBLSTATS];
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;
893 /* Use a window for the genl version; backward port compatibility */
894 WIN_STATUS = create_nhwindow(NHW_STATUS);
895 display_nhwindow(WIN_STATUS, FALSE);
901 /* tear down routine */
904 /* free alloc'd memory here */
905 for (i = 0; i < MAXBLSTATS; ++i) {
907 free((genericptr_t) status_vals[i]), status_vals[i] = (char *) 0;
912 genl_status_enablefield(fieldidx, nm, fmt, enable)
918 status_fieldfmt[fieldidx] = fmt;
919 status_fieldnm[fieldidx] = nm;
920 status_activefields[fieldidx] = enable;
923 /* call once for each field, then call with BL_FLUSH to output the result */
925 genl_status_update(idx, ptr, chg, percent, color, colormasks)
928 int chg UNUSED, percent UNUSED, color UNUSED;
929 unsigned long *colormasks UNUSED;
931 char newbot1[MAXCO], newbot2[MAXCO];
932 long cond, *condptr = (long *) ptr;
934 unsigned pass, lndelta;
935 enum statusfields idx1, idx2, *fieldlist;
936 char *nb, *text = (char *) ptr;
938 static enum statusfields fieldorder[][15] = {
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,
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,
948 BL_HUNGER, BL_CAP, BL_CONDITION,
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,
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 },
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;
973 if (!status_activefields[idx])
977 cond = condptr ? *condptr : 0L;
978 nb = status_vals[idx];
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");
1008 Sprintf(status_vals[idx],
1009 status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s",
1013 return; /* processed one field other than BL_FLUSH */
1014 } /* (idx >= 0, thus not BL_FLUSH, BL_RESET, BL_CHARACTERISTICS) */
1016 /* does BL_RESET require any specific code to ensure all fields ? */
1018 if (!(idx == BL_FLUSH || idx == BL_RESET))
1021 /* We've received BL_FLUSH; time to output the gathered data */
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]);
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];
1044 for (i = 0; (idx2 = fieldlist[i]) != BL_FLUSH; ++i) {
1045 if (status_activefields[idx2]) {
1046 const char *val = status_vals[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:
1053 Strcpy(nb = eos(nb), " ");
1056 /* leveldesc has no leading space, so if we've moved
1057 it past the first position, provide one */
1059 Strcpy(nb = eos(nb), " ");
1062 * We want " hunger encumbrance conditions"
1063 * or " encumbrance conditions"
1064 * or " hunger conditions"
1066 * 'hunger' is either " " or " hunger_text";
1067 * 'encumbrance' is either " " or " encumbrance_text";
1068 * 'conditions' is either "" or " cond1 cond2...".
1071 /* hunger==" " - keep it, end up with " ";
1072 hunger!=" " - insert space and get " hunger" */
1073 if (strcmp(val, " "))
1074 Strcpy(nb = eos(nb), " ");
1077 /* cap==" " - suppress it, retain " hunger" or " ";
1078 cap!=" " - use it, get " hunger cap" or " cap" */
1079 if (!strcmp(val, " "))
1085 Strcpy(nb = eos(nb), val); /* status_vals[idx2] */
1086 } /* status_activefields[idx2] */
1088 if (idx2 == BL_CONDITION && pass < 4
1089 && strlen(newbot2) - lndelta > COLNO)
1090 break; /* switch to next order */
1093 if (idx2 == BL_FLUSH) { /* made it past BL_CONDITION */
1095 mungspaces(newbot2);
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 */
1105 STATIC_VAR struct window_procs dumplog_windowprocs_backup;
1106 STATIC_VAR FILE *dumplog_file;
1109 STATIC_VAR time_t dumplog_now;
1112 dump_fmtstr(fmt, buf, fullsubs)
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 */
1119 const char *fp = fmt;
1128 uid = (long) getuid();
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.]
1140 while (fp && *fp && len < BUFSZ - 1) {
1146 case '\0': /* fallthrough */
1147 case '%': /* literal % */
1148 Sprintf(tmpbuf, "%%");
1150 case 't': /* game start, timestamp */
1152 Sprintf(tmpbuf, "%lu", (unsigned long) ubirthday);
1154 Strcpy(tmpbuf, "{game start cookie}");
1156 case 'T': /* current time, timestamp */
1158 Sprintf(tmpbuf, "%lu", (unsigned long) now);
1160 Strcpy(tmpbuf, "{current time cookie}");
1162 case 'd': /* game start, YYYYMMDDhhmmss */
1164 Sprintf(tmpbuf, "%08ld%06ld",
1165 yyyymmdd(ubirthday), hhmmss(ubirthday));
1167 Strcpy(tmpbuf, "{game start date+time}");
1169 case 'D': /* current time, YYYYMMDDhhmmss */
1171 Sprintf(tmpbuf, "%08ld%06ld", yyyymmdd(now), hhmmss(now));
1173 Strcpy(tmpbuf, "{current date+time}");
1175 case 'v': /* version, eg. "3.6.5-0" */
1176 Sprintf(tmpbuf, "%s", version_string(verbuf));
1179 Sprintf(tmpbuf, "%ld", uid);
1181 case 'n': /* player name */
1183 Sprintf(tmpbuf, "%s", *plname ? plname : "unknown");
1185 Strcpy(tmpbuf, "{hero name}");
1187 case 'N': /* first character of player name */
1189 Sprintf(tmpbuf, "%c", *plname ? *plname : 'u');
1191 Strcpy(tmpbuf, "{hero initial}");
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) */
1206 slen = (int) strlen(tmpbuf);
1207 if (len + slen < BUFSZ - 1) {
1209 Sprintf(bp, "%s", tmpbuf);
1226 #endif /* DUMPLOG */
1238 if (!sysopt.dumplogfile)
1240 fname = dump_fmtstr(sysopt.dumplogfile, buf, TRUE);
1242 fname = dump_fmtstr(DUMPLOG_FILE, buf, TRUE);
1244 dumplog_file = fopen(fname, "w");
1245 dumplog_windowprocs_backup = windowprocs;
1256 (void) fclose(dumplog_file);
1257 dumplog_file = (FILE *) 0;
1262 dump_forward_putstr(win, attr, str, no_forward)
1269 fprintf(dumplog_file, "%s\n", str);
1271 putstr(win, attr, str);
1276 dump_putstr(win, attr, str)
1282 fprintf(dumplog_file, "%s\n", str);
1286 dump_create_nhwindow(dummy)
1294 dump_clear_nhwindow(win)
1302 dump_display_nhwindow(win, p)
1311 dump_destroy_nhwindow(win)
1319 dump_start_menu(win)
1327 dump_add_menu(win, glyph, identifier, ch, gch, attr, str, preselected)
1330 const anything *identifier UNUSED;
1335 boolean preselected UNUSED;
1338 if (glyph == NO_GLYPH)
1339 fprintf(dumplog_file, " %s\n", str);
1341 fprintf(dumplog_file, " %c - %s\n", ch, str);
1347 dump_end_menu(win, str)
1353 fprintf(dumplog_file, "%s\n", str);
1355 fputs("\n", dumplog_file);
1360 dump_select_menu(win, how, item)
1365 *item = (menu_item *) 0;
1370 dump_redirect(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;
1385 windowprocs = dumplog_windowprocs_backup;
1387 iflags.in_dumplog = onoff_flag;
1389 iflags.in_dumplog = FALSE;
1396 extern const char *hilites[CLR_MAX];
1398 extern NEARDATA char *hilites[CLR_MAX];
1407 return (iflags.use_color && windowprocs.name
1408 && (windowprocs.wincap & WC_COLOR) && windowprocs.has_color[color]
1410 #if defined(TEXTCOLOR) && defined(TERMLIB) && !defined(NO_TERMS)
1411 && (hilites[color] != 0)