File: [local] / src / usr.bin / mg / keymap.c (download)
Revision 1.5, Mon Jan 29 01:58:08 2001 UTC (23 years, 4 months ago) by niklas
Branch: MAIN
CVS Tags: OPENBSD_2_9_BASE, OPENBSD_2_9 Changes since 1.4: +2 -0 lines
$OpenBSD$
|
/* $OpenBSD: keymap.c,v 1.5 2001/01/29 01:58:08 niklas Exp $ */
/*
* Keyboard maps. This is character set dependent. The terminal specific
* parts of building the keymap has been moved to a better place.
*/
#include "def.h"
#include "kbd.h"
static int name_fent __P((char *, int));
/*
* initial keymap declarations, deepest first
*/
#ifndef NO_HELP
static PF cHcG[] = {
ctrlg, /* ^G */
help_help, /* ^H */
};
static PF cHa[] = {
apropos_command, /* a */
wallchart, /* b */
desckey, /* c */
};
static struct KEYMAPE (2 + IMAPEXT) helpmap = {
2,
2 + IMAPEXT,
rescan,
{
{
CCHR('G'), CCHR('H'), cHcG, (KEYMAP *)NULL
},
{
'a', 'c', cHa, (KEYMAP *)NULL
},
}
};
#endif /* !NO_HELP */
static struct KEYMAPE (1 + IMAPEXT) extramap1 = {
0,
1 + IMAPEXT,
rescan
};
static struct KEYMAPE (1 + IMAPEXT) extramap2 = {
0,
1 + IMAPEXT,
rescan
};
static struct KEYMAPE (1 + IMAPEXT) extramap3 = {
0,
1 + IMAPEXT,
rescan
};
static struct KEYMAPE (1 + IMAPEXT) extramap4 = {
0,
1 + IMAPEXT,
rescan
};
static struct KEYMAPE (1 + IMAPEXT) extramap5 = {
0,
1 + IMAPEXT,
rescan
};
static PF cX4cF[] = {
poptofile, /* ^f */
ctrlg, /* ^g */
};
static PF cX4b[] = {
poptobuffer, /* b */
rescan, /* c */
rescan, /* d */
rescan, /* e */
poptofile, /* f */
};
static struct KEYMAPE (2 + IMAPEXT) cX4map = {
2,
2 + IMAPEXT,
rescan,
{
{
CCHR('F'), CCHR('G'), cX4cF, (KEYMAP *)NULL
},
{
'b', 'f', cX4b, (KEYMAP *)NULL
},
}
};
static PF cXcB[] = {
listbuffers, /* ^B */
quit, /* ^C */
rescan, /* ^D */
rescan, /* ^E */
filevisit, /* ^F */
ctrlg, /* ^G */
};
static PF cXcL[] = {
lowerregion, /* ^L */
rescan, /* ^M */
rescan, /* ^N */
deblank, /* ^O */
rescan, /* ^P */
rescan, /* ^Q */
rescan, /* ^R */
filesave, /* ^S */
rescan, /* ^T */
upperregion, /* ^U */
rescan, /* ^V */
filewrite, /* ^W */
swapmark, /* ^X */
};
#ifndef NO_MACRO
static PF cXlp[] = {
definemacro, /* ( */
finishmacro, /* ) */
};
#endif /* !NO_MACRO */
static PF cX0[] = {
delwind, /* 0 */
onlywind, /* 1 */
splitwind, /* 2 */
rescan, /* 3 */
prefix, /* 4 */
};
static PF cXeq[] = {
showcpos, /* = */
};
static PF cXcar[] = {
enlargewind, /* ^ */
rescan, /* _ */
rescan, /* ` */
rescan, /* a */
usebuffer, /* b */
rescan, /* c */
#ifndef NO_DIRED
dired, /* d */
#else /* !NO_DIRED */
rescan, /* d */
#endif /* !NO_DIRED */
#ifndef NO_MACRO
executemacro, /* e */
#else /* !NO_MACRO */
rescan, /* e */
#endif /* !NO_MACRO */
setfillcol, /* f */
rescan, /* g */
rescan, /* h */
fileinsert, /* i */
rescan, /* j */
killbuffer, /* k */
rescan, /* l */
rescan, /* m */
rescan, /* n */
nextwind, /* o */
rescan, /* p */
rescan, /* q */
rescan, /* r */
savebuffers, /* s */
};
#ifndef NO_MACRO
static struct KEYMAPE (6 + IMAPEXT) cXmap = {
6,
6 + IMAPEXT,
#else /* !NO_MACRO */
static struct KEYMAPE (5 + IMAPEXT) cXmap = {
5,
5 + IMAPEXT,
#endif /* !NO_MACRO */
rescan,
{
{
CCHR('B'), CCHR('G'), cXcB, (KEYMAP *)NULL
},
{
CCHR('L'), CCHR('X'), cXcL, (KEYMAP *)NULL
},
#ifndef NO_MACRO
{
'(', ')', cXlp, (KEYMAP *)NULL
},
#endif /* !NO_MACRO */
{
'0', '4', cX0, (KEYMAP *) & cX4map
},
{
'=', '=', cXeq, (KEYMAP *)NULL
},
{
'^', 's', cXcar, (KEYMAP *)NULL
},
}
};
static PF metacG[] = {
ctrlg, /* ^G */
};
static PF metacV[] = {
pagenext, /* ^V */
};
static PF metasp[] = {
justone, /* space */
};
static PF metapct[] = {
queryrepl, /* % */
};
static PF metami[] = {
negative_argument, /* - */
rescan, /* . */
rescan, /* / */
digit_argument, /* 0 */
digit_argument, /* 1 */
digit_argument, /* 2 */
digit_argument, /* 3 */
digit_argument, /* 4 */
digit_argument, /* 5 */
digit_argument, /* 6 */
digit_argument, /* 7 */
digit_argument, /* 8 */
digit_argument, /* 9 */
rescan, /* : */
rescan, /* ; */
gotobob, /* < */
rescan, /* = */
gotoeob, /* > */
};
static PF metalb[] = {
gotobop, /* [ */
delwhite, /* \ */
gotoeop, /* ] */
rescan, /* ^ */
rescan, /* _ */
rescan, /* ` */
rescan, /* a */
backword, /* b */
capword, /* c */
delfword, /* d */
rescan, /* e */
forwword, /* f */
};
static PF metal[] = {
lowerword, /* l */
rescan, /* m */
rescan, /* n */
rescan, /* o */
rescan, /* p */
fillpara, /* q */
backsearch, /* r */
forwsearch, /* s */
rescan, /* t */
upperword, /* u */
backpage, /* v */
copyregion, /* w */
extend, /* x */
};
static PF metatilde[] = {
notmodified, /* ~ */
delbword, /* DEL */
};
static struct KEYMAPE (8 + IMAPEXT) metamap = {
8,
8 + IMAPEXT,
rescan,
{
{
CCHR('G'), CCHR('G'), metacG, (KEYMAP *)NULL
},
{
CCHR('V'), CCHR('V'), metacV, (KEYMAP *)NULL
},
{
' ', ' ', metasp, (KEYMAP *)NULL
},
{
'%', '%', metapct, (KEYMAP *)NULL
},
{
'-', '>', metami, (KEYMAP *)NULL
},
{
'[', 'f', metalb, (KEYMAP *)NULL
},
{
'l', 'x', metal, (KEYMAP *) NULL
},
{
'~', CCHR('?'), metatilde, (KEYMAP *)NULL
},
}
};
static PF fund_at[] = {
setmark, /* ^@ */
gotobol, /* ^A */
backchar, /* ^B */
rescan, /* ^C */
forwdel, /* ^D */
gotoeol, /* ^E */
forwchar, /* ^F */
ctrlg, /* ^G */
#ifndef NO_HELP
prefix, /* ^H */
#else /* !NO_HELP */
rescan, /* ^H */
#endif /* !NO_HELP */
};
/* ^I is selfinsert */
static PF fund_CJ[] = {
indent, /* ^J */
killline, /* ^K */
reposition, /* ^L */
newline, /* ^M */
forwline, /* ^N */
openline, /* ^O */
backline, /* ^P */
quote, /* ^Q */
backisearch, /* ^R */
forwisearch, /* ^S */
twiddle, /* ^T */
universal_argument, /* ^U */
forwpage, /* ^V */
killregion, /* ^W */
prefix, /* ^X */
yank, /* ^Y */
spawncli, /* ^Z */
};
static PF fund_esc[] = {
prefix, /* esc */
rescan, /* ^\ selfinsert is default on fundamental */
rescan, /* ^] */
rescan, /* ^^ */
rescan, /* ^_ */
};
static PF fund_del[] = {
backdel, /* DEL */
};
#ifndef FUND_XMAPS
#define NFUND_XMAPS 0 /* extra map sections after normal ones */
#endif
static struct KEYMAPE (4 + NFUND_XMAPS + IMAPEXT) fundmap = {
4 + NFUND_XMAPS,
4 + NFUND_XMAPS + IMAPEXT,
selfinsert,
{
#ifndef NO_HELP
{
CCHR('@'), CCHR('H'), fund_at, (KEYMAP *) & helpmap
},
#else /* !NO_HELP */
{
CCHR('@'), CCHR('H'), fund_at, (KEYMAP *)NULL
},
#endif /* !NO_HELP */
{
CCHR('J'), CCHR('Z'), fund_CJ, (KEYMAP *) & cXmap
},
{
CCHR('['), CCHR('_'), fund_esc, (KEYMAP *) & metamap
},
{
CCHR('?'), CCHR('?'), fund_del, (KEYMAP *)NULL
},
#ifdef FUND_XMAPS
FUND_XMAPS,
#endif /* FUND_XMAPS */
}
};
static PF fill_sp[] = {
fillword, /* ' ' */
};
static struct KEYMAPE (1 + IMAPEXT) fillmap = {
1,
1 + IMAPEXT,
rescan,
{
{
' ', ' ', fill_sp, (KEYMAP *)NULL
},
}
};
static PF indent_lf[] = {
newline, /* ^J */
rescan, /* ^K */
rescan, /* ^L */
indent, /* ^M */
};
static struct KEYMAPE (1 + IMAPEXT) indntmap = {
1,
1 + IMAPEXT,
rescan,
{
{
CCHR('J'), CCHR('M'), indent_lf, (KEYMAP *)NULL
},
}
};
static PF blink_rp[] = {
showmatch, /* ) */
};
static struct KEYMAPE (1 + IMAPEXT) blinkmap = {
1,
1 + IMAPEXT,
rescan,
{
{
')', ')', blink_rp, (KEYMAP *)NULL
},
}
};
#ifdef NOTAB
static PF notab_tab[] = {
space_to_tabstop, /* ^I */
};
static struct KEYMAPE (1 + IMAPEXT) notabmap = {
1,
1 + IMAPEXT,
rescan,
{
{
CCHR('I'), CCHR('I'), notab_tab, (KEYMAP *)NULL
},
}
};
#endif /* NOTAB */
static struct KEYMAPE (1 + IMAPEXT) overwmap = {
0,
1 + IMAPEXT, /* 1 to avoid 0 sized array */
rescan,
{
/* unused dummy entry for VMS C */
{
(KCHAR)0, (KCHAR)0, (PF *)NULL, (KEYMAP *)NULL
},
}
};
#ifndef NO_DIRED
static PF dirednul[] = {
setmark, /* ^@ */
gotobol, /* ^A */
backchar, /* ^B */
rescan, /* ^C */
d_del, /* ^D */
gotoeol, /* ^E */
forwchar, /* ^F */
ctrlg, /* ^G */
#ifndef NO_HELP
prefix, /* ^H */
#endif /* !NO_HELP */
};
static PF diredcl[] = {
reposition, /* ^L */
forwline, /* ^M */
forwline, /* ^N */
rescan, /* ^O */
backline, /* ^P */
rescan, /* ^Q */
backisearch, /* ^R */
forwisearch, /* ^S */
rescan, /* ^T */
universal_argument, /* ^U */
forwpage, /* ^V */
rescan, /* ^W */
prefix, /* ^X */
};
static PF diredcz[] = {
spawncli, /* ^Z */
prefix, /* esc */
rescan, /* ^\ */
rescan, /* ^] */
rescan, /* ^^ */
rescan, /* ^_ */
forwline, /* SP */
};
static PF diredc[] = {
d_copy, /* c */
d_del, /* d */
d_findfile, /* e */
d_findfile, /* f */
};
static PF diredn[] = {
forwline, /* n */
d_ffotherwindow, /* o */
backline, /* p */
rescan, /* q */
d_rename, /* r */
rescan, /* s */
rescan, /* t */
d_undel, /* u */
rescan, /* v */
rescan, /* w */
d_expunge, /* x */
};
static PF direddl[] = {
d_undelbak, /* del */
};
#ifndef DIRED_XMAPS
#define NDIRED_XMAPS 0 /* number of extra map sections */
#endif /* DIRED_XMAPS */
static struct KEYMAPE (6 + NDIRED_XMAPS + IMAPEXT) diredmap = {
6 + NDIRED_XMAPS,
6 + NDIRED_XMAPS + IMAPEXT,
rescan,
{
#ifndef NO_HELP
{
CCHR('@'), CCHR('H'), dirednul, (KEYMAP *) & helpmap
},
#else /* !NO_HELP */
{
CCHR('@'), CCHR('G'), dirednul, (KEYMAP *)NULL
},
#endif /* !NO_HELP */
{
CCHR('L'), CCHR('X'), diredcl, (KEYMAP *) & cXmap
},
{
CCHR('Z'), ' ', diredcz, (KEYMAP *) & metamap
},
{
'c', 'f', diredc, (KEYMAP *)NULL
},
{
'n', 'x', diredn, (KEYMAP *)NULL
},
{
CCHR('?'), CCHR('?'), direddl, (KEYMAP *)NULL
},
#ifdef DIRED_XMAPS
DIRED_XMAPS, /* map sections for dired mode keys */
#endif /* DIRED_XMAPS */
}
};
#endif /* !NO_DIRED */
/*
* give names to the maps, for use by help etc. If the map is to be bindable,
* it must also be listed in the function name table below with the same
* name. Maps created dynamicly currently don't get added here, thus are
* unnamed. Modes are just named keymaps with functions to add/subtract them
* from a buffer's list of modes. If you change a mode name, change it in
* modes.c also.
*/
MAPS map_table[] = {
/* fundamental map MUST be first entry */
{(KEYMAP *) & fundmap, "fundamental"},
{(KEYMAP *) & fillmap, "fill"},
{(KEYMAP *) & indntmap, "indent"},
{(KEYMAP *) & blinkmap, "blink"},
#ifdef NOTAB
{(KEYMAP *) & notabmap, "notab"},
#endif /* NOTAB */
{(KEYMAP *) & overwmap, "overwrite"},
{(KEYMAP *) & metamap, "esc prefix"},
{(KEYMAP *) & cXmap, "c-x prefix"},
{(KEYMAP *) & cX4map, "c-x 4 prefix"},
{(KEYMAP *) & extramap1, "extra prefix 1"},
{(KEYMAP *) & extramap2, "extra prefix 2"},
{(KEYMAP *) & extramap3, "extra prefix 3"},
{(KEYMAP *) & extramap4, "extra prefix 4"},
{(KEYMAP *) & extramap5, "extra prefix 5"},
#ifndef NO_HELP
{(KEYMAP *) & helpmap, "help"},
#endif
#ifndef NO_DIRED
{(KEYMAP *) & diredmap, "dired"},
#endif
};
#define NMAPS (sizeof map_table/sizeof(MAPS))
int nmaps = NMAPS; /* for use by rebind in extend.c */
char *
map_name(map)
KEYMAP *map;
{
MAPS *mp = &map_table[0];
do {
if (mp->p_map == map)
return mp->p_name;
} while (++mp < &map_table[NMAPS]);
return (char *)NULL;
}
MAPS *
name_mode(name)
char *name;
{
MAPS *mp = &map_table[0];
do {
if (strcmp(mp->p_name, name) == 0)
return mp;
} while (++mp < &map_table[NMAPS]);
return (MAPS *)NULL;
}
KEYMAP *
name_map(name)
char *name;
{
MAPS *mp;
return (mp = name_mode(name)) == NULL ? (KEYMAP *)NULL : mp->p_map;
}
/*
* Warning: functnames MUST be in alphabetical order! (due to binary search
* in name_function.) If the function is prefix, it must be listed with the
* same name in the map_table above.
*/
FUNCTNAMES functnames[] = {
#ifndef NO_HELP
{apropos_command, "apropos"},
#endif /* !NO_HELP */
{fillmode, "auto-fill-mode"},
{indentmode, "auto-indent-mode"},
{backchar, "backward-char"},
{delbword, "backward-kill-word"},
{gotobop, "backward-paragraph"},
{backword, "backward-word"},
{gotobob, "beginning-of-buffer"},
{gotobol, "beginning-of-line"},
{blinkparen, "blink-matching-paren"},
{showmatch, "blink-matching-paren-hack"},
#ifdef BSMAP
{bsmap, "bsmap-mode"},
#endif /* BSMAP */
{prefix, "c-x 4 prefix"},
{prefix, "c-x prefix"},
#ifndef NO_MACRO
{executemacro, "call-last-kbd-macro"},
#endif /* !NO_MACRO */
{capword, "capitalize-word"},
#ifndef NO_DIR
{changedir, "cd"},
#endif /* !NO_DIR */
{copyregion, "copy-region-as-kill"},
#ifdef REGEX
{cntmatchlines, "count-matches"},
{cntnonmatchlines, "count-non-matches"},
#endif /* REGEX */
{define_key, "define-key"},
{backdel, "delete-backward-char"},
{deblank, "delete-blank-lines"},
{forwdel, "delete-char"},
{delwhite, "delete-horizontal-space"},
#ifdef REGEX
{delmatchlines, "delete-matching-lines"},
{delnonmatchlines, "delete-non-matching-lines"},
#endif /* REGEX */
{onlywind, "delete-other-windows"},
{delwind, "delete-window"},
#ifndef NO_HELP
{wallchart, "describe-bindings"},
{desckey, "describe-key-briefly"},
#endif /* !NO_HELP */
{digit_argument, "digit-argument"},
#ifndef NO_DIRED
{dired, "dired"},
{d_undelbak, "dired-backup-unflag"},
{d_copy, "dired-copy-file"},
{d_expunge, "dired-do-deletions"},
{d_findfile, "dired-find-file"},
{d_ffotherwindow, "dired-find-file-other-window"},
{d_del, "dired-flag-file-deleted"},
{d_otherwindow, "dired-other-window"},
{d_rename, "dired-rename-file"},
{d_undel, "dired-unflag"},
#endif /* !NO_DIRED */
{lowerregion, "downcase-region"},
{lowerword, "downcase-word"},
{showversion, "emacs-version"},
#ifndef NO_MACRO
{finishmacro, "end-kbd-macro"},
#endif /* !NO_MACRO */
{gotoeob, "end-of-buffer"},
{gotoeol, "end-of-line"},
{enlargewind, "enlarge-window"},
{prefix, "esc prefix"},
#ifndef NO_STARTUP
{evalbuffer, "eval-current-buffer"},
{evalexpr, "eval-expression"},
#endif /* !NO_STARTUP */
{swapmark, "exchange-point-and-mark"},
{extend, "execute-extended-command"},
{prefix, "extra prefix 1"},
{prefix, "extra prefix 2"},
{prefix, "extra prefix 3"},
{prefix, "extra prefix 4"},
{prefix, "extra prefix 5"},
{fillpara, "fill-paragraph"},
{filevisit, "find-file"},
{poptofile, "find-file-other-window"},
{forwchar, "forward-char"},
{gotoeop, "forward-paragraph"},
{forwword, "forward-word"},
{bindtokey, "global-set-key"},
{unbindtokey, "global-unset-key"},
{gotoline, "goto-line"},
#ifndef NO_HELP
{prefix, "help"},
{help_help, "help-help"},
#endif /* !NO_HELP */
{insert, "insert"},
{bufferinsert, "insert-buffer"},
{fileinsert, "insert-file"},
{fillword, "insert-with-wrap"},
{backisearch, "isearch-backward"},
{forwisearch, "isearch-forward"},
{justone, "just-one-space"},
{ctrlg, "keyboard-quit"},
{killbuffer, "kill-buffer"},
{killline, "kill-line"},
{killpara, "kill-paragraph"},
{killregion, "kill-region"},
{delfword, "kill-word"},
{listbuffers, "list-buffers"},
#ifndef NO_STARTUP
{evalfile, "load"},
#endif /* !NO_STARTUP */
{localbind, "local-set-key"},
{localunbind, "local-unset-key"},
#ifndef NO_BACKUP
{makebkfile, "make-backup-files"},
#endif /* !NO_BACKUP */
#ifdef DO_METAKEY
{do_meta, "meta-key-mode"}, /* better name, anyone? */
#endif /* DO_METAKEY */
{negative_argument, "negative-argument"},
{newline, "newline"},
{indent, "newline-and-indent"},
{forwline, "next-line"},
#ifdef NOTAB
{notabmode, "no-tab-mode"},
#endif /* NOTAB */
{notmodified, "not-modified"},
{openline, "open-line"},
{nextwind, "other-window"},
{overwrite, "overwrite-mode"},
#ifdef PREFIXREGION
{prefixregion, "prefix-region"},
#endif /* PREFIXREGION */
{backline, "previous-line"},
#ifdef GOSMACS
{prevwind, "previous-window"},
#endif /* GOSEMACS */
{spawncli, "push-shell"},
#ifndef NO_DIR
{showcwdir, "pwd"},
#endif /* !NO_DIR */
{queryrepl, "query-replace"},
#ifdef REGEX
{re_queryrepl, "query-replace-regexp"},
#endif /* REGEX */
{quote, "quoted-insert"},
#ifdef REGEX
{re_searchagain, "re-search-again"},
{re_backsearch, "re-search-backward"},
{re_forwsearch, "re-search-forward"},
#endif /* REGEX */
{reposition, "recenter"},
{refresh, "redraw-display"},
{filesave, "save-buffer"},
{quit, "save-buffers-kill-emacs"},
{savebuffers, "save-some-buffers"},
{backpage, "scroll-down"},
#ifdef GOSMACS
{back1page, "scroll-one-line-down"},
{forw1page, "scroll-one-line-up"},
#endif /* GOSMACS */
{pagenext, "scroll-other-window"},
{forwpage, "scroll-up"},
{searchagain, "search-again"},
{backsearch, "search-backward"},
{forwsearch, "search-forward"},
{selfinsert, "self-insert-command"},
#ifdef REGEX
{setcasefold, "set-case-fold-search"},
#endif /* REGEX */
{set_default_mode, "set-default-mode"},
{setfillcol, "set-fill-column"},
{setmark, "set-mark-command"},
#ifdef PREFIXREGION
{setprefix, "set-prefix-string"},
#endif /* PREFIXREGION */
{shrinkwind, "shrink-window"},
#ifdef NOTAB
{space_to_tabstop, "space-to-tabstop"},
#endif /* NOTAB */
{splitwind, "split-window-vertically"},
#ifndef NO_MACRO
{definemacro, "start-kbd-macro"},
#endif /* !NO_MACRO */
{spawncli, "suspend-emacs"},
{usebuffer, "switch-to-buffer"},
{poptobuffer, "switch-to-buffer-other-window"},
{twiddle, "transpose-chars"},
{universal_argument, "universal-argument"},
{upperregion, "upcase-region"},
{upperword, "upcase-word"},
{showcpos, "what-cursor-position"},
{filewrite, "write-file"},
{yank, "yank"},
};
#define NFUNCT (sizeof(functnames)/sizeof(FUNCTNAMES))
int nfunct = NFUNCT; /* used by help.c */
/*
* The general-purpose version of ROUND2 blows osk C (2.0) out of the water.
* (reboot required) If you need to build a version of mg with less than 32
* or more than 511 functions, something better must be done.
* The version that should work, but doesn't is:
* #define ROUND2(x) (1+((x>>1)|(x>>2)|(x>>3)|(x>>4)|(x>>5)|(x>>6)|(x>>7)|\
* (x>>8)|(x>>9)|(x>>10)|(x>>11)|(x>>12)|(x>>13)|(x>>14)|(x>>15)))
*/
#define ROUND2(x) (x<128?(x<64?32:64):(x<256?128:256))
static int
name_fent(fname, flag)
char *fname;
int flag;
{
int try, notit;
int x = ROUND2(NFUNCT);
int base = 0;
do {
/* + can be used instead of | here if more efficent. */
if ((try = base | x) < NFUNCT) {
if ((notit = strcmp(fname, functnames[try].n_name))
>= 0) {
if (!notit)
return try;
base = try;
}
}
/* try 0 once if needed */
} while ((x >>= 1) || (try == 1 && base == 0));
return flag ? base : -1;
}
/*
* Translate from function name to function pointer, using binary search.
*/
PF
name_function(fname)
char *fname;
{
int i;
if ((i = name_fent(fname, FALSE)) >= 0)
return functnames[i].n_funct;
return (PF)NULL;
}
/*
* complete function name
*/
int
complete_function(fname, c)
char *fname;
int c;
{
int i, j, k, l, oj;
i = name_fent(fname, TRUE);
for (j = 0; (l = fname[j]) && functnames[i].n_name[j] == l; j++) {
}
if (fname[j] != '\0') {
if (++i >= NFUNCT)
/* no match */
return -2;
for (j = 0; (l = fname[j]) && functnames[i].n_name[j] == l;
j++);
if (fname[j] != '\0')
/* no match */
return -2;
}
if (c == CCHR('M') && functnames[i].n_name[j] == '\0')
return -1;
/* find last match */
for (k = i + 1; k < NFUNCT; k++) {
for (l = 0; functnames[k].n_name[l] == fname[l]; l++);
if (l < j)
break;
}
k--;
oj = j;
if (k > i) {
/* multiple matches */
while ((l = functnames[i].n_name[j]) ==
functnames[k].n_name[j]) {
fname[j++] = l;
if (l == '-' && c == ' ')
break;
}
if (j == oj)
/* ambiguous */
return -3;
} else {
/* single match */
while ((l = functnames[i].n_name[j])) {
fname[j++] = l;
if (l == '-' && c == ' ')
break;
}
}
fname[j] = '\0';
return j - oj;
}
/*
* list possible function name completions.
*/
LIST *
complete_function_list(fname, c)
char *fname;
int c;
{
int i, j, k, l;
LIST *current, *last;
i = name_fent(fname, TRUE);
for (j = 0; (l = fname[j]) && functnames[i].n_name[j] == l; j++);
if (fname[j] != '\0') {
if (++i >= NFUNCT)
/* no match */
return NULL;
for (j = 0; (l = fname[j]) && functnames[i].n_name[j] == l;
j++);
if (fname[j] != '\0')
/* no match */
return NULL;
}
/*
* if(c==CCHR('M') && functnames[i].n_name[j]=='\0') return -1;
*/
/* find last match */
for (k = i + 1; k < NFUNCT; k++) {
for (l = 0; functnames[k].n_name[l] == fname[l]; l++);
if (l < j)
break;
}
k--;
last = NULL;
for (; k >= i; k--) {
current = (LIST *)malloc(sizeof(LIST));
current->l_next = last;
current->l_name = functnames[k].n_name;
last = current;
}
return (last);
}
/*
* translate from function pointer to function name.
*/
char *
function_name(fpoint)
PF fpoint;
{
FUNCTNAMES *fnp = &functnames[0];
if (fpoint == prefix)
/* ambiguous */
return (char *)NULL;
do {
if (fnp->n_funct == fpoint)
return fnp->n_name;
} while (++fnp < &functnames[NFUNCT]);
return (char *)NULL;
}