617 lines
19 KiB
C
617 lines
19 KiB
C
/* NetHack 3.7 vmstty.c $NHDT-Date: 1596498309 2020/08/03 23:45:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.21 $ */
|
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
|
/*-Copyright (c) Robert Patrick Rankin, 2011. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
/* tty.c - (VMS) version */
|
|
|
|
#define NEED_VARARGS
|
|
#include "hack.h"
|
|
#include "wintty.h"
|
|
#include "tcap.h"
|
|
|
|
#ifdef VMSVSI
|
|
#include <lib$routines.h>
|
|
#include <smg$routines.h>
|
|
#include <starlet.h>
|
|
#include <elfdef.h>
|
|
#endif
|
|
|
|
#include <descrip.h>
|
|
#include <iodef.h>
|
|
#ifndef __GNUC__
|
|
#include <smgdef.h>
|
|
#include <ttdef.h>
|
|
#include <tt2def.h>
|
|
#else /* values needed from missing include files */
|
|
#define SMG$K_TRM_UP 274
|
|
#define SMG$K_TRM_DOWN 275
|
|
#define SMG$K_TRM_LEFT 276
|
|
#define SMG$K_TRM_RIGHT 277
|
|
#define TT$M_MECHTAB 0x00000100 /* hardware tab support */
|
|
#define TT$M_MECHFORM 0x00080000 /* hardware form-feed support */
|
|
#define TT$M_NOBRDCST 0x00020000 /* disable broadcast messages, but */
|
|
#define TT2$M_BRDCSTMBX 0x00000010 /* catch them in associated mailbox */
|
|
#define TT2$M_APP_KEYPAD 0x00800000 /* application vs numeric keypad mode */
|
|
#endif /* __GNUC__ */
|
|
#ifdef USE_QIO_INPUT
|
|
#include <ssdef.h>
|
|
#endif
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
|
|
|
|
#ifndef VMSVSI
|
|
unsigned long lib$disable_ctrl(), lib$enable_ctrl();
|
|
unsigned long sys$assign(), sys$dassgn(), sys$qiow();
|
|
#endif
|
|
#ifndef USE_QIO_INPUT
|
|
#ifndef VMSVSI
|
|
unsigned long smg$create_virtual_keyboard(), smg$delete_virtual_keyboard(),
|
|
smg$read_keystroke(), smg$cancel_input();
|
|
#endif
|
|
#else
|
|
static short parse_function_key(int);
|
|
#endif
|
|
static void setctty(void);
|
|
static void resettty(void);
|
|
|
|
#define vms_ok(sts) ((sts) &1)
|
|
#define META(c) ((c) | 0x80) /* 8th bit */
|
|
#define CTRL(c) ((c) & 0x1F)
|
|
#define CMASK(c) (1 << CTRL(c))
|
|
#define LIB$M_CLI_CTRLT CMASK('T') /* 0x00100000 */
|
|
#define LIB$M_CLI_CTRLY CMASK('Y') /* 0x02000000 */
|
|
#define ESC '\033'
|
|
#define CSI META(ESC) /* '\233' */
|
|
#define SS3 META(CTRL('O')) /* '\217' */
|
|
|
|
extern short ospeed;
|
|
char erase_char, intr_char, kill_char;
|
|
static boolean settty_needed = FALSE, bombing = FALSE;
|
|
static unsigned long kb = 0;
|
|
#ifdef USE_QIO_INPUT
|
|
static char inputbuf[15 + 1], *inp = 0;
|
|
static int inc = 0;
|
|
#endif
|
|
|
|
#define QIO_FUNC IO$_TTYREADALL | IO$M_NOECHO | IO$M_TRMNOECHO
|
|
#ifdef MAIL
|
|
#define TT_SPECIAL_HANDLING (TT$M_MECHTAB | TT$M_MECHFORM | TT$M_NOBRDCST)
|
|
#define TT2_SPECIAL_HANDLING (TT2$M_BRDCSTMBX)
|
|
#else
|
|
#define TT_SPECIAL_HANDLING (TT$M_MECHTAB | TT$M_MECHFORM)
|
|
#define TT2_SPECIAL_HANDLING (0)
|
|
#endif
|
|
#define Uword unsigned short
|
|
#define Ubyte unsigned char
|
|
struct _rd_iosb { /* i/o status block for read */
|
|
Uword status, trm_offset;
|
|
Uword terminator, trm_siz;
|
|
};
|
|
struct _wr_iosb { /* i/o status block for write */
|
|
Uword status, byte_cnt;
|
|
unsigned : 32;
|
|
};
|
|
struct _sm_iosb { /* i/o status block for sense-mode qio */
|
|
Uword status;
|
|
Ubyte xmt_speed, rcv_speed;
|
|
Ubyte cr_fill, lf_fill, parity;
|
|
unsigned : 8;
|
|
};
|
|
struct _sm_bufr { /* sense-mode characteristics buffer */
|
|
Ubyte class, type; /* class==DC$_TERM, type==(various) */
|
|
Uword buf_siz; /* aka page width */
|
|
#define page_width buf_siz /* number of columns */
|
|
unsigned tt_char : 24; /* primary characteristics */
|
|
unsigned page_length : 8; /* number of lines */
|
|
unsigned tt2_char : 32; /* secondary characteristics */
|
|
};
|
|
static struct {
|
|
struct _sm_iosb io;
|
|
struct _sm_bufr sm;
|
|
} sg = { { 0 }, { 0 } };
|
|
static unsigned short tt_chan = 0;
|
|
static unsigned long tt_char_restore = 0, tt_char_active = 0,
|
|
tt2_char_restore = 0, tt2_char_active = 0;
|
|
static unsigned long ctrl_mask = 0;
|
|
|
|
#ifdef DEBUG
|
|
extern int nh_vms_getchar(void);
|
|
|
|
/* rename the real vms_getchar and interpose this one in front of it */
|
|
int
|
|
vms_getchar(void)
|
|
{
|
|
static int althack = 0, altprefix;
|
|
char *nhalthack;
|
|
int res;
|
|
|
|
if (!althack) {
|
|
/* one-time init */
|
|
nhalthack = nh_getenv("NH_ALTHACK");
|
|
althack = nhalthack ? 1 : -1;
|
|
if (althack > 0)
|
|
altprefix = *nhalthack;
|
|
}
|
|
|
|
#define vms_getchar nh_vms_getchar
|
|
|
|
res = vms_getchar();
|
|
if (althack > 0 && res == altprefix) {
|
|
res = vms_getchar();
|
|
if (res != ESC)
|
|
res = META(res);
|
|
}
|
|
return res;
|
|
}
|
|
#endif /*DEBUG*/
|
|
|
|
int
|
|
vms_getchar(void)
|
|
{
|
|
short key;
|
|
#ifdef USE_QIO_INPUT
|
|
struct _rd_iosb iosb;
|
|
unsigned long sts;
|
|
unsigned char kb_buf;
|
|
#else /* SMG input */
|
|
static volatile int recurse = 0; /* SMG is not AST re-entrant! */
|
|
#endif
|
|
|
|
if (gp.program_state.done_hup) {
|
|
/* hangup has occurred; do not attempt to get further user input */
|
|
return ESC;
|
|
}
|
|
|
|
#ifdef USE_QIO_INPUT
|
|
if (inc > 0) {
|
|
/* we have buffered character(s) from previous read */
|
|
kb_buf = *inp++;
|
|
--inc;
|
|
sts = SS$_NORMAL;
|
|
} else {
|
|
sts = sys$qiow(0, tt_chan, QIO_FUNC, &iosb, (void (*) ()) 0, 0,
|
|
&kb_buf, sizeof kb_buf, 0, 0, 0, 0);
|
|
}
|
|
if (vms_ok(sts)) {
|
|
if (kb_buf == CTRL('C')) {
|
|
if (intr_char)
|
|
gsignal(SIGINT);
|
|
key = (short) kb_buf;
|
|
} else if (kb_buf == '\r') { /* <return> */
|
|
key = (short) '\n';
|
|
} else if (kb_buf == ESC || kb_buf == CSI || kb_buf == SS3) {
|
|
switch (parse_function_key((int) kb_buf)) {
|
|
case SMG$K_TRM_UP:
|
|
key = gc.Cmd.dirchars[2];
|
|
break;
|
|
case SMG$K_TRM_DOWN:
|
|
key = gc.Cmd.dirchars[6];
|
|
break;
|
|
case SMG$K_TRM_LEFT:
|
|
key = gc.Cmd.dirchars[0];
|
|
break;
|
|
case SMG$K_TRM_RIGHT:
|
|
key = gc.Cmd.dirchars[4];
|
|
break;
|
|
default:
|
|
key = ESC;
|
|
break;
|
|
}
|
|
} else {
|
|
key = (short) kb_buf;
|
|
}
|
|
} else if (sts == SS$_HANGUP || iosb.status == SS$_HANGUP
|
|
|| sts == SS$_DEVOFFLINE) {
|
|
gsignal(SIGHUP);
|
|
key = ESC;
|
|
} else /*(this should never happen)*/
|
|
key = getchar();
|
|
|
|
#else /*!USE_QIO_INPUT*/
|
|
if (recurse++ == 0 && kb != 0) {
|
|
smg$read_keystroke(&kb, &key);
|
|
switch (key) {
|
|
case SMG$K_TRM_UP:
|
|
key = gc.Cmd.move_N;
|
|
break;
|
|
case SMG$K_TRM_DOWN:
|
|
key = gc.Cmd.move_S;
|
|
break;
|
|
case SMG$K_TRM_LEFT:
|
|
key = gc.Cmd.move_W;
|
|
break;
|
|
case SMG$K_TRM_RIGHT:
|
|
key = gc.Cmd.move_E;
|
|
break;
|
|
case '\r':
|
|
key = '\n';
|
|
break;
|
|
default:
|
|
if (key > 255)
|
|
key = ESC;
|
|
break;
|
|
}
|
|
} else {
|
|
/* abnormal input--either SMG didn't initialize properly or
|
|
* vms_getchar() has been called recursively (via SIGINT handler).
|
|
*/
|
|
if (kb != 0) /* must have been a recursive call */
|
|
smg$cancel_input(&kb); /* from an interrupt handler */
|
|
key = getchar();
|
|
}
|
|
--recurse;
|
|
#endif /* USE_QIO_INPUT */
|
|
|
|
return (int) key;
|
|
}
|
|
|
|
#ifdef USE_QIO_INPUT
|
|
/*
|
|
* We've just gotten an <escape> character. Do a timed read to
|
|
* get any other characters, then try to parse them as an escape
|
|
* sequence. This isn't perfect, since there's no guarantee
|
|
* that a full escape sequence will be available, or even if one
|
|
* is, it might actually by regular input from a fast typist or
|
|
* a stalled input connection. {For packetized environments,
|
|
* cross plural(body_part(FINGER)) and hope for best. :-}
|
|
*
|
|
* This is needed to preserve compatibility with SMG interface
|
|
* for two reasons:
|
|
* 1) retain support for arrow keys, and
|
|
* 2) treat other VTxxx function keys as <esc> for aborting
|
|
* various NetHack prompts.
|
|
* The second reason is compelling; otherwise remaining chars of
|
|
* an escape sequence get treated as inappropriate user commands.
|
|
*
|
|
* SMG code values for these key sequences fall in the range of
|
|
* 256 thru 3xx. The assignments are not particularly intuitive.
|
|
*/
|
|
/*=
|
|
-- Summary of VTxxx-style keyboards and transmitted escape sequences. --
|
|
Keypad codes are prefixed by 7 bit (\033 O) or 8 bit SS3:
|
|
keypad: PF1 PF2 PF3 PF4 codes: P Q R S
|
|
7 8 9 - w x y m
|
|
4 5 6 . t u v n
|
|
1 2 3 :en-: q r s : :
|
|
...0... , :ter: ...p... l :M:
|
|
Arrows are prefixed by either SS3 or CSI (either 7 or 8 bit), depending on
|
|
whether the terminal is in application or numeric mode (ditto for PF keys):
|
|
arrows: <up> <dwn> <lft> <rgt> A B D C
|
|
Additional function keys (vk201/vk401) generate CSI nn ~ (nn is 1 or 2 digits):
|
|
vk201 keys: F6 F7 F8 F9 F10 F11 F12 F13 F14 Help Do F17 F18 F19 F20
|
|
'nn' digits: 17 18 19 20 21 23 24 25 26 28 29 31 32 33 34
|
|
alternate: ^C ^[ ^H ^J (when in VT100 mode)
|
|
edit keypad: <fnd> <ins> <rmv> digits: 1 2 3
|
|
<sel> <prv> <nxt> 4 5 6
|
|
VT52 mode: arrows and PF keys send ESCx where x is in A-D or P-S.
|
|
=*/
|
|
|
|
static const char *arrow_or_PF = "ABCDPQRS", /* suffix char */
|
|
*smg_keypad_codes = "PQRSpqrstuvwxyMmlnABDC";
|
|
/* PF1..PF4,KP0..KP9,enter,dash,comma,dot,up-arrow,down,left,right */
|
|
/* Ultimate return value is (index into smg_keypad_codes[] + 256). */
|
|
|
|
static short
|
|
parse_function_key(int c)
|
|
{
|
|
struct _rd_iosb iosb;
|
|
unsigned long sts;
|
|
char seq_buf[15 + 1]; /* plenty room for escape sequence + slop */
|
|
short result = ESC; /* translate to <escape> by default */
|
|
|
|
/*
|
|
* Read whatever we can from type-ahead buffer (1 second timeout).
|
|
* If the user typed an actual <escape> to deliberately abort
|
|
* something, he or she should be able to tolerate the necessary
|
|
* restriction of a negligible pause before typing anything else.
|
|
* We might already have [at least some of] an escape sequence from a
|
|
* previous read, particularly if user holds down the arrow keys...
|
|
*/
|
|
if (inc > 0)
|
|
strncpy(seq_buf, inp, inc);
|
|
if (inc < (int) (sizeof seq_buf) - 1) {
|
|
sts = sys$qiow(0, tt_chan, QIO_FUNC | IO$M_TIMED, &iosb,
|
|
(void (*) ()) 0, 0, seq_buf + inc,
|
|
sizeof seq_buf - 1 - inc, 1, 0, 0, 0);
|
|
if (vms_ok(sts))
|
|
sts = iosb.status;
|
|
} else
|
|
sts = SS$_NORMAL;
|
|
if (vms_ok(sts) || sts == SS$_TIMEOUT) {
|
|
int cnt = iosb.trm_offset + iosb.trm_siz + inc;
|
|
char *p = seq_buf;
|
|
|
|
if (c == ESC) /* check for 7-bit vt100/ANSI, or vt52 */
|
|
if (*p == '[' || *p == 'O')
|
|
c = META(CTRL(*p++)), cnt--;
|
|
else if (strchr(arrow_or_PF, *p))
|
|
c = SS3; /*CSI*/
|
|
if (cnt > 0 && (c == SS3 || (c == CSI && strchr(arrow_or_PF, *p)))) {
|
|
char *q = strchr(smg_keypad_codes, *p);
|
|
|
|
if (q)
|
|
result = 256 + (q - smg_keypad_codes);
|
|
p++, --cnt; /* one more char consumed */
|
|
} else if (cnt > 1 && c == CSI) {
|
|
static short /* "CSI nn ~" -> F_keys[nn] */
|
|
F_keys[35] = {
|
|
ESC, /*(filler)*/
|
|
311, 312, 313, 314, 315, 316, /* E1-E6 */
|
|
ESC, ESC, ESC, ESC, /*(more filler)*/
|
|
281, 282, 283, 284, 285, ESC, /* F1-F5 */
|
|
286, 287, 288, 289, 290, ESC, /* F6-F10*/
|
|
291, 292, 293, 294, ESC, /*F11-F14*/
|
|
295, 296, ESC, /*<help>,<do>, aka F15,F16*/
|
|
297, 298, 299, 300 /*F17-F20*/
|
|
}; /* note: there are several missing nn in CSI nn ~ values */
|
|
int nn;
|
|
char *q;
|
|
|
|
*(p + cnt) = '\0'; /* terminate string */
|
|
q = strchr(p, '~');
|
|
if (q && sscanf(p, "%d~", &nn) == 1) {
|
|
if (nn > 0 && nn < SIZE(F_keys))
|
|
result = F_keys[nn];
|
|
cnt -= (++q - p);
|
|
p = q;
|
|
}
|
|
}
|
|
if (cnt > 0)
|
|
strncpy((inp = inputbuf), p, (inc = cnt));
|
|
else
|
|
inc = 0, inp = 0;
|
|
}
|
|
return result;
|
|
}
|
|
#endif /* USE_QIO_INPUT */
|
|
|
|
static void
|
|
setctty(void)
|
|
{
|
|
struct _sm_iosb iosb;
|
|
unsigned long status;
|
|
|
|
status = sys$qiow(0, tt_chan, IO$_SETMODE, &iosb, (void (*) ()) 0, 0,
|
|
&sg.sm, sizeof sg.sm, 0, 0, 0, 0);
|
|
if (vms_ok(status))
|
|
status = iosb.status;
|
|
if (vms_ok(status)) {
|
|
/* try to force terminal into synch with TTDRIVER's setting */
|
|
number_pad((sg.sm.tt2_char & TT2$M_APP_KEYPAD) ? -1 : 1);
|
|
} else {
|
|
raw_print("");
|
|
errno = EVMSERR, vaxc$errno = status;
|
|
perror("NetHack(setctty: setmode)");
|
|
wait_synch();
|
|
}
|
|
}
|
|
|
|
/* atexit() routine */
|
|
static void
|
|
resettty(void)
|
|
{
|
|
if (settty_needed) {
|
|
bombing = TRUE; /* don't clear screen; preserve traceback info */
|
|
settty((char *) 0);
|
|
}
|
|
(void) sys$dassgn(tt_chan), tt_chan = 0;
|
|
}
|
|
|
|
/*
|
|
* Get initial state of terminal, set ospeed (for termcap routines)
|
|
* and switch off tab expansion if necessary.
|
|
* Called by init_nhwindows() and resume_nhwindows() in wintty.c
|
|
* (for initial startup and for returning from '!' or ^Z).
|
|
*/
|
|
void
|
|
gettty(void)
|
|
{
|
|
static char dev_tty[] = "TT:";
|
|
static $DESCRIPTOR(tty_dsc, dev_tty);
|
|
int err = 0;
|
|
unsigned long status, zero = 0;
|
|
|
|
if (tt_chan == 0) { /* do this stuff once only */
|
|
iflags.cbreak = OFF, iflags.echo = ON; /* until setup is complete */
|
|
status = sys$assign(&tty_dsc, &tt_chan, 0, 0);
|
|
if (!vms_ok(status)) {
|
|
raw_print(""), err++;
|
|
errno = EVMSERR, vaxc$errno = status;
|
|
perror("NetHack(gettty: $assign)");
|
|
}
|
|
atexit(resettty); /* register an exit handler to reset things */
|
|
}
|
|
status = sys$qiow(0, tt_chan, IO$_SENSEMODE, &sg.io, (void (*) ()) 0, 0,
|
|
&sg.sm, sizeof sg.sm, 0, 0, 0, 0);
|
|
if (vms_ok(status))
|
|
status = sg.io.status;
|
|
if (!vms_ok(status)) {
|
|
raw_print(""), err++;
|
|
errno = EVMSERR, vaxc$errno = status;
|
|
perror("NetHack(gettty: sensemode)");
|
|
}
|
|
ospeed = sg.io.xmt_speed;
|
|
erase_char = '\177'; /* <rubout>, aka <delete> */
|
|
kill_char = CTRL('U');
|
|
intr_char = CTRL('C');
|
|
(void) lib$enable_ctrl(&zero, &ctrl_mask);
|
|
/* Use the systems's values for lines and columns if it has any idea. */
|
|
if (sg.sm.page_length)
|
|
LI = sg.sm.page_length;
|
|
if (sg.sm.page_width)
|
|
CO = sg.sm.page_width;
|
|
/* suppress tab and form-feed expansion, in case termcap uses them */
|
|
tt_char_restore = sg.sm.tt_char;
|
|
tt_char_active = sg.sm.tt_char |= TT_SPECIAL_HANDLING;
|
|
tt2_char_restore = sg.sm.tt2_char;
|
|
tt2_char_active = sg.sm.tt2_char |= TT2_SPECIAL_HANDLING;
|
|
#if 0 /*[ defer until setftty() ]*/
|
|
setctty();
|
|
#endif
|
|
|
|
if (err)
|
|
wait_synch();
|
|
}
|
|
|
|
/* reset terminal to original state */
|
|
void
|
|
settty(const char *s)
|
|
{
|
|
if (!bombing)
|
|
end_screen();
|
|
if (s)
|
|
raw_print(s);
|
|
if (settty_needed) {
|
|
disable_broadcast_trapping();
|
|
#if 0 /* let SMG's exit handler do the cleanup (as per doc) */
|
|
/* #ifndef USE_QIO_INPUT */
|
|
if (kb)
|
|
smg$delete_virtual_keyboard(&kb), kb = 0;
|
|
#endif /* 0 (!USE_QIO_INPUT) */
|
|
if (ctrl_mask)
|
|
(void) lib$enable_ctrl(&ctrl_mask, 0);
|
|
iflags.echo = ON;
|
|
iflags.cbreak = OFF;
|
|
/* reset original tab, form-feed, broadcast settings */
|
|
sg.sm.tt_char = tt_char_restore;
|
|
sg.sm.tt2_char = tt2_char_restore;
|
|
setctty();
|
|
|
|
settty_needed = FALSE;
|
|
}
|
|
}
|
|
|
|
/* same as settty, with no clearing of the screen */
|
|
void
|
|
shuttty(const char *s)
|
|
{
|
|
bombing = TRUE;
|
|
settty(s);
|
|
bombing = FALSE;
|
|
}
|
|
|
|
void
|
|
setftty(void)
|
|
{
|
|
unsigned long mask = LIB$M_CLI_CTRLT | LIB$M_CLI_CTRLY;
|
|
|
|
(void) lib$disable_ctrl(&mask, 0);
|
|
if (kb == 0) { /* do this stuff once only */
|
|
#ifdef USE_QIO_INPUT
|
|
kb = tt_chan;
|
|
#else /*!USE_QIO_INPUT*/
|
|
smg$create_virtual_keyboard(&kb);
|
|
#endif /*USE_QIO_INPUT*/
|
|
init_broadcast_trapping();
|
|
}
|
|
enable_broadcast_trapping(); /* no-op if !defined(MAIL) */
|
|
iflags.cbreak = (kb != 0) ? ON : OFF;
|
|
iflags.echo = (kb != 0) ? OFF : ON;
|
|
/* disable tab & form-feed expansion; prepare for broadcast trapping */
|
|
sg.sm.tt_char = tt_char_active;
|
|
sg.sm.tt2_char = tt2_char_active;
|
|
setctty();
|
|
|
|
start_screen();
|
|
settty_needed = TRUE;
|
|
}
|
|
|
|
/* enable kbd interrupts if enabled when game started */
|
|
void
|
|
intron(void)
|
|
{
|
|
intr_char = CTRL('C');
|
|
}
|
|
|
|
/* disable kbd interrupts if required*/
|
|
void
|
|
introff(void)
|
|
{
|
|
intr_char = 0;
|
|
}
|
|
|
|
#ifdef TIMED_DELAY
|
|
|
|
#ifndef VMSVSI
|
|
extern unsigned long lib$emul(const long *, const long *, const long *,
|
|
long *);
|
|
extern unsigned long sys$schdwk(), sys$hiber();
|
|
#endif
|
|
|
|
#define VMS_UNITS_PER_SECOND 10000000L /* hundreds of nanoseconds, 1e-7 */
|
|
/* constant for conversion from milliseconds to VMS delta time (negative) */
|
|
static const long mseconds_to_delta = VMS_UNITS_PER_SECOND / 1000L * -1L;
|
|
|
|
/* sleep for specified number of milliseconds (note: the timer used
|
|
generally only has 10-millisecond resolution at the hardware level...) */
|
|
void
|
|
msleep(unsigned mseconds) /* milliseconds */
|
|
{
|
|
long pid = 0L, zero = 0L, msec, qtime[2];
|
|
|
|
msec = (long) mseconds;
|
|
if (msec > 0 &&
|
|
/* qtime{0:63} = msec{0:31} * mseconds_to_delta{0:31} + zero{0:31} */
|
|
vms_ok(lib$emul(&msec, &mseconds_to_delta, &zero, qtime))) {
|
|
/* schedule a wake-up call, then go to sleep */
|
|
if (vms_ok(sys$schdwk(&pid, (genericptr_t) 0, qtime, (long *) 0)))
|
|
(void) sys$hiber();
|
|
}
|
|
}
|
|
|
|
#endif /* TIMED_DELAY */
|
|
|
|
/* fatal error */
|
|
/*VARARGS1*/
|
|
void error
|
|
VA_DECL(const char *, s)
|
|
{
|
|
VA_START(s);
|
|
VA_INIT(s, const char *);
|
|
|
|
if (settty_needed)
|
|
settty((char *) 0);
|
|
Vprintf(s, VA_ARGS);
|
|
(void) putchar('\n');
|
|
VA_END();
|
|
#ifndef SAVE_ON_FATAL_ERROR
|
|
/* prevent vmsmain's exit handler byebye() from calling hangup() */
|
|
/* sethanguphandler((void (*)(int) )) SIG_DFL; */
|
|
sethanguphandler((SIG_RET_TYPE) SIG_DFL);
|
|
#endif
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
#ifdef SIGWINCH
|
|
/* called by resize_tty(wintty.c) after receiving a SIGWINCH signal;
|
|
terminal size has changed and we should update LI and CO (from termcap) */
|
|
void
|
|
getwindowsz(void)
|
|
{
|
|
/*
|
|
* gettty() has code to do this, but it can't be used directly because
|
|
* it fetches terminal state in order to reset that upon termination.
|
|
* We need to avoid clobbering other saved state with values used by
|
|
* game-in-progress. For now, do nothing.
|
|
*/
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#ifdef ENHANCED_SYMBOLS
|
|
/*
|
|
* set in tty_start_screen() and allows
|
|
* OS-specific changes that may be
|
|
* required for support of utf8.
|
|
* Currently a placeholder for VMS.
|
|
*/
|
|
void
|
|
tty_utf8graphics_fixup(void)
|
|
{
|
|
return;
|
|
}
|
|
#endif /* ENHANCED_SYMBOLS */
|
|
|
|
/*vmstty.c */
|