From e74702b467171dbdafb56dfe354794a212e020d9 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:05:38 +0000 Subject: Initial revision --- Src/Zle/zle_misc.c | 816 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 816 insertions(+) create mode 100644 Src/Zle/zle_misc.c (limited to 'Src/Zle/zle_misc.c') diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c new file mode 100644 index 000000000..42953852f --- /dev/null +++ b/Src/Zle/zle_misc.c @@ -0,0 +1,816 @@ +/* + * zle_misc.c - miscellaneous editor routines + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 1992-1997 Paul Falstad + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Paul Falstad or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Paul Falstad and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Paul Falstad and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Paul Falstad and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "zle.mdh" +#include "zle_misc.pro" + +/* insert a metafied string, with repetition and suffix removal */ + +/**/ +void +doinsert(char *str) +{ + char *s; + int len = ztrlen(str); + int c1 = *str == Meta ? STOUC(str[1])^32 : STOUC(*str);/* first character */ + int neg = zmult < 0; /* insert *after* the cursor? */ + int m = neg ? -zmult : zmult; /* number of copies to insert */ + + iremovesuffix(c1); + invalidatelist(); + + if(insmode) + spaceinline(m * len); + else if(cs + m * len > ll) + spaceinline(cs + m * len - ll); + while(m--) + for(s = str; *s; s++) + line[cs++] = *s == Meta ? *++s ^ 32 : *s; + if(neg) + cs += zmult * len; +} + +/**/ +void +selfinsert(void) +{ + char s[3], *p = s; + + if(imeta(c)) { + *p++ = Meta; + c ^= 32; + } + *p++ = c; + *p = 0; + doinsert(s); +} + +/**/ +void +selfinsertunmeta(void) +{ + c &= 0x7f; + if (c == '\r') + c = '\n'; + selfinsert(); +} + +/**/ +void +deletechar(void) +{ + if (zmult < 0) { + zmult = -zmult; + backwarddeletechar(); + zmult = -zmult; + return; + } + if (cs + zmult <= ll) { + cs += zmult; + backdel(zmult); + } else + feep(); +} + +/**/ +void +backwarddeletechar(void) +{ + if (zmult < 0) { + zmult = -zmult; + deletechar(); + zmult = -zmult; + return; + } + backdel(zmult > cs ? cs : zmult); +} + +/**/ +void +killwholeline(void) +{ + int i, fg, n = zmult; + + if (n < 0) + return; + while (n--) { + if ((fg = (cs && cs == ll))) + cs--; + while (cs && line[cs - 1] != '\n') + cs--; + for (i = cs; i != ll && line[i] != '\n'; i++); + forekill(i - cs + (i != ll), fg); + } +} + +/**/ +void +killbuffer(void) +{ + cs = 0; + forekill(ll, 0); +} + +/**/ +void +backwardkillline(void) +{ + int i = 0, n = zmult; + + if (n < 0) { + zmult = -n; + killline(); + zmult = n; + return; + } + while (n--) { + if (cs && line[cs - 1] == '\n') + cs--, i++; + else + while (cs && line[cs - 1] != '\n') + cs--, i++; + } + forekill(i, 1); +} + +/**/ +void +gosmacstransposechars(void) +{ + int cc; + + if (cs < 2 || line[cs - 1] == '\n' || line[cs - 2] == '\n') { + if (cs == ll || line[cs] == '\n' || + ((cs + 1 == ll || line[cs + 1] == '\n') && + (!cs || line[cs - 1] == '\n'))) { + feep(); + return; + } + cs += (cs == 0 || line[cs - 1] == '\n') ? 2 : 1; + } + cc = line[cs - 2]; + line[cs - 2] = line[cs - 1]; + line[cs - 1] = cc; +} + +/**/ +void +transposechars(void) +{ + int cc, ct; + int n = zmult; + int neg = n < 0; + + if (neg) + n = -n; + while (n--) { + if (!(ct = cs) || line[cs - 1] == '\n') { + if (ll == cs || line[cs] == '\n') { + feep(); + return; + } + if (!neg) + cs++; + ct++; + } + if (neg) { + if (cs && line[cs - 1] != '\n') { + cs--; + if (ct > 1 && line[ct - 2] != '\n') + ct--; + } + } else { + if (cs != ll && line[cs] != '\n') + cs++; + } + if (ct == ll || line[ct] == '\n') + ct--; + if (ct < 1 || line[ct - 1] == '\n') { + feep(); + return; + } + cc = line[ct - 1]; + line[ct - 1] = line[ct]; + line[ct] = cc; + } +} + +/**/ +void +poundinsert(void) +{ + cs = 0; + vifirstnonblank(); + if (line[cs] != '#') { + spaceinline(1); + line[cs] = '#'; + cs = findeol(); + while(cs != ll) { + cs++; + vifirstnonblank(); + spaceinline(1); + line[cs] = '#'; + cs = findeol(); + } + } else { + foredel(1); + cs = findeol(); + while(cs != ll) { + cs++; + vifirstnonblank(); + if(line[cs] == '#') + foredel(1); + cs = findeol(); + } + } + done = 1; +} + +/**/ +void +acceptline(void) +{ + done = 1; +} + +/**/ +void +acceptandhold(void) +{ + pushnode(bufstack, metafy((char *)line, ll, META_DUP)); + stackcs = cs; + done = 1; +} + +/**/ +void +killline(void) +{ + int i = 0, n = zmult; + + if (n < 0) { + zmult = -n; + backwardkillline(); + zmult = n; + return; + } + while (n--) { + if (line[cs] == '\n') + cs++, i++; + else + while (cs != ll && line[cs] != '\n') + cs++, i++; + } + backkill(i, 0); +} + +/**/ +void +killregion(void) +{ + if (mark > ll) + mark = ll; + if (mark > cs) + forekill(mark - cs, 0); + else + backkill(cs - mark, 1); +} + +/**/ +void +copyregionaskill(void) +{ + if (mark > ll) + mark = ll; + if (mark > cs) + cut(cs, mark - cs, 0); + else + cut(mark, cs - mark, 1); +} + +static int kct, yankb, yanke; + +/**/ +void +yank(void) +{ + Cutbuffer buf = &cutbuf; + int n = zmult; + + if (n < 0) + return; + if (zmod.flags & MOD_VIBUF) + buf = &vibuf[zmod.vibuf]; + if (!buf->buf) { + feep(); + return; + } + mark = cs; + yankb = cs; + while (n--) { + kct = kringnum; + spaceinline(buf->len); + memcpy((char *)line + cs, buf->buf, buf->len); + cs += buf->len; + yanke = cs; + } +} + +/**/ +void +yankpop(void) +{ + int cc; + + if (!(lastcmd & ZLE_YANK) || !kring[kct].buf) { + feep(); + return; + } + cs = yankb; + foredel(yanke - yankb); + cc = kring[kct].len; + spaceinline(cc); + memcpy((char *)line + cs, kring[kct].buf, cc); + cs += cc; + yanke = cs; + kct = (kct + KRINGCT - 1) % KRINGCT; +} + +/**/ +void +overwritemode(void) +{ + insmode ^= 1; +} +/**/ +void +whatcursorposition(void) +{ + char msg[100]; + char *s = msg; + int bol = findbol(); + int c = STOUC(line[cs]); + + if (cs == ll) + strucpy(&s, "EOF"); + else { + strucpy(&s, "Char: "); + switch (c) { + case ' ': + strucpy(&s, "SPC"); + break; + case '\t': + strucpy(&s, "TAB"); + break; + case '\n': + strucpy(&s, "LFD"); + break; + default: + if (imeta(c)) { + *s++ = Meta; + *s++ = c ^ 32; + } else + *s++ = c; + } + sprintf(s, " (0%o, %d, 0x%x)", c, c, c); + s += strlen(s); + } + sprintf(s, " point %d of %d(%d%%) column %d", cs+1, ll+1, + ll ? 100 * cs / ll : 0, cs - bol); + showmsg(msg); +} + +/**/ +void +undefinedkey(void) +{ + feep(); +} + +/**/ +void +quotedinsert(void) +{ +#ifndef HAS_TIO + struct sgttyb sob; + + sob = shttyinfo.sgttyb; + sob.sg_flags = (sob.sg_flags | RAW) & ~ECHO; + ioctl(SHTTY, TIOCSETN, &sob); +#endif + c = getkey(0); +#ifndef HAS_TIO + setterm(); +#endif + if (c < 0) + feep(); + else + selfinsert(); +} + +/**/ +void +digitargument(void) +{ + int sign = (zmult < 0) ? -1 : 1; + + if (!(zmod.flags & MOD_TMULT)) + zmod.tmult = 0; + if (zmod.flags & MOD_NEG) { + /* If we just had a negative argument, this is the digit, * + * rather than the -1 assumed by negargument() */ + zmod.tmult = sign * (c & 0xf); + zmod.flags &= ~MOD_NEG; + } else + zmod.tmult = zmod.tmult * 10 + sign * (c & 0xf); + zmod.flags |= MOD_TMULT; + prefixflag = 1; +} + +/**/ +void +negargument(void) +{ + if(zmod.flags & MOD_TMULT) { + feep(); + return; + } + zmod.tmult = -1; + zmod.flags |= MOD_TMULT|MOD_NEG; + prefixflag = 1; +} + +/**/ +void +universalargument(void) +{ + int digcnt = 0, pref = 0, minus = 1, gotk; + while ((gotk = getkey(0)) != EOF) { + if (gotk == '-' && !digcnt) { + minus = -1; + digcnt++; + } else if (gotk >= '0' && gotk <= '9') { + pref = pref * 10 + (gotk & 0xf); + digcnt++; + } else { + ungetkey(gotk); + break; + } + } + if (digcnt) + zmod.tmult = minus * (pref ? pref : 1); + else + zmod.tmult *= 4; + zmod.flags |= MOD_TMULT; + prefixflag = 1; +} + +/**/ +void +copyprevword(void) +{ + int len, t0; + + for (t0 = cs - 1; t0 >= 0; t0--) + if (iword(line[t0])) + break; + for (; t0 >= 0; t0--) + if (!iword(line[t0])) + break; + if (t0) + t0++; + len = cs - t0; + spaceinline(len); + memcpy((char *)&line[cs], (char *)&line[t0], len); + cs += len; +} + +/**/ +void +sendbreak(void) +{ + errflag = 1; +} + +/**/ +void +quoteregion(void) +{ + char *str; + size_t len; + + if (mark > ll) + mark = ll; + if (mark < cs) { + int tmp = mark; + mark = cs; + cs = tmp; + } + str = (char *)hcalloc(len = mark - cs); + memcpy(str, (char *)&line[cs], len); + foredel(len); + str = makequote(str, &len); + spaceinline(len); + memcpy((char *)&line[cs], str, len); + mark = cs; + cs += len; +} + +/**/ +void +quoteline(void) +{ + char *str; + size_t len = ll; + + str = makequote((char *)line, &len); + sizeline(len); + memcpy(line, str, len); + cs = ll = len; +} + +/**/ +static char * +makequote(char *str, size_t *len) +{ + int qtct = 0; + char *l, *ol; + char *end = str + *len; + + for (l = str; l < end; l++) + if (*l == '\'') + qtct++; + *len += 2 + qtct*3; + l = ol = (char *)halloc(*len); + *l++ = '\''; + for (; str < end; str++) + if (*str == '\'') { + *l++ = '\''; + *l++ = '\\'; + *l++ = '\''; + *l++ = '\''; + } else + *l++ = *str; + *l++ = '\''; + return ol; +} + +static char *cmdbuf; +static LinkList cmdll; +static int cmdambig; + +/**/ +static void +scancompcmd(HashNode hn, int flags) +{ + int l; + Thingy t = (Thingy) hn; + + if(strpfx(cmdbuf, t->nam)) { + addlinknode(cmdll, t->nam); + l = pfxlen(peekfirst(cmdll), t->nam); + if (l < cmdambig) + cmdambig = l; + } + +} + +#define NAMLEN 60 + +/**/ +Thingy +executenamedcommand(char *prmt) +{ + Thingy cmd; + int len, l = strlen(prmt); + char *ptr; + char *okeymap = curkeymapname; + + cmdbuf = halloc(l + NAMLEN + 2); + strcpy(cmdbuf, prmt); + statusline = cmdbuf; + selectkeymap("main", 1); + ptr = cmdbuf += l; + len = 0; + for (;;) { + *ptr = '_'; + statusll = l + len + 1; + refresh(); + if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { + statusline = NULL; + selectkeymap(okeymap, 1); + return NULL; + } + if(cmd == Th(z_clearscreen)) { + clearscreen(); + } else if(cmd == Th(z_redisplay)) { + redisplay(); + } else if(cmd == Th(z_viquotedinsert)) { + *ptr = '^'; + refresh(); + c = getkey(0); + if(c == EOF || !c || len == NAMLEN) + feep(); + else + *ptr++ = c, len++; + } else if(cmd == Th(z_quotedinsert)) { + if((c = getkey(0)) == EOF || !c || len == NAMLEN) + feep(); + else + *ptr++ = c, len++; + } else if(cmd == Th(z_backwarddeletechar) || + cmd == Th(z_vibackwarddeletechar)) { + if (len) + len--, ptr--; + } else if(cmd == Th(z_killregion) || cmd == Th(z_backwardkillword) || + cmd == Th(z_vibackwardkillword)) { + while (len && (len--, *--ptr != '-')); + } else if(cmd == Th(z_killwholeline) || cmd == Th(z_vikillline) || + cmd == Th(z_backwardkillline)) { + len = 0; + ptr = cmdbuf; + } else { + if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) { + Thingy r; + unambiguous: + *ptr = 0; + r = rthingy(cmdbuf); + if (!(r->flags & DISABLED)) { + unrefthingy(r); + statusline = NULL; + selectkeymap(okeymap, 1); + return r; + } + unrefthingy(r); + } + if(cmd == Th(z_selfinsertunmeta)) { + c &= 0x7f; + if(c == '\r') + c = '\n'; + cmd = Th(z_selfinsert); + } + if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist) || + cmd == Th(z_expandorcomplete) || cmd == Th(z_completeword) || + cmd == Th(z_expandorcompleteprefix) || cmd == Th(z_vicmdmode) || + cmd == Th(z_acceptline) || c == ' ' || c == '\t') { + cmdambig = 100; + + HEAPALLOC { + cmdll = newlinklist(); + *ptr = 0; + + scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0); + } LASTALLOC; + if (empty(cmdll)) + feep(); + else if (cmd == Th(z_listchoices) || + cmd == Th(z_deletecharorlist)) { + int zmultsav = zmult; + *ptr = '_'; + statusll = l + len + 1; + zmult = 1; + listlist(cmdll); + zmult = zmultsav; + } else if (!nextnode(firstnode(cmdll))) { + strcpy(ptr = cmdbuf, peekfirst(cmdll)); + ptr += (len = strlen(ptr)); + if(cmd == Th(z_acceptline) || cmd == Th(z_vicmdmode)) + goto unambiguous; + } else { + strcpy(cmdbuf, peekfirst(cmdll)); + ptr = cmdbuf + cmdambig; + *ptr = '_'; + if (isset(AUTOLIST) && + !(isset(LISTAMBIGUOUS) && cmdambig > len)) { + int zmultsav = zmult; + if (isset(LISTBEEP)) + feep(); + statusll = l + cmdambig + 1; + zmult = 1; + listlist(cmdll); + zmult = zmultsav; + } + len = cmdambig; + } + } else { + if (len == NAMLEN || icntrl(c) || cmd != Th(z_selfinsert)) + feep(); + else + *ptr++ = c, len++; + } + } + handlefeep(); + } +} + +/*****************/ +/* Suffix system */ +/*****************/ + +/* + * The completion system sometimes tentatively adds a suffix to a word, + * which can be removed depending on what is inserted next. These + * functions provide the capability to handle a removable suffix. + * + * Any removable suffix consists of characters immediately before the + * cursor. Whether it is removed depends on the next editing action. + * There can be more than one suffix simultaneously present, with + * different actions deleting different numbers of characters. + * + * If the next editing action changes the buffer other than by inserting + * characters, normally the suffix should be removed so as to leave a + * meaningful complete word. The behaviour should be the same if the + * next character inserted is a word separator. If the next character + * reasonably belongs where it is typed, or if the next editing action + * is a deletion, the suffix should not be removed. Other reasons for + * suffix removal may have other behaviour. + * + * In order to maintain a consistent state, after a suffix has been added + * the table *must* be zeroed, one way or another, before the buffer is + * changed. If the suffix is not being removed, call fixsuffix() to + * indicate that it is being permanently fixed. + */ + +/* Length of suffix to remove when inserting each possible character value. * + * suffixlen[256] is the length to remove for non-insertion editing actions. */ + +/**/ +int suffixlen[257]; + +/* Set up suffix: the last n characters are a suffix that should be * + * removed in the usual word end conditions. */ + +/**/ +void +makesuffix(int n) +{ + suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] = n; +} + +/* Set up suffix for parameter names: the last n characters are a suffix * + * that should be removed if the next character is one of the ones that * + * needs to go immediately after the parameter name. br indicates that * + * the name is in braces (${PATH} instead of $PATH), so the extra * + * characters that can only be used in braces are included. */ + +/**/ +void +makeparamsuffix(int br, int n) +{ + if(br || unset(KSHARRAYS)) + suffixlen[':'] = suffixlen['['] = n; + if(br) { + suffixlen['#'] = suffixlen['%'] = suffixlen['?'] = n; + suffixlen['-'] = suffixlen['+'] = suffixlen['='] = n; + /*{*/ suffixlen['}'] = n; + } +} + +/* Remove suffix, if there is one, when inserting character c. */ + +/**/ +void +iremovesuffix(int c) +{ + int sl = suffixlen[c]; + if(sl) { + backdel(sl); + invalidatelist(); + } + fixsuffix(); +} + +/* Fix the suffix in place, if there is one, making it non-removable. */ + +/**/ +void +fixsuffix(void) +{ + memset(suffixlen, 0, sizeof(suffixlen)); +} -- cgit 1.4.1