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)
982 Strcpy(nb = eos(nb), " Stone");
984 Strcpy(nb = eos(nb), "
\90ÃŽ
\89»");
985 if (cond & BL_MASK_SLIME)
987 Strcpy(nb = eos(nb), " Slime");
989 Strcpy(nb = eos(nb), "
\82Ç
\82ë
\82Ç
\82ë");
990 if (cond & BL_MASK_STRNGL)
992 Strcpy(nb = eos(nb), " Strngl");
994 Strcpy(nb = eos(nb), "
\92\82\91§");
995 if (cond & BL_MASK_FOODPOIS)
997 Strcpy(nb = eos(nb), " FoodPois");
999 Strcpy(nb = eos(nb), "
\90H
\93Ã…");
1000 if (cond & BL_MASK_TERMILL)
1002 Strcpy(nb = eos(nb), " TermIll");
1004 Strcpy(nb = eos(nb), "
\95a
\8bC");
1005 if (cond & BL_MASK_BLIND)
1007 Strcpy(nb = eos(nb), " Blind");
1009 Strcpy(nb = eos(nb), "
\96Ó
\96Ú");
1010 if (cond & BL_MASK_DEAF)
1012 Strcpy(nb = eos(nb), " Deaf");
1014 Strcpy(nb = eos(nb), "
\8e¨
\98W");
1015 if (cond & BL_MASK_STUN)
1017 Strcpy(nb = eos(nb), " Stun");
1019 Strcpy(nb = eos(nb), " á¿
\9dò");
1020 if (cond & BL_MASK_CONF)
1022 Strcpy(nb = eos(nb), " Conf");
1024 Strcpy(nb = eos(nb), "
\8d¬
\97\90");
1025 if (cond & BL_MASK_HALLU)
1027 Strcpy(nb = eos(nb), " Hallu");
1029 Strcpy(nb = eos(nb), "
\8c¶
\8ao");
1030 if (cond & BL_MASK_LEV)
1032 Strcpy(nb = eos(nb), " Lev");
1034 Strcpy(nb = eos(nb), "
\95\82\97V");
1035 if (cond & BL_MASK_FLY)
1037 Strcpy(nb = eos(nb), " Fly");
1039 Strcpy(nb = eos(nb), "
\94ò
\8ds");
1040 if (cond & BL_MASK_RIDE)
1042 Strcpy(nb = eos(nb), " Ride");
1044 Strcpy(nb = eos(nb), "
\8bR
\8fæ");
1047 Sprintf(status_vals[idx],
1048 status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s",
1052 return; /* processed one field other than BL_FLUSH */
1053 } /* (idx >= 0, thus not BL_FLUSH, BL_RESET, BL_CHARACTERISTICS) */
1055 /* does BL_RESET require any specific code to ensure all fields ? */
1057 if (!(idx == BL_FLUSH || idx == BL_RESET))
1060 /* We've received BL_FLUSH; time to output the gathered data */
1063 /* BL_FLUSH is the only pseudo-index value we need to check for
1064 in the loop below because it is the only entry used to pad the
1065 end of the fieldorder array. We could stop on any
1066 negative (illegal) index, but this should be fine */
1067 for (i = 0; (idx1 = fieldorder[0][i]) != BL_FLUSH; ++i) {
1068 if (status_activefields[idx1])
1069 Strcpy(nb = eos(nb), status_vals[idx1]);
1071 /* if '$' is encoded, buffer length of \GXXXXNNNN is 9 greater than
1072 single char; we want to subtract that 9 when checking display length */
1073 lndelta = (status_activefields[BL_GOLD]
1074 && strstr(status_vals[BL_GOLD], "\\G")) ? 9 : 0;
1075 /* basic bot2 formats groups of second line fields into five buffers,
1076 then decides how to order those buffers based on comparing lengths
1077 of [sub]sets of them to the width of the map; we have more control
1078 here but currently emulate that behavior */
1079 for (pass = 1; pass <= 4; pass++) {
1080 fieldlist = fieldorder[pass];
1083 for (i = 0; (idx2 = fieldlist[i]) != BL_FLUSH; ++i) {
1084 if (status_activefields[idx2]) {
1085 const char *val = status_vals[idx2];
1088 case BL_HP: /* for pass 4, Hp comes first; mungspaces()
1089 will strip the unwanted leading spaces */
1090 case BL_XP: case BL_HD:
1092 Strcpy(nb = eos(nb), " ");
1095 /* leveldesc has no leading space, so if we've moved
1096 it past the first position, provide one */
1098 Strcpy(nb = eos(nb), " ");
1101 * We want " hunger encumbrance conditions"
1102 * or " encumbrance conditions"
1103 * or " hunger conditions"
1105 * 'hunger' is either " " or " hunger_text";
1106 * 'encumbrance' is either " " or " encumbrance_text";
1107 * 'conditions' is either "" or " cond1 cond2...".
1110 /* hunger==" " - keep it, end up with " ";
1111 hunger!=" " - insert space and get " hunger" */
1112 if (strcmp(val, " "))
1113 Strcpy(nb = eos(nb), " ");
1116 /* cap==" " - suppress it, retain " hunger" or " ";
1117 cap!=" " - use it, get " hunger cap" or " cap" */
1118 if (!strcmp(val, " "))
1124 Strcpy(nb = eos(nb), val); /* status_vals[idx2] */
1125 } /* status_activefields[idx2] */
1127 if (idx2 == BL_CONDITION && pass < 4
1128 && strlen(newbot2) - lndelta > COLNO)
1129 break; /* switch to next order */
1132 if (idx2 == BL_FLUSH) { /* made it past BL_CONDITION */
1134 mungspaces(newbot2);
1138 curs(WIN_STATUS, 1, 0);
1139 putstr(WIN_STATUS, 0, newbot1);
1140 curs(WIN_STATUS, 1, 1);
1141 putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
1144 STATIC_VAR struct window_procs dumplog_windowprocs_backup;
1145 STATIC_VAR FILE *dumplog_file;
1148 STATIC_VAR time_t dumplog_now;
1151 dump_fmtstr(fmt, buf, fullsubs)
1154 boolean fullsubs; /* True -> full substitution for file name, False ->
1155 * partial substitution for '--showpaths' feedback
1156 * where there's no game in progress when executed */
1158 const char *fp = fmt;
1167 uid = (long) getuid();
1170 * Note: %t and %T assume that time_t is a 'long int' number of
1171 * seconds since some epoch value. That's quite iffy.... The
1172 * unit of time might be different and the datum size might be
1173 * some variant of 'long long int'. [Their main purpose is to
1174 * construct a unique file name rather than record the date and
1175 * time; violating the 'long seconds since base-date' assumption
1176 * may or may not interfere with that usage.]
1179 while (fp && *fp && len < BUFSZ - 1) {
1185 case '\0': /* fallthrough */
1186 case '%': /* literal % */
1187 Sprintf(tmpbuf, "%%");
1189 case 't': /* game start, timestamp */
1191 Sprintf(tmpbuf, "%lu", (unsigned long) ubirthday);
1193 Strcpy(tmpbuf, "{game start cookie}");
1195 case 'T': /* current time, timestamp */
1197 Sprintf(tmpbuf, "%lu", (unsigned long) now);
1199 Strcpy(tmpbuf, "{current time cookie}");
1201 case 'd': /* game start, YYYYMMDDhhmmss */
1203 Sprintf(tmpbuf, "%08ld%06ld",
1204 yyyymmdd(ubirthday), hhmmss(ubirthday));
1206 Strcpy(tmpbuf, "{game start date+time}");
1208 case 'D': /* current time, YYYYMMDDhhmmss */
1210 Sprintf(tmpbuf, "%08ld%06ld", yyyymmdd(now), hhmmss(now));
1212 Strcpy(tmpbuf, "{current date+time}");
1214 case 'v': /* version, eg. "3.6.5-0" */
1215 Sprintf(tmpbuf, "%s", version_string(verbuf));
1218 Sprintf(tmpbuf, "%ld", uid);
1220 case 'n': /* player name */
1222 Sprintf(tmpbuf, "%s", *plname ? plname : "unknown");
1224 Strcpy(tmpbuf, "{hero name}");
1226 case 'N': /* first character of player name */
1228 Sprintf(tmpbuf, "%c", *plname ? *plname : 'u');
1230 Strcpy(tmpbuf, "{hero initial}");
1234 /* replace potentially troublesome characters (including
1235 <space> even though it might be an acceptable file name
1236 character); user shouldn't be able to get ' ' or '/'
1237 or '\\' into plname[] but play things safe */
1238 (void) strNsubst(tmpbuf, " ", "_", 0);
1239 (void) strNsubst(tmpbuf, "/", "_", 0);
1240 (void) strNsubst(tmpbuf, "\\", "_", 0);
1241 /* note: replacements are only done on field substitutions,
1242 not on the template (from sysconf or DUMPLOG_FILE) */
1245 slen = (int) strlen(tmpbuf);
1246 if (len + slen < BUFSZ - 1) {
1248 Sprintf(bp, "%s", tmpbuf);
1265 #endif /* DUMPLOG */
1277 if (!sysopt.dumplogfile)
1279 fname = dump_fmtstr(sysopt.dumplogfile, buf, TRUE);
1281 fname = dump_fmtstr(DUMPLOG_FILE, buf, TRUE);
1283 dumplog_file = fopen(fname, "w");
1284 dumplog_windowprocs_backup = windowprocs;
1295 (void) fclose(dumplog_file);
1296 dumplog_file = (FILE *) 0;
1301 dump_forward_putstr(win, attr, str, no_forward)
1308 fprintf(dumplog_file, "%s\n", str);
1310 putstr(win, attr, str);
1315 dump_putstr(win, attr, str)
1321 fprintf(dumplog_file, "%s\n", str);
1325 dump_create_nhwindow(dummy)
1333 dump_clear_nhwindow(win)
1341 dump_display_nhwindow(win, p)
1350 dump_destroy_nhwindow(win)
1358 dump_start_menu(win)
1366 dump_add_menu(win, glyph, identifier, ch, gch, attr, str, preselected)
1369 const anything *identifier UNUSED;
1374 boolean preselected UNUSED;
1377 if (glyph == NO_GLYPH)
1378 fprintf(dumplog_file, " %s\n", str);
1380 fprintf(dumplog_file, " %c - %s\n", ch, str);
1386 dump_end_menu(win, str)
1392 fprintf(dumplog_file, "%s\n", str);
1394 fputs("\n", dumplog_file);
1399 dump_select_menu(win, how, item)
1404 *item = (menu_item *) 0;
1409 dump_redirect(onoff_flag)
1414 windowprocs.win_create_nhwindow = dump_create_nhwindow;
1415 windowprocs.win_clear_nhwindow = dump_clear_nhwindow;
1416 windowprocs.win_display_nhwindow = dump_display_nhwindow;
1417 windowprocs.win_destroy_nhwindow = dump_destroy_nhwindow;
1418 windowprocs.win_start_menu = dump_start_menu;
1419 windowprocs.win_add_menu = dump_add_menu;
1420 windowprocs.win_end_menu = dump_end_menu;
1421 windowprocs.win_select_menu = dump_select_menu;
1422 windowprocs.win_putstr = dump_putstr;
1424 windowprocs = dumplog_windowprocs_backup;
1426 iflags.in_dumplog = onoff_flag;
1428 iflags.in_dumplog = FALSE;
1435 extern const char *hilites[CLR_MAX];
1437 extern NEARDATA char *hilites[CLR_MAX];
1446 return (iflags.use_color && windowprocs.name
1447 && (windowprocs.wincap & WC_COLOR) && windowprocs.has_color[color]
1449 #if defined(TEXTCOLOR) && defined(TERMLIB) && !defined(NO_TERMS)
1450 && (hilites[color] != 0)