File: [local] / src / usr.bin / mg / kbd.c (download)
Revision 1.29, Wed Mar 25 20:53:31 2015 UTC (9 years, 2 months ago) by bcallah
Branch: MAIN
CVS Tags: OPENBSD_5_8_BASE, OPENBSD_5_8 Changes since 1.28: +1 -9 lines
unifdef -U NO_DPROMPT and GOSREC.
NO_DPROMPT has been around since the import of mg2a and it has never been
considered a "(Common) compile-time option" in the Makefile.
Assume everyone has been running mg this way since at least 2000 if not
already in the 90s.
Same with GOSREC. Has always been there but it looks like no one noticed
it (and no one was running with it). Indeed, the mg tutorial appears to be
oblivious to GOSREC being an option.
With this commit there are no more #ifndef blocks in mg. Only a couple of
#ifdef blocks remain.
ok lum@
|
/* $OpenBSD: kbd.c,v 1.29 2015/03/25 20:53:31 bcallah Exp $ */
/* This file is in the public domain. */
/*
* Terminal independent keyboard handling.
*/
#include <sys/queue.h>
#include <signal.h>
#include <stdio.h>
#include "def.h"
#include "kbd.h"
#include "key.h"
#include "macro.h"
#define METABIT 0x80
#define PROMPTL 80
char prompt[PROMPTL] = "", *promptp = prompt;
static int mgwrap(PF, int, int);
static int use_metakey = TRUE;
static int pushed = FALSE;
static int pushedc;
struct map_element *ele;
struct key key;
/*
* Toggle the value of use_metakey
*/
int
do_meta(int f, int n)
{
if (f & FFARG)
use_metakey = n > 0;
else
use_metakey = !use_metakey;
ewprintf("Meta keys %sabled", use_metakey ? "en" : "dis");
return (TRUE);
}
static int bs_map = 0;
/*
* Toggle backspace mapping
*/
int
bsmap(int f, int n)
{
if (f & FFARG)
bs_map = n > 0;
else
bs_map = !bs_map;
ewprintf("Backspace mapping %sabled", bs_map ? "en" : "dis");
return (TRUE);
}
void
ungetkey(int c)
{
if (use_metakey && pushed && c == CCHR('['))
pushedc |= METABIT;
else
pushedc = c;
pushed = TRUE;
}
int
getkey(int flag)
{
int c;
if (flag && !pushed) {
if (prompt[0] != '\0' && ttwait(2000)) {
/* avoid problems with % */
ewprintf("%s", prompt);
/* put the cursor back */
update(CMODE);
epresf = KCLEAR;
}
if (promptp > prompt)
*(promptp - 1) = ' ';
}
if (pushed) {
c = pushedc;
pushed = FALSE;
} else
c = ttgetc();
if (bs_map) {
if (c == CCHR('H'))
c = CCHR('?');
else if (c == CCHR('?'))
c = CCHR('H');
}
if (use_metakey && (c & METABIT)) {
pushedc = c & ~METABIT;
pushed = TRUE;
c = CCHR('[');
}
if (flag && promptp < &prompt[PROMPTL - 5]) {
promptp = getkeyname(promptp,
sizeof(prompt) - (promptp - prompt) - 1, c);
*promptp++ = '-';
*promptp = '\0';
}
return (c);
}
/*
* doscan scans a keymap for a keyboard character and returns a pointer
* to the function associated with that character. Sets ele to the
* keymap element the keyboard was found in as a side effect.
*/
PF
doscan(KEYMAP *map, int c, KEYMAP **newmap)
{
struct map_element *elec = &map->map_element[0];
struct map_element *last = &map->map_element[map->map_num];
PF ret;
while (elec < last && c > elec->k_num)
elec++;
/* used by prefix and binding code */
ele = elec;
if (elec >= last || c < elec->k_base)
ret = map->map_default;
else
ret = elec->k_funcp[c - elec->k_base];
if (ret == NULL && newmap != NULL)
*newmap = elec->k_prefmap;
return (ret);
}
int
doin(void)
{
KEYMAP *curmap;
PF funct;
*(promptp = prompt) = '\0';
curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
key.k_count = 0;
while ((funct = doscan(curmap, (key.k_chars[key.k_count++] =
getkey(TRUE)), &curmap)) == NULL)
/* nothing */;
if (macrodef && macrocount < MAXMACRO)
macro[macrocount++].m_funct = funct;
return (mgwrap(funct, 0, 1));
}
int
rescan(int f, int n)
{
int c;
KEYMAP *curmap;
int i;
PF fp = NULL;
int md = curbp->b_nmodes;
for (;;) {
if (ISUPPER(key.k_chars[key.k_count - 1])) {
c = TOLOWER(key.k_chars[key.k_count - 1]);
curmap = curbp->b_modes[md]->p_map;
for (i = 0; i < key.k_count - 1; i++) {
if ((fp = doscan(curmap, (key.k_chars[i]),
&curmap)) != NULL)
break;
}
if (fp == NULL) {
if ((fp = doscan(curmap, c, NULL)) == NULL)
while ((fp = doscan(curmap,
key.k_chars[key.k_count++] =
getkey(TRUE), &curmap)) == NULL)
/* nothing */;
if (fp != rescan) {
if (macrodef && macrocount <= MAXMACRO)
macro[macrocount - 1].m_funct
= fp;
return (mgwrap(fp, f, n));
}
}
}
/* try previous mode */
if (--md < 0)
return (ABORT);
curmap = curbp->b_modes[md]->p_map;
for (i = 0; i < key.k_count; i++) {
if ((fp = doscan(curmap, (key.k_chars[i]), &curmap)) != NULL)
break;
}
if (fp == NULL) {
while ((fp = doscan(curmap, key.k_chars[i++] =
getkey(TRUE), &curmap)) == NULL)
/* nothing */;
key.k_count = i;
}
if (fp != rescan && i >= key.k_count - 1) {
if (macrodef && macrocount <= MAXMACRO)
macro[macrocount - 1].m_funct = fp;
return (mgwrap(fp, f, n));
}
}
}
int
universal_argument(int f, int n)
{
KEYMAP *curmap;
PF funct;
int c, nn = 4;
if (f & FFUNIV)
nn *= n;
for (;;) {
key.k_chars[0] = c = getkey(TRUE);
key.k_count = 1;
if (c == '-')
return (negative_argument(f, nn));
if (c >= '0' && c <= '9')
return (digit_argument(f, nn));
curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
while ((funct = doscan(curmap, c, &curmap)) == NULL) {
key.k_chars[key.k_count++] = c = getkey(TRUE);
}
if (funct != universal_argument) {
if (macrodef && macrocount < MAXMACRO - 1) {
if (f & FFARG)
macrocount--;
macro[macrocount++].m_count = nn;
macro[macrocount++].m_funct = funct;
}
return (mgwrap(funct, FFUNIV, nn));
}
nn <<= 2;
}
}
/* ARGSUSED */
int
digit_argument(int f, int n)
{
KEYMAP *curmap;
PF funct;
int nn, c;
nn = key.k_chars[key.k_count - 1] - '0';
for (;;) {
c = getkey(TRUE);
if (c < '0' || c > '9')
break;
nn *= 10;
nn += c - '0';
}
key.k_chars[0] = c;
key.k_count = 1;
curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
while ((funct = doscan(curmap, c, &curmap)) == NULL) {
key.k_chars[key.k_count++] = c = getkey(TRUE);
}
if (macrodef && macrocount < MAXMACRO - 1) {
if (f & FFARG)
macrocount--;
else
macro[macrocount - 1].m_funct = universal_argument;
macro[macrocount++].m_count = nn;
macro[macrocount++].m_funct = funct;
}
return (mgwrap(funct, FFOTHARG, nn));
}
int
negative_argument(int f, int n)
{
KEYMAP *curmap;
PF funct;
int c;
int nn = 0;
for (;;) {
c = getkey(TRUE);
if (c < '0' || c > '9')
break;
nn *= 10;
nn += c - '0';
}
if (nn)
nn = -nn;
else
nn = -n;
key.k_chars[0] = c;
key.k_count = 1;
curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
while ((funct = doscan(curmap, c, &curmap)) == NULL) {
key.k_chars[key.k_count++] = c = getkey(TRUE);
}
if (macrodef && macrocount < MAXMACRO - 1) {
if (f & FFARG)
macrocount--;
else
macro[macrocount - 1].m_funct = universal_argument;
macro[macrocount++].m_count = nn;
macro[macrocount++].m_funct = funct;
}
return (mgwrap(funct, FFNEGARG, nn));
}
/*
* Insert a character. While defining a macro, create a "LINE" containing
* all inserted characters.
*/
int
selfinsert(int f, int n)
{
struct line *lp;
int c;
int count;
if (n < 0)
return (FALSE);
if (n == 0)
return (TRUE);
c = key.k_chars[key.k_count - 1];
if (macrodef && macrocount < MAXMACRO) {
if (f & FFARG)
macrocount -= 2;
/* last command was insert -- tack on the end */
if (lastflag & CFINS) {
macrocount--;
/* Ensure the line can handle the new characters */
if (maclcur->l_size < maclcur->l_used + n) {
if (lrealloc(maclcur, maclcur->l_used + n) ==
FALSE)
return (FALSE);
}
maclcur->l_used += n;
/* Copy in the new data */
for (count = maclcur->l_used - n;
count < maclcur->l_used; count++)
maclcur->l_text[count] = c;
} else {
macro[macrocount - 1].m_funct = insert;
if ((lp = lalloc(n)) == NULL)
return (FALSE);
lp->l_bp = maclcur;
lp->l_fp = maclcur->l_fp;
maclcur->l_fp = lp;
maclcur = lp;
for (count = 0; count < n; count++)
lp->l_text[count] = c;
}
thisflag |= CFINS;
}
if (c == '\n') {
do {
count = lnewline();
} while (--n && count == TRUE);
return (count);
}
/* overwrite mode */
if (curbp->b_flag & BFOVERWRITE) {
lchange(WFEDIT);
while (curwp->w_doto < llength(curwp->w_dotp) && n--)
lputc(curwp->w_dotp, curwp->w_doto++, c);
if (n <= 0)
return (TRUE);
}
return (linsert(n, c));
}
/*
* This could be implemented as a keymap with everything defined as self-insert.
*/
int
quote(int f, int n)
{
int c;
key.k_count = 1;
if ((key.k_chars[0] = getkey(TRUE)) >= '0' && key.k_chars[0] <= '7') {
key.k_chars[0] -= '0';
if ((c = getkey(TRUE)) >= '0' && c <= '7') {
key.k_chars[0] <<= 3;
key.k_chars[0] += c - '0';
if ((c = getkey(TRUE)) >= '0' && c <= '7') {
key.k_chars[0] <<= 3;
key.k_chars[0] += c - '0';
} else
ungetkey(c);
} else
ungetkey(c);
}
return (selfinsert(f, n));
}
/*
* Wraper function to count invocation repeats.
* We ignore any function whose sole purpose is to get us
* to the intended function.
*/
static int
mgwrap(PF funct, int f, int n)
{
static PF ofp;
if (funct != rescan &&
funct != negative_argument &&
funct != digit_argument &&
funct != universal_argument) {
if (funct == ofp)
rptcount++;
else
rptcount = 0;
ofp = funct;
}
return ((*funct)(f, n));
}