win/tty/getline.c(305) : warning C4701: potentially uninitialized local variable 'ecmatches' used win/tty/getline.c(305) : error C4703: potentially uninitialized local pointer variable 'ecmatches' used
311 lines
9.1 KiB
C
311 lines
9.1 KiB
C
/* NetHack 3.7 getline.c $NHDT-Date: 1596498343 2020/08/03 23:45:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.44 $ */
|
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
|
/*-Copyright (c) Michael Allison, 2006. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include "hack.h"
|
|
|
|
#ifdef TTY_GRAPHICS
|
|
|
|
#if !defined(MAC)
|
|
#define NEWAUTOCOMP
|
|
#endif
|
|
|
|
#include "wintty.h"
|
|
#include "func_tab.h"
|
|
|
|
char morc = 0; /* tell the outside world what char you chose */
|
|
static boolean suppress_history;
|
|
static boolean ext_cmd_getlin_hook(char *);
|
|
|
|
typedef boolean (*getlin_hook_proc)(char *);
|
|
|
|
static void hooked_tty_getlin(const char *, char *, getlin_hook_proc);
|
|
extern int extcmd_via_menu(void); /* cmd.c */
|
|
|
|
extern char erase_char, kill_char; /* from appropriate tty.c file */
|
|
|
|
/*
|
|
* Read a line closed with '\n' into the array char bufp[BUFSZ].
|
|
* (The '\n' is not stored. The string is closed with a '\0'.)
|
|
* Reading can be interrupted by an escape ('\033') - now the
|
|
* resulting string is "\033".
|
|
*/
|
|
void
|
|
tty_getlin(const char *query, register char *bufp)
|
|
{
|
|
suppress_history = FALSE;
|
|
hooked_tty_getlin(query, bufp, (getlin_hook_proc) 0);
|
|
}
|
|
|
|
static void
|
|
hooked_tty_getlin(const char *query, register char *bufp, getlin_hook_proc hook)
|
|
{
|
|
register char *obufp = bufp;
|
|
register int c;
|
|
struct WinDesc *cw = wins[WIN_MESSAGE];
|
|
boolean doprev = 0;
|
|
|
|
if (ttyDisplay->toplin == TOPLINE_NEED_MORE && !(cw->flags & WIN_STOP))
|
|
more();
|
|
cw->flags &= ~WIN_STOP;
|
|
ttyDisplay->toplin = TOPLINE_SPECIAL_PROMPT;
|
|
ttyDisplay->inread++;
|
|
|
|
/* issue the prompt */
|
|
custompline(OVERRIDE_MSGTYPE | SUPPRESS_HISTORY, "%s ", query);
|
|
#ifdef EDIT_GETLIN
|
|
/* bufp is input/output; treat current contents (presumed to be from
|
|
previous getlin()) as default input */
|
|
addtopl(obufp);
|
|
bufp = eos(obufp);
|
|
#else
|
|
/* !EDIT_GETLIN: bufp is output only; init it to empty */
|
|
*bufp = '\0';
|
|
#endif
|
|
|
|
for (;;) {
|
|
(void) fflush(stdout);
|
|
Strcat(strcat(strcpy(g.toplines, query), " "), obufp);
|
|
c = pgetchar();
|
|
if (c == '\033' || c == EOF) {
|
|
if (c == '\033' && obufp[0] != '\0') {
|
|
obufp[0] = '\0';
|
|
bufp = obufp;
|
|
tty_clear_nhwindow(WIN_MESSAGE);
|
|
cw->maxcol = cw->maxrow;
|
|
addtopl(query);
|
|
addtopl(" ");
|
|
addtopl(obufp);
|
|
} else {
|
|
obufp[0] = '\033';
|
|
obufp[1] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
if (ttyDisplay->intr) {
|
|
ttyDisplay->intr--;
|
|
*bufp = 0;
|
|
}
|
|
if (c == '\020') { /* ctrl-P */
|
|
if (iflags.prevmsg_window != 's') {
|
|
int sav = ttyDisplay->inread;
|
|
|
|
ttyDisplay->inread = 0;
|
|
(void) tty_doprev_message();
|
|
ttyDisplay->inread = sav;
|
|
tty_clear_nhwindow(WIN_MESSAGE);
|
|
cw->maxcol = cw->maxrow;
|
|
addtopl(query);
|
|
addtopl(" ");
|
|
*bufp = 0;
|
|
addtopl(obufp);
|
|
} else {
|
|
if (!doprev)
|
|
(void) tty_doprev_message(); /* need two initially */
|
|
(void) tty_doprev_message();
|
|
doprev = 1;
|
|
continue;
|
|
}
|
|
} else if (doprev && iflags.prevmsg_window == 's') {
|
|
tty_clear_nhwindow(WIN_MESSAGE);
|
|
cw->maxcol = cw->maxrow;
|
|
doprev = 0;
|
|
addtopl(query);
|
|
addtopl(" ");
|
|
*bufp = 0;
|
|
addtopl(obufp);
|
|
}
|
|
if (c == erase_char || c == '\b') {
|
|
if (bufp != obufp) {
|
|
#ifdef NEWAUTOCOMP
|
|
char *i;
|
|
|
|
#endif /* NEWAUTOCOMP */
|
|
bufp--;
|
|
#ifndef NEWAUTOCOMP
|
|
putsyms("\b \b"); /* putsym converts \b */
|
|
#else /* NEWAUTOCOMP */
|
|
putsyms("\b");
|
|
for (i = bufp; *i; ++i)
|
|
putsyms(" ");
|
|
for (; i > bufp; --i)
|
|
putsyms("\b");
|
|
*bufp = 0;
|
|
#endif /* NEWAUTOCOMP */
|
|
} else
|
|
tty_nhbell();
|
|
} else if (c == '\n' || c == '\r') {
|
|
#ifndef NEWAUTOCOMP
|
|
*bufp = 0;
|
|
#endif /* not NEWAUTOCOMP */
|
|
break;
|
|
} else if (' ' <= (unsigned char) c && c != '\177'
|
|
/* avoid isprint() - some people don't have it
|
|
' ' is not always a printing char */
|
|
&& (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)) {
|
|
#ifdef NEWAUTOCOMP
|
|
char *i = eos(bufp);
|
|
|
|
#endif /* NEWAUTOCOMP */
|
|
*bufp = c;
|
|
bufp[1] = 0;
|
|
putsyms(bufp);
|
|
bufp++;
|
|
if (hook && (*hook)(obufp)) {
|
|
putsyms(bufp);
|
|
#ifndef NEWAUTOCOMP
|
|
bufp = eos(bufp);
|
|
#else /* NEWAUTOCOMP */
|
|
/* pointer and cursor left where they were */
|
|
for (i = bufp; *i; ++i)
|
|
putsyms("\b");
|
|
} else if (i > bufp) {
|
|
char *s = i;
|
|
|
|
/* erase rest of prior guess */
|
|
for (; i > bufp; --i)
|
|
putsyms(" ");
|
|
for (; s > bufp; --s)
|
|
putsyms("\b");
|
|
#endif /* NEWAUTOCOMP */
|
|
}
|
|
} else if (c == kill_char || c == '\177') { /* Robert Viduya */
|
|
/* this test last - @ might be the kill_char */
|
|
#ifndef NEWAUTOCOMP
|
|
while (bufp != obufp) {
|
|
bufp--;
|
|
putsyms("\b \b");
|
|
}
|
|
#else /* NEWAUTOCOMP */
|
|
for (; *bufp; ++bufp)
|
|
putsyms(" ");
|
|
for (; bufp != obufp; --bufp)
|
|
putsyms("\b \b");
|
|
*bufp = 0;
|
|
#endif /* NEWAUTOCOMP */
|
|
} else
|
|
tty_nhbell();
|
|
}
|
|
ttyDisplay->toplin = TOPLINE_NON_EMPTY;
|
|
ttyDisplay->inread--;
|
|
clear_nhwindow(WIN_MESSAGE); /* clean up after ourselves */
|
|
|
|
if (suppress_history) {
|
|
/* prevent next message from pushing current query+answer into
|
|
tty message history */
|
|
*g.toplines = '\0';
|
|
#ifdef DUMPLOG
|
|
} else {
|
|
/* needed because we've bypassed pline() */
|
|
dumplogmsg(g.toplines);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void
|
|
xwaitforspace(register const char *s) /* chars allowed besides return */
|
|
{
|
|
register int c, x = ttyDisplay ? (int) ttyDisplay->dismiss_more : '\n';
|
|
|
|
morc = 0;
|
|
while (
|
|
#ifdef HANGUPHANDLING
|
|
!g.program_state.done_hup &&
|
|
#endif
|
|
(c = tty_nhgetch()) != EOF) {
|
|
if (c == '\n' || c == '\r')
|
|
break;
|
|
|
|
if (iflags.cbreak) {
|
|
if (c == '\033') {
|
|
if (ttyDisplay)
|
|
ttyDisplay->dismiss_more = 1;
|
|
morc = '\033';
|
|
break;
|
|
}
|
|
if ((s && index(s, c)) || c == x || (x == '\n' && c == '\r')) {
|
|
morc = (char) c;
|
|
break;
|
|
}
|
|
tty_nhbell();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Implement extended command completion by using this hook into
|
|
* tty_getlin. Check the characters already typed, if they uniquely
|
|
* identify an extended command, expand the string to the whole
|
|
* command.
|
|
*
|
|
* Return TRUE if we've extended the string at base. Otherwise return FALSE.
|
|
* Assumptions:
|
|
*
|
|
* + we don't change the characters that are already in base
|
|
* + base has enough room to hold our string
|
|
*/
|
|
static boolean
|
|
ext_cmd_getlin_hook(char *base)
|
|
{
|
|
int *ecmatches;
|
|
int nmatches = extcmds_match(base, ECM_NOFLAGS, &ecmatches);
|
|
|
|
if (nmatches == 1) {
|
|
struct ext_func_tab *ec = extcmds_getentry(ecmatches[0]);
|
|
|
|
Strcpy(base, ec->ef_txt);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE; /* didn't match anything */
|
|
}
|
|
|
|
/*
|
|
* Read in an extended command, doing command line completion. We
|
|
* stop when we have found enough characters to make a unique command.
|
|
*/
|
|
int
|
|
tty_get_ext_cmd(void)
|
|
{
|
|
char buf[BUFSZ];
|
|
int nmatches;
|
|
int *ecmatches = 0;
|
|
boolean (*no_hook)(char *base) = (boolean (*)(char *)) 0;
|
|
char extcmd_char[2];
|
|
|
|
if (iflags.extmenu)
|
|
return extcmd_via_menu();
|
|
|
|
suppress_history = TRUE;
|
|
/* maybe a runtime option?
|
|
* hooked_tty_getlin("#", buf,
|
|
* (flags.cmd_comp && !g.in_doagain)
|
|
* ? ext_cmd_getlin_hook
|
|
* : (getlin_hook_proc) 0);
|
|
*/
|
|
extcmd_char[0] = extcmd_initiator(), extcmd_char[1] = '\0';
|
|
buf[0] = '\0';
|
|
hooked_tty_getlin(extcmd_char, buf,
|
|
!g.in_doagain ? ext_cmd_getlin_hook : no_hook);
|
|
(void) mungspaces(buf);
|
|
|
|
nmatches = (buf[0] == '\0' || buf[0] == '\033') ? -1
|
|
: extcmds_match(buf, ECM_IGNOREAC | ECM_EXACTMATCH, &ecmatches);
|
|
if (nmatches != 1) {
|
|
if (nmatches != -1)
|
|
pline("%s%.60s: unknown extended command.",
|
|
visctrl(extcmd_char[0]), buf);
|
|
savech(0); /* reset do-again buffer */
|
|
savech(extcmd_char[0]);
|
|
return -1;
|
|
}
|
|
|
|
savech_extcmd(buf, TRUE); /* savech() for extcmd_char+buf[...]+'\n' */
|
|
return ecmatches[0];
|
|
}
|
|
|
|
#endif /* TTY_GRAPHICS */
|
|
|
|
/*getline.c*/
|