1 /* NetHack 3.6 windows.c $NHDT-Date: 1448013599 2015/11/20 09:59:59 $ $NHDT-Branch: master $:$NHDT-Revision: 1.35 $ */
2 /* Copyright (c) D. Cohrs, 1993. */
3 /* NetHack may be freely redistributed. See license for details. */
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));
16 extern struct window_procs Qt_procs;
22 extern struct window_procs mac_procs;
25 extern struct window_procs beos_procs;
26 extern void FDECL(be_win_init, (int));
27 FAIL /* be_win_init doesn't exist? XXX*/
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));
35 extern struct window_procs win32_procs;
39 extern struct window_procs Gnome_procs;
42 extern struct window_procs mswin_procs;
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 *));
58 STATIC_DCL void FDECL(def_raw_print, (const char *s));
63 NEARDATA struct window_procs windowprocs;
71 static struct win_choices {
72 struct window_procs *procs;
73 void FDECL((*ini_routine), (int)); /* optional (can be 0) */
75 void *FDECL((*chain_routine), (int, int, void *, void *, void *));
79 { &tty_procs, win_tty_init CHAINR(0) },
82 { &X11_procs, win_X11_init CHAINR(0) },
85 { &Qt_procs, 0 CHAINR(0) },
88 { &Gem_procs, win_Gem_init CHAINR(0) },
91 { &mac_procs, 0 CHAINR(0) },
94 { &beos_procs, be_win_init CHAINR(0) },
96 #ifdef AMIGA_INTUITION
98 ami_wininit_data CHAINR(0) }, /* Old font version of the game */
100 ami_wininit_data CHAINR(0) }, /* Tile version of the game */
102 #ifdef WIN32_GRAPHICS
103 { &win32_procs, 0 CHAINR(0) },
105 #ifdef GNOME_GRAPHICS
106 { &Gnome_procs, 0 CHAINR(0) },
108 #ifdef MSWIN_GRAPHICS
109 { &mswin_procs, 0 CHAINR(0) },
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,
119 { 0, 0 CHAINR(0) } /* must be last */
124 struct winlink *nextlink;
125 struct win_choices *wincp;
128 /* NB: this chain does not contain the terminal real window system pointer */
130 static struct winlink *chain = 0;
132 static struct winlink *
135 return calloc(1, sizeof(struct winlink));
138 wl_addhead(struct winlink *wl)
140 wl->nextlink = chain;
144 wl_addtail(struct winlink *wl)
146 struct winlink *p = chain;
152 while (p->nextlink) {
158 #endif /* WINCHAIN */
160 static struct win_choices *last_winchoice = 0;
163 genl_can_suspend_no(VOID_ARGS)
169 genl_can_suspend_yes(VOID_ARGS)
183 static struct win_choices *
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;
204 for (i = 0; winchoices[i].procs; i++) {
205 if ('+' == winchoices[i].procs->name[0])
207 if ('-' == winchoices[i].procs->name[0])
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];
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?");
228 if (!winchoices[1].procs) {
229 raw_printf("Window type %s not recognized. The only choice is: %s.",
230 s, winchoices[0].procs->name);
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])
236 if ('-' == winchoices[i].procs->name[0])
238 raw_printf(" %s", winchoices[i].procs->name);
242 if (windowprocs.win_raw_print == def_raw_print)
243 terminate(EXIT_SUCCESS);
254 for (i = 0; winchoices[i].procs; i++) {
255 if ('+' != winchoices[i].procs->name[0])
257 if (!strcmpi(s, winchoices[i].procs->name)) {
258 struct winlink *p = wl_new();
259 p->wincp = &winchoices[i];
261 /* NB: The ini_routine() will be called during commit. */
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])
272 raw_printf(" %s", winchoices[i].procs->name);
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 */
294 p->wincp = win_choices_find("-chainin");
296 raw_printf("Can't locate processor '-chainin'");
302 p->wincp = win_choices_find("-chainout");
304 raw_printf("Can't locate processor '-chainout'");
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) {
316 (void) (*p->wincp->chain_routine)(WINCHAIN_INIT, n, p->linkdata,
317 p->nextlink->wincp->procs,
318 p->nextlink->linkdata);
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. */
332 while (p->nextlink) {
333 if (p->wincp->ini_routine) {
334 (*p->wincp->ini_routine)(WININIT);
339 /* Install the chain into window procs very late so ini_routine()s
340 * can raw_print on error. */
341 windowprocs = *chain->wincp->procs;
345 struct winlink *np = p->nextlink;
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.
358 genl_message_menu(let, how, mesg)
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
376 Just return in this genl one. */
381 genl_getmsghistory(init)
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.
399 genl_putmsghistory(msg, is_restoring)
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 */
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));
453 static void FDECL(hup_cliparound, (int, int));
456 static void FDECL(hup_change_color, (int, long, int));
458 static short FDECL(hup_set_font_name, (winid, char *));
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));
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 */
491 (void FDECL((*), (char *))) hup_void_fdecl_constchar_p,
492 /* update_positionbar */
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 */
505 hup_void_fdecl_int, /* change_background */
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,
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,
521 #endif /* STATUS_VIA_WINDOWPORT */
525 static void FDECL((*previnterface_exit_nhwindows), (const char *)) = 0;
527 /* hangup has occurred; switch to no-op user interface */
531 char *FDECL((*previnterface_getmsghistory), (BOOLEAN_P)) = 0;
534 /* command processor shouldn't look for 2nd char after seeing ESC */
535 iflags.altmeta = FALSE;
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;
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;
572 hup_nhgetch(VOID_ARGS)
574 return '\033'; /* ESC */
579 hup_yn_function(prompt, resp, deflt)
580 const char *prompt UNUSED, *resp UNUSED;
590 hup_nh_poskey(x, y, mod)
591 int *x UNUSED, *y UNUSED, *mod UNUSED;
598 hup_getlin(prompt, outbuf)
599 const char *prompt UNUSED;
602 Strcpy(outbuf, "\033");
607 hup_init_nhwindows(argc_p, argv)
611 iflags.window_inited = 1;
616 hup_create_nhwindow(type)
624 hup_select_menu(window, how, menu_list)
627 struct mi **menu_list UNUSED;
634 hup_add_menu(window, glyph, identifier, sel, grpsel, attr, txt, preselected)
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;
647 hup_end_menu(window, prompt)
649 const char *prompt UNUSED;
656 hup_putstr(window, attr, text)
659 const char *text UNUSED;
666 hup_print_glyph(window, x, y, glyph, bkglyph)
668 xchar x UNUSED, y UNUSED;
677 hup_outrip(tmpwin, how, when)
687 hup_curs(window, x, y)
689 int x UNUSED, y UNUSED;
696 hup_display_nhwindow(window, blocking)
698 boolean blocking UNUSED;
705 hup_display_file(fname, complain)
706 const char *fname UNUSED;
707 boolean complain UNUSED;
716 int x UNUSED, y UNUSED;
725 hup_change_color(color, rgb, reverse)
735 hup_set_font_name(window, fontname)
744 hup_get_color_string(VOID_ARGS)
748 #endif /* CHANGE_COLOR */
750 #ifdef STATUS_VIA_WINDOWPORT
753 hup_status_update(idx, ptr, chg, percent)
754 int idx UNUSED, chg UNUSED, percent UNUSED;
755 genericptr_t ptr UNUSED;
759 #endif /* STATUS_VIA_WINDOWPORT */
762 * Non-specific stubs.
766 hup_int_ndecl(VOID_ARGS)
772 hup_void_ndecl(VOID_ARGS)
779 hup_void_fdecl_int(arg)
787 hup_void_fdecl_winid(window)
795 hup_void_fdecl_constchar_p(string)
796 const char *string UNUSED;
801 #endif /* HANGUPHANDLING */
803 #ifdef STATUS_VIA_WINDOWPORT
805 /****************************************************************************/
806 /* genl backward compat stuff */
807 /****************************************************************************/
809 const char *status_fieldnm[MAXBLSTATS];
810 const char *status_fieldfmt[MAXBLSTATS];
811 char *status_vals[MAXBLSTATS];
812 boolean status_activefields[MAXBLSTATS];
813 NEARDATA winid WIN_STATUS;
819 for (i = 0; i < MAXBLSTATS; ++i) {
820 status_vals[i] = (char *) alloc(MAXCO);
821 *status_vals[i] = '\0';
822 status_activefields[i] = FALSE;
823 status_fieldfmt[i] = (const char *) 0;
825 /* Use a window for the genl version; backward port compatibility */
826 WIN_STATUS = create_nhwindow(NHW_STATUS);
827 display_nhwindow(WIN_STATUS, FALSE);
833 /* tear down routine */
836 /* free alloc'd memory here */
837 for (i = 0; i < MAXBLSTATS; ++i) {
839 free((genericptr_t) status_vals[i]);
840 status_vals[i] = (char *) 0;
845 genl_status_enablefield(fieldidx, nm, fmt, enable)
851 status_fieldfmt[fieldidx] = fmt;
852 status_fieldnm[fieldidx] = nm;
853 status_activefields[fieldidx] = enable;
857 genl_status_update(idx, ptr, chg, percent)
858 int idx, chg, percent;
861 char newbot1[MAXCO], newbot2[MAXCO];
862 long cond, *condptr = (long *) ptr;
864 char *text = (char *) ptr;
866 enum statusfields fieldorder[2][15] = {
867 { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
868 BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
870 { BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
871 BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
872 BL_CAP, BL_CONDITION, BL_FLUSH }
875 if (idx != BL_FLUSH) {
876 if (!status_activefields[idx])
881 *status_vals[idx] = '\0';
882 if (cond & BL_MASK_BLIND)
883 Strcat(status_vals[idx], " Blind");
884 if (cond & BL_MASK_CONF)
885 Strcat(status_vals[idx], " Conf");
886 if (cond & BL_MASK_FOODPOIS)
887 Strcat(status_vals[idx], " FoodPois");
888 if (cond & BL_MASK_ILL)
889 Strcat(status_vals[idx], " Ill");
890 if (cond & BL_MASK_STUNNED)
891 Strcat(status_vals[idx], " Stun");
892 if (cond & BL_MASK_HALLU)
893 Strcat(status_vals[idx], " Hallu");
894 if (cond & BL_MASK_SLIMED)
895 Strcat(status_vals[idx], " Slime");
898 Sprintf(status_vals[idx],
899 status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s", text);
904 /* This genl version updates everything on the display, everytime */
906 for (i = 0; fieldorder[0][i] != BL_FLUSH; ++i) {
907 int idx1 = fieldorder[0][i];
908 if (status_activefields[idx1])
909 Strcat(newbot1, status_vals[idx1]);
912 for (i = 0; fieldorder[1][i] != BL_FLUSH; ++i) {
913 int idx2 = fieldorder[1][i];
914 if (status_activefields[idx2])
915 Strcat(newbot2, status_vals[idx2]);
917 curs(WIN_STATUS, 1, 0);
918 putstr(WIN_STATUS, 0, newbot1);
919 curs(WIN_STATUS, 1, 1);
920 putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
923 #ifdef STATUS_HILITES
925 genl_status_threshold(fldidx, thresholdtype, threshold, behavior, under, over)
926 int fldidx, thresholdtype;
927 int behavior, under, over;
932 #endif /* STATUS_HILITES */
933 #endif /* STATUS_VIA_WINDOWPORT */