mirror of
https://git.zap.org.au/git/trader.git
synced 2024-09-01 17:14:15 -04:00
Add gettxline() to read a line of input from the keyboard
This commit is contained in:
parent
85e09ab4f2
commit
dd281f795b
663
src/intf.c
663
src/intf.c
@ -37,7 +37,7 @@
|
|||||||
* Module constants and type declarations *
|
* Module constants and type declarations *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
#define OUTBUFSIZE (1024) /* Output string buffer size */
|
#define BUFSIZE (1024) /* Size of various string buffers */
|
||||||
|
|
||||||
|
|
||||||
typedef struct txwin {
|
typedef struct txwin {
|
||||||
@ -314,13 +314,13 @@ int center (WINDOW *win, int y, const bool clrline, const char *format, ...)
|
|||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
|
|
||||||
buf = malloc(OUTBUFSIZE);
|
buf = malloc(BUFSIZE);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
err_exit("out of memory");
|
err_exit("out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
len = vsnprintf(buf, OUTBUFSIZE, format, args);
|
len = vsnprintf(buf, BUFSIZE, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
return ERR;
|
return ERR;
|
||||||
@ -448,3 +448,660 @@ bool getanswer (WINDOW *win)
|
|||||||
wrefresh(win);
|
wrefresh(win);
|
||||||
return (key == 'Y');
|
return (key == 'Y');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
Function: gettxline - Read a line from the keyboard (generic)
|
||||||
|
Arguments: win - Window to use
|
||||||
|
buf - Pointer to preallocated buffer
|
||||||
|
bufsize - Size of buffer
|
||||||
|
multifield - Allow <TAB>, etc, to move between fields
|
||||||
|
maxlen - Maximum length of string
|
||||||
|
emptyval - String used if an empty string is input
|
||||||
|
defaultval - Default string, used if KEY_DEFAULTVAL is
|
||||||
|
pressed as the first character
|
||||||
|
allowed - Characters allowed in the string
|
||||||
|
stripspc - Strip leading and trailing spaces from string
|
||||||
|
y, x - Start of field (line, col)
|
||||||
|
fieldsize - Size of field in characters
|
||||||
|
attr - Curses attribute to use for the field
|
||||||
|
Returns: int - Status code: OK, ERR or key code
|
||||||
|
|
||||||
|
This low-level function draws an input field fieldsize characters long
|
||||||
|
using attr as the window attribute, then reads a line of input from the
|
||||||
|
keyboard (of no more than maxlen characters) and places it into the
|
||||||
|
preallocated buffer buf[]. On entry, buf[] must contain the current
|
||||||
|
input string: this allows for resumed editing of an input line. On
|
||||||
|
exit, buf[] will contain the input string; this string is printed using
|
||||||
|
the original window attributes with A_BOLD added. Many EMACS/Bash-
|
||||||
|
style keyboard editing shortcuts are allowed.
|
||||||
|
|
||||||
|
If ENTER (or equivalent) is pressed, OK is returned. In this case,
|
||||||
|
leading and trailing spaces are stripped if stripspc is true; if an
|
||||||
|
empty string is entered, the string pointed to by emptyval (if not
|
||||||
|
NULL) is stored in buf[].
|
||||||
|
|
||||||
|
If CANCEL, ESC or ^G is pressed, ERR is returned. In this case, buf[]
|
||||||
|
contains the string as edited by the user: emptyval is NOT used, nor
|
||||||
|
are leading and trailing spaces stripped.
|
||||||
|
|
||||||
|
If multifield is true, the UP and DOWN arrow keys, as well as TAB,
|
||||||
|
Shift-TAB, ^P (Previous) and ^N (Next) return KEY_UP or KEY_DOWN as
|
||||||
|
appropriate. As with CANCEL etc., emptyval is NOT used, nor are
|
||||||
|
leading and trailing spaces stripped.
|
||||||
|
|
||||||
|
If KEY_DEFAULTVAL is pressed when the input line is empty, the string
|
||||||
|
pointed to by defaultval (if not NULL) is placed in the buffer as if
|
||||||
|
typed by the user. Editing is NOT terminated in this case.
|
||||||
|
|
||||||
|
If allowed points to a string (ie, is not NULL), only characters in
|
||||||
|
that string are allowed to be entered into the input line. For
|
||||||
|
example, if allowed points to "0123456789abcdefABCDEF", only those
|
||||||
|
characters would be allowed (allowing a hexadecimal number to be
|
||||||
|
entered).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int gettxline (WINDOW *win, char *buf, int bufsize, bool multifield,
|
||||||
|
int maxlen, const char *emptyval, const char *defaultval,
|
||||||
|
const char *allowed, bool stripspc, int y, int x,
|
||||||
|
int fieldsize, int attr)
|
||||||
|
{
|
||||||
|
int i, len, pos, cpos, nb;
|
||||||
|
int oldattr;
|
||||||
|
bool done, redraw, first;
|
||||||
|
char c;
|
||||||
|
int key, key2, ret;
|
||||||
|
|
||||||
|
|
||||||
|
assert(buf != NULL);
|
||||||
|
assert(bufsize > 1);
|
||||||
|
assert(maxlen > 0);
|
||||||
|
assert(maxlen < bufsize);
|
||||||
|
assert(fieldsize > 1);
|
||||||
|
|
||||||
|
|
||||||
|
keypad(win, true);
|
||||||
|
meta(win, true);
|
||||||
|
wtimeout(win, -1);
|
||||||
|
|
||||||
|
oldattr = getbkgd(win) & ~A_CHARTEXT;
|
||||||
|
wattrset(win, attr & ~A_CHARTEXT);
|
||||||
|
curs_set(CURS_ON);
|
||||||
|
|
||||||
|
len = strlen(buf);
|
||||||
|
pos = len; // pos can be from 0 to strlen(buf)
|
||||||
|
cpos = MIN(len, fieldsize - 1);
|
||||||
|
redraw = true;
|
||||||
|
done = false;
|
||||||
|
|
||||||
|
while (! done) {
|
||||||
|
if (redraw) {
|
||||||
|
/*
|
||||||
|
Redisplay the visible part of the current input string.
|
||||||
|
Blanks at the end of the input area are replaced with
|
||||||
|
"attr", which may contain a '_' for non-colour mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mvwprintw(win, y, x, "%-*.*s", fieldsize, fieldsize,
|
||||||
|
buf + pos - cpos);
|
||||||
|
|
||||||
|
nb = (len - (pos - cpos) > fieldsize) ?
|
||||||
|
0 : fieldsize - (len - (pos - cpos));
|
||||||
|
wmove(win, y, x + fieldsize - nb);
|
||||||
|
for (i = 0; i < nb; i++) {
|
||||||
|
waddch(win, ((attr & A_CHARTEXT) == 0) ? attr | ' ' : attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
wmove(win, y, x + cpos);
|
||||||
|
wrefresh(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = wgetch(win);
|
||||||
|
if (key == ERR) {
|
||||||
|
// Do nothing on ERR
|
||||||
|
;
|
||||||
|
} else if ((key == KEY_DEFAULTVAL) && (defaultval != NULL)
|
||||||
|
&& (len == 0)) {
|
||||||
|
// Initialise buffer with the default value
|
||||||
|
|
||||||
|
strncpy(buf, defaultval, bufsize - 1);
|
||||||
|
buf[bufsize - 1] = '\0';
|
||||||
|
len = strlen(buf);
|
||||||
|
pos = len;
|
||||||
|
cpos = MIN(len, fieldsize - 1);
|
||||||
|
redraw = true;
|
||||||
|
} else if ((key < 0400) && (! iscntrl(key))) {
|
||||||
|
if ((len >= maxlen) ||
|
||||||
|
((allowed != NULL) && (strchr(allowed, key) == NULL))) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
// Process ordinary key press: insert it into the string
|
||||||
|
|
||||||
|
memmove(buf + pos + 1, buf + pos, len - pos + 1);
|
||||||
|
buf[pos] = (char) key;
|
||||||
|
len++;
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (key) {
|
||||||
|
|
||||||
|
// Terminating keys
|
||||||
|
|
||||||
|
case KEY_RETURN:
|
||||||
|
case KEY_ENTER:
|
||||||
|
case KEY_CTRL('M'):
|
||||||
|
// Finish entering the string
|
||||||
|
|
||||||
|
if (stripspc) {
|
||||||
|
// Strip leading spaces
|
||||||
|
i = 0;
|
||||||
|
while ((i < len) && isspace(buf[i])) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
memmove(buf, buf + i, len - i + 1);
|
||||||
|
len -= i;
|
||||||
|
|
||||||
|
// Strip trailing spaces
|
||||||
|
i = len;
|
||||||
|
while ((i > 0) && isspace(buf[i - 1])) {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
buf[i] = '\0';
|
||||||
|
len = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((emptyval != NULL) && (len == 0)) {
|
||||||
|
strncpy(buf, emptyval, bufsize - 1);
|
||||||
|
buf[bufsize - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = OK;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_CANCEL:
|
||||||
|
case KEY_CTRL('G'):
|
||||||
|
// case KEY_CTRL('C'):
|
||||||
|
// case KEY_CTRL('\\'):
|
||||||
|
// Cancel entering the string
|
||||||
|
ret = ERR;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_UP:
|
||||||
|
case KEY_BTAB:
|
||||||
|
case KEY_CTRL('P'):
|
||||||
|
// Finish entering the string, if multifield is true
|
||||||
|
if (multifield) {
|
||||||
|
ret = KEY_UP;
|
||||||
|
done = true;
|
||||||
|
} else {
|
||||||
|
beep();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_DOWN:
|
||||||
|
case KEY_TAB:
|
||||||
|
case KEY_CTRL('N'):
|
||||||
|
// Finish entering the string, if multifield is true
|
||||||
|
if (multifield) {
|
||||||
|
ret = KEY_DOWN;
|
||||||
|
done = true;
|
||||||
|
} else {
|
||||||
|
beep();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Cursor movement keys
|
||||||
|
|
||||||
|
case KEY_LEFT:
|
||||||
|
case KEY_CTRL('B'):
|
||||||
|
// Move cursor back one character
|
||||||
|
if (pos == 0) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
pos--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_RIGHT:
|
||||||
|
case KEY_CTRL('F'):
|
||||||
|
// Move cursor forward one character
|
||||||
|
if (pos == len) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_HOME:
|
||||||
|
case KEY_CTRL('A'):
|
||||||
|
// Move cursor to start of string
|
||||||
|
pos = 0;
|
||||||
|
cpos = 0;
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_END:
|
||||||
|
case KEY_CTRL('E'):
|
||||||
|
// Move cursor to end of string
|
||||||
|
pos = len;
|
||||||
|
cpos = MIN(pos, fieldsize - 1);
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_CLEFT:
|
||||||
|
// Move cursor to start of current or previous word
|
||||||
|
while ((pos > 0) && (! isalnum(buf[pos - 1]))) {
|
||||||
|
pos--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos > 0) && isalnum(buf[pos - 1])) {
|
||||||
|
pos--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_CRIGHT:
|
||||||
|
// Move cursor to end of current or next word
|
||||||
|
while ((pos < len) && (! isalnum(buf[pos]))) {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos < len) && isalnum(buf[pos])) {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Deletion keys
|
||||||
|
|
||||||
|
case KEY_BS:
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
case KEY_DEL:
|
||||||
|
// Delete previous character
|
||||||
|
if (pos == 0) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
memmove(buf + pos - 1, buf + pos, len - pos + 1);
|
||||||
|
len--;
|
||||||
|
pos--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_DC:
|
||||||
|
case KEY_CTRL('D'):
|
||||||
|
// Delete character under cursor
|
||||||
|
if (pos == len) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
memmove(buf + pos, buf + pos + 1, len - pos);
|
||||||
|
len--;
|
||||||
|
// pos and cpos stay the same
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_CLEAR:
|
||||||
|
// Delete the entire line
|
||||||
|
strcpy(buf, "");
|
||||||
|
len = 0;
|
||||||
|
pos = 0;
|
||||||
|
cpos = 0;
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_CTRL('U'):
|
||||||
|
// Delete backwards to the start of the line
|
||||||
|
if (pos == 0) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
memmove(buf, buf + pos, len - pos + 1);
|
||||||
|
len -= pos;
|
||||||
|
pos = 0;
|
||||||
|
cpos = 0;
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_CTRL('K'):
|
||||||
|
// Delete to the end of the line
|
||||||
|
if (pos == len) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
buf[pos] = '\0';
|
||||||
|
len = pos;
|
||||||
|
// pos and cpos stay the same
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_CTRL('W'):
|
||||||
|
// Delete the previous word
|
||||||
|
if (pos == 0) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
Note the use of isspace() instead of isalnum():
|
||||||
|
this makes ^W follow GNU Bash standards, which
|
||||||
|
behaves differently from Meta-DEL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
i = pos;
|
||||||
|
while ((i > 0) && isspace(buf[i - 1])) {
|
||||||
|
i--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((i > 0) && (! isspace(buf[i - 1]))) {
|
||||||
|
i--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(buf + i, buf + pos, len - pos + 1);
|
||||||
|
len -= (pos - i);
|
||||||
|
pos = i;
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Miscellaneous keys and events
|
||||||
|
|
||||||
|
case KEY_CTRL('T'):
|
||||||
|
// Transpose characters
|
||||||
|
if ((pos == 0) || (len <= 1)) {
|
||||||
|
beep();
|
||||||
|
} else if (pos == len) {
|
||||||
|
c = buf[pos - 1];
|
||||||
|
buf[pos - 1] = buf[pos - 2];
|
||||||
|
buf[pos - 2] = c;
|
||||||
|
redraw = true;
|
||||||
|
} else {
|
||||||
|
c = buf[pos];
|
||||||
|
buf[pos] = buf[pos - 1];
|
||||||
|
buf[pos - 1] = c;
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_ESC:
|
||||||
|
// Handle Meta-X-style and other function key presses
|
||||||
|
wtimeout(win, META_TIMEOUT);
|
||||||
|
key2 = wgetch(win);
|
||||||
|
|
||||||
|
if (key2 == ERR) {
|
||||||
|
// <ESC> by itself: cancel entering the string
|
||||||
|
ret = ERR;
|
||||||
|
done = true;
|
||||||
|
} else if ((key2 == 'O') || (key2 == '[')) {
|
||||||
|
// Swallow any unknown VT100-style function keys
|
||||||
|
key2 = wgetch(win);
|
||||||
|
while ((key2 != ERR) && isascii(key2) &&
|
||||||
|
(strchr("0123456789;", key2) != NULL) &&
|
||||||
|
(strchr("~ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz", key2) == NULL)) {
|
||||||
|
key2 = wgetch(win);
|
||||||
|
}
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
// Handle Meta-X-style keypress
|
||||||
|
switch (key2) {
|
||||||
|
|
||||||
|
// Cursor movement keys
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
case 'b':
|
||||||
|
// Move cursor to start of current or previous word
|
||||||
|
while ((pos > 0) && (! isalnum(buf[pos - 1]))) {
|
||||||
|
pos--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos > 0) && isalnum(buf[pos - 1])) {
|
||||||
|
pos--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
case 'f':
|
||||||
|
// Move cursor to end of current or next word
|
||||||
|
while ((pos < len) && (! isalnum(buf[pos]))) {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos < len) && isalnum(buf[pos])) {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Deletion keys
|
||||||
|
|
||||||
|
case KEY_BS:
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
case KEY_DEL:
|
||||||
|
// Delete the previous word (different from ^W)
|
||||||
|
i = pos;
|
||||||
|
while ((i > 0) && (! isalnum(buf[i - 1]))) {
|
||||||
|
i--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((i > 0) && isalnum(buf[i - 1])) {
|
||||||
|
i--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(buf + i, buf + pos, len - pos + 1);
|
||||||
|
len -= (pos - i);
|
||||||
|
pos = i;
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
case 'd':
|
||||||
|
// Delete the next word
|
||||||
|
i = pos;
|
||||||
|
while ((i < len) && (! isalnum(buf[i]))) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while ((i < len) && isalnum(buf[i])) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(buf + pos, buf + i, len - i + 1);
|
||||||
|
len -= (i - pos);
|
||||||
|
// pos and cpos stay the same
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
case ' ':
|
||||||
|
// Delete all surrounding spaces; if key2 == ' ',
|
||||||
|
// also insert one space
|
||||||
|
i = pos;
|
||||||
|
while ((pos > 0) && isspace(buf[pos - 1])) {
|
||||||
|
pos--;
|
||||||
|
if (cpos > 0) {
|
||||||
|
cpos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((i < len) && isspace(buf[i])) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(buf + pos, buf + i, len - i + 1);
|
||||||
|
len -= (i - pos);
|
||||||
|
|
||||||
|
if (key2 == ' ') {
|
||||||
|
if ((len >= maxlen) || ((allowed != NULL) &&
|
||||||
|
(strchr(allowed, key) == NULL))) {
|
||||||
|
beep();
|
||||||
|
} else {
|
||||||
|
memmove(buf + pos + 1, buf + pos, len - pos + 1);
|
||||||
|
buf[pos] = ' ';
|
||||||
|
len++;
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Transformation keys
|
||||||
|
|
||||||
|
case 'U':
|
||||||
|
case 'u':
|
||||||
|
// Convert word (from cursor onwards) to upper case
|
||||||
|
while ((pos < len) && (! isalnum(buf[pos]))) {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos < len) && isalnum(buf[pos])) {
|
||||||
|
buf[pos] = toupper(buf[pos]);
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'L':
|
||||||
|
case 'l':
|
||||||
|
// Convert word (from cursor onwards) to lower case
|
||||||
|
while ((pos < len) && (! isalnum(buf[pos]))) {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos < len) && isalnum(buf[pos])) {
|
||||||
|
buf[pos] = tolower(buf[pos]);
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
case 'c':
|
||||||
|
// Convert current letter to upper case, following
|
||||||
|
// letters to lower case
|
||||||
|
first = true;
|
||||||
|
while ((pos < len) && (! isalnum(buf[pos]))) {
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos < len) && isalnum(buf[pos])) {
|
||||||
|
if (first) {
|
||||||
|
buf[pos] = toupper(buf[pos]);
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
buf[pos] = tolower(buf[pos]);
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
if (cpos < fieldsize - 1) {
|
||||||
|
cpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Miscellaneous keys and events
|
||||||
|
|
||||||
|
case KEY_RESIZE:
|
||||||
|
case KEY_EVENT:
|
||||||
|
ret = key;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
beep();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wtimeout(win, -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_RESIZE:
|
||||||
|
case KEY_EVENT:
|
||||||
|
ret = key;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
beep();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wattrset(win, oldattr);
|
||||||
|
curs_set(CURS_OFF);
|
||||||
|
|
||||||
|
wattron(win, A_BOLD);
|
||||||
|
mvwprintw(win, y, x, "%-*.*s", fieldsize, fieldsize, buf);
|
||||||
|
wattrset(win, oldattr);
|
||||||
|
wrefresh(win);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
34
src/intf.h
34
src/intf.h
@ -51,9 +51,33 @@ typedef enum curs_type {
|
|||||||
|
|
||||||
|
|
||||||
// Keycodes
|
// Keycodes
|
||||||
#define KEY_TAB (011)
|
#define KEY_BS (0010)
|
||||||
#define KEY_RETURN (012)
|
#define KEY_TAB (0011)
|
||||||
#define KEY_ESC (033)
|
#define KEY_RETURN (0012)
|
||||||
|
#define KEY_ESC (0033)
|
||||||
|
#define KEY_DEL (0177)
|
||||||
|
|
||||||
|
#define KEY_CTRL(x) (x - 0100)
|
||||||
|
|
||||||
|
// Control-arrow key combinations
|
||||||
|
#ifndef KEY_CDOWN
|
||||||
|
# define KEY_CDOWN (01007)
|
||||||
|
#endif
|
||||||
|
#ifndef KEY_CUP
|
||||||
|
# define KEY_CUP (01060)
|
||||||
|
#endif
|
||||||
|
#ifndef KEY_CLEFT
|
||||||
|
# define KEY_CLEFT (01033)
|
||||||
|
#endif
|
||||||
|
#ifndef KEY_CRIGHT
|
||||||
|
# define KEY_CRIGHT (01052)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Keycode for inserting the default value
|
||||||
|
#define KEY_DEFAULTVAL '='
|
||||||
|
|
||||||
|
// Timeout value (in ms) for Meta-X-style keyboard input
|
||||||
|
#define META_TIMEOUT (1000)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -124,6 +148,10 @@ extern int attrpr (WINDOW *win, int attr, const char *format, ...)
|
|||||||
|
|
||||||
extern int gettxchar (WINDOW *win);
|
extern int gettxchar (WINDOW *win);
|
||||||
extern bool getanswer (WINDOW *win);
|
extern bool getanswer (WINDOW *win);
|
||||||
|
extern int gettxline (WINDOW *win, char *buf, int bufsize, bool multifield,
|
||||||
|
int maxlen, const char *emptyval, const char *defaultval,
|
||||||
|
const char *allowed, bool stripspc, int y, int x,
|
||||||
|
int fieldsize, int attr);
|
||||||
|
|
||||||
|
|
||||||
#endif /* included_INTF_H */
|
#endif /* included_INTF_H */
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
|
|
||||||
#define _GNU_SOURCE 1
|
#define _GNU_SOURCE 1
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
10
src/utils.h
10
src/utils.h
@ -40,6 +40,16 @@
|
|||||||
#define GAME_FILENAME_BUFSIZE (16)
|
#define GAME_FILENAME_BUFSIZE (16)
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Utility macro definitions *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
// Type-unsafe minimum and maximum macros
|
||||||
|
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Utility function declarations *
|
* Utility function declarations *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user