home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: zle_misc.c,v 2.30 1996/10/15 20:16:35 hzoli Exp $
- *
- * zle_misc.c - miscellaneous editor routines
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1996 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.
- *
- */
-
- #define ZLE
- #include "zsh.h"
-
- /**/
- void
- selfinsert(void)
- {
- int ncs = cs + zmult;
-
- if (complexpect && isset(AUTOPARAMKEYS)) {
- if (complexpect == 2 && /*{*/ c == '}') {
- if (!menucmp || line[cs-1] == '/' || addedsuffix) {
- int i = 0;
- spaceinline(1);
- do {
- line[cs-i] = line[cs-i-1];
- } while (++i < addedsuffix);
- line[cs-i] = c;
- cs++;
- return;
- }
- } else if (c == ':' || c == '[' || (complexpect == 2 &&
- (c == '#' || c == '%' || c == '-' ||
- c == '?' || c == '+' || c == '='))) {
- if (addedsuffix > 1)
- backdel(addedsuffix - 1);
-
- if (!menucmp || line[cs-1] == '/' || addedsuffix) {
- line[cs - 1] = c;
- return;
- }
- }
- }
- if (zmult < 0) {
- zmult = -zmult;
- ncs = cs;
- }
- if (insmode || ll == cs)
- spaceinline(zmult);
- else if (zmult + cs > ll)
- spaceinline(ll - (zmult + cs));
- while (zmult--)
- line[cs++] = c;
- cs = ncs;
- }
-
- /**/
- void
- selfinsertunmeta(void)
- {
- c &= 0x7f;
- if (c == '\r')
- c = '\n';
- selfinsert();
- }
-
- /**/
- void
- deletechar(void)
- {
- if (zmult < 0) {
- zmult = -zmult;
- backwarddeletechar();
- return;
- }
- if (cs + zmult <= ll) {
- cs += zmult;
- backdel(zmult);
- } else
- feep();
- }
-
- /**/
- void
- backwarddeletechar(void)
- {
- if (zmult < 0) {
- zmult = -zmult;
- deletechar();
- return;
- }
- if (zmult > cs)
- zmult = cs;
- backdel(zmult);
- }
-
- /**/
- void
- killwholeline(void)
- {
- int i, fg;
-
- if (zmult < 0)
- return;
- while (zmult--) {
- 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;
-
- if (zmult < 0) {
- zmult = -zmult;
- killline();
- return;
- }
- while (zmult--) {
- 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 neg = zmult < 0;
-
- if (neg)
- zmult = -zmult;
- while (zmult--) {
- 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;
-
- if (zmult < 0) {
- zmult = -zmult;
- backwardkillline();
- return;
- }
- while (zmult--) {
- 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;
-
- if (zmult < 0)
- return;
- if (gotvibufspec)
- buf = &vibuf[vibufspec];
- if (!buf->buf) {
- feep();
- return;
- }
- mark = cs;
- yankb = cs;
- while (zmult--) {
- 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
- 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 (!(lastcmd & ZLE_DIGIT))
- zmult = 0;
- zmult = zmult * 10 + sign * (c & 0xf);
- gotmult = 1;
- }
-
- /**/
- void
- negargument(void)
- {
- if (lastcmd & (ZLE_NEGARG | ZLE_DIGIT))
- feep();
- zmult = -1;
- gotmult = 1;
- }
-
- /**/
- void
- universalargument(void)
- {
- if (!(lastcmd & ZLE_ARG))
- zmult = 4;
- else
- zmult *= 4;
- gotmult = 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
- undo(void)
- {
- char *s;
- struct undoent *ue;
-
- ue = undos + undoct;
- if (!ue->change) {
- feep();
- return;
- }
- line[ll] = '\0';
- s = zalloc(ue->suff + 1);
- memcpy(s, (char *)&line[ll - ue->suff], ue->suff);
- sizeline(ll = ue->pref + ue->suff + ue->len);
- memcpy((char *)line + ue->pref, ue->change, ue->len);
- memcpy((char *)line + ue->pref + ue->len, s, ue->suff);
- zfree(s, ue->suff + 1);
- ue->change = NULL;
- undoct = (undoct + UNDOCT - 1) % UNDOCT;
- cs = ue->cs;
- }
-
- /**/
- 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;
- }
-
- /**/
- 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;
- }
-
- #define NAMLEN 60
-
- /**/
- int
- executenamedcommand(char *prmt)
- {
- int len, cmd, t0, l = strlen(prmt);
- char *ptr, *buf = halloc(l + NAMLEN + 2);
- int *obindtab = bindtab;
-
- strcpy(buf, prmt);
- statusline = buf;
- bindtab = mainbindtab;
- ptr = buf += l;
- len = 0;
- for (;;) {
- *ptr = '_';
- statusll = l + len + 1;
- refresh();
- if ((cmd = getkeycmd()) < 0 || cmd == z_sendbreak) {
- statusline = NULL;
- bindtab = obindtab;
- return -1;
- }
- switch (cmd) {
- case z_sendstring:
- sendstring();
- break;
- case z_clearscreen:
- clearscreen();
- break;
- case z_redisplay:
- redisplay();
- break;
- case z_viquotedinsert:
- *ptr = '^';
- refresh();
- c = getkey(0);
- if(c == EOF || !c || len == NAMLEN)
- feep();
- else
- *ptr++ = c, len++;
- break;
- case z_quotedinsert:
- if((c = getkey(0)) == EOF || !c || len == NAMLEN)
- feep();
- else
- *ptr++ = c, len++;
- break;
- case z_backwarddeletechar:
- case z_vibackwarddeletechar:
- if (len)
- len--, ptr--;
- break;
- case z_killregion:
- case z_backwardkillword:
- case z_vibackwardkillword:
- while (len && (len--, *--ptr != '-'));
- break;
- case z_killwholeline:
- case z_vikillline:
- case z_backwardkillline:
- len = 0;
- ptr = buf;
- break;
- case z_acceptline:
- case z_vicmdmode:
- unambiguous:
- *ptr = 0;
- for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
- if (!strcmp(buf, zlecmds[t0].name))
- break;
- if (t0 != ZLECMDCOUNT) {
- statusline = NULL;
- bindtab = obindtab;
- return t0;
- }
- /* fall through */
- default:
- if(cmd == z_selfinsertunmeta) {
- c &= 0x7f;
- if(c == '\r')
- c = '\n';
- cmd = z_selfinsert;
- }
- if (cmd == z_listchoices || cmd == z_deletecharorlist ||
- cmd == z_expandorcomplete || cmd == z_expandorcompleteprefix ||
- cmd == z_completeword || cmd == z_vicmdmode ||
- cmd == z_acceptline || c == ' ' || c == '\t') {
- LinkList cmdll;
- int ambig = 100;
-
- HEAPALLOC {
- cmdll = newlinklist();
- *ptr = 0;
- for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
- if (strpfx(buf, zlecmds[t0].name)) {
- int xx;
-
- addlinknode(cmdll, zlecmds[t0].name);
- xx = pfxlen(peekfirst(cmdll), zlecmds[t0].name);
- if (xx < ambig)
- ambig = xx;
- }
- } LASTALLOC;
- if (empty(cmdll))
- feep();
- else if (cmd == z_listchoices || cmd == z_deletecharorlist) {
- int zmultsav = zmult;
- *ptr = '_';
- statusll = l + len + 1;
- zmult = 1;
- listlist(cmdll);
- zmult = zmultsav;
- } else if (!nextnode(firstnode(cmdll))) {
- strcpy(ptr = buf, peekfirst(cmdll));
- ptr += (len = strlen(ptr));
- if(cmd == z_acceptline || cmd == z_vicmdmode)
- goto unambiguous;
- } else {
- strcpy(buf, peekfirst(cmdll));
- ptr = buf + ambig;
- *ptr = '_';
- if (isset(AUTOLIST) &&
- !(isset(LISTAMBIGUOUS) && ambig > len)) {
- int zmultsav = zmult;
- if (isset(LISTBEEP))
- feep();
- statusll = l + ambig + 1;
- zmult = 1;
- listlist(cmdll);
- zmult = zmultsav;
- }
- len = ambig;
- }
- } else {
- if (len == NAMLEN || icntrl(c) || cmd != z_selfinsert)
- feep();
- else
- *ptr++ = c, len++;
- }
- }
- }
- }
-
- static char *bp;
- static char *truncstr;
- static int dontcount, lensb, trunclen;
-
- /* stradd() adds a string to the prompt, in a *
- * visible representation, doing truncation. */
-
- /**/
- void
- stradd(char *d)
- {
- /* dlen is the full length of the string we want to add */
- int dlen = nicestrlen(d);
- char *ps, *pd, *pc, *t;
- int tlen, maxlen;
- addbufspc(dlen);
- /* This loop puts the nice representation of the string into the prompt *
- * buffer. It might be modified later. Note that bp isn't changed. */
- for(ps=d, pd=bp; *ps; ps++)
- for(pc=nicechar(STOUC(*ps)); *pc; pc++)
- *pd++ = *pc;
- if(!trunclen || dlen <= trunclen) {
- /* No truncation is needed, so update bp and return, *
- * leaving the full string in the prompt. */
- bp += dlen;
- return;
- }
- /* We need to truncate. t points to the truncation string -- which is *
- * inserted literally, without nice representation. tlen is its *
- * length, and maxlen is the amout of the main string that we want to *
- * keep. Note that if the truncation string is longer than the *
- * truncation length (tlen > trunclen), the truncation string is used *
- * in full. */
- t = truncstr + 1;
- tlen = strlen(t);
- maxlen = tlen < trunclen ? trunclen - tlen : 0;
- addbufspc(tlen);
- if(*truncstr == '>') {
- /* '>' means truncate at the right. We just move past the first *
- * maxlen characters of the string, and write the truncation *
- * string there. */
- bp += maxlen;
- while(*t)
- pputc(*t++);
- } else {
- /* Truncation at the left: ps is initialised to the start of the *
- * part of the string that we want to keep. pc points to the *
- * end of the string. The truncation string is added to the *
- * prompt, then the desired part of the string is copied into *
- * the right place. */
- ps = bp + dlen - maxlen;
- pc = bp + dlen;
- while(*t)
- pputc(*t++);
- while(ps < pc)
- *bp++ = *ps++;
- }
- }
-
- /**/
- int
- putstr(int d)
- {
- addbufspc(1);
- *bp++ = d;
- if (!dontcount)
- lensb++;
- return 0;
- }
-
- /**/
- void
- tsetcap(int cap, int flag)
- {
- if (!(termflags & TERM_SHORT) && tcstr[cap]) {
- switch(flag) {
- case -1:
- tputs(tcstr[cap], 1, putraw);
- break;
- case 0:
- tputs(tcstr[cap], 1, putshout);
- break;
- case 1:
- if (!dontcount) {
- int t0;
-
- if (cap == TCSTANDOUTBEG || cap == TCSTANDOUTEND)
- t0 = tgetnum("sg");
- else if (cap == TCUNDERLINEBEG || cap == TCUNDERLINEEND)
- t0 = tgetnum("ug");
- else
- t0 = 0;
- if (t0 > 0)
- lensb -= t0;
- }
- tputs(tcstr[cap], 1, putstr);
- break;
- }
-
- if (txtisset(TXTDIRTY)) {
- txtunset(TXTDIRTY);
- if (txtisset(TXTBOLDFACE) && cap != TCBOLDFACEBEG)
- tsetcap(TCBOLDFACEBEG, flag);
- if (txtisset(TXTSTANDOUT))
- tsetcap(TCSTANDOUTBEG, flag);
- if (txtisset(TXTUNDERLINE))
- tsetcap(TCUNDERLINEBEG, flag);
- }
- }
- }
-
- /* get a prompt string */
-
- static char *buf, *bp1, *bl0, *fm, *pmpt;
- static int bracepos, bufspc, pmpth;
-
- /**/
- char *
- putprompt(char *fmin, int *lenp, int *wp, int cnt)
- {
- if (!fmin) {
- *lenp = 0;
- if (wp)
- *wp = 0;
- return ztrdup("");
- }
- pmpth = 1;
-
- if ((termflags & TERM_UNKNOWN) && (unset(INTERACTIVE)))
- init_term();
-
- bracepos = -1;
- fm = fmin;
- lensb = 0;
- pmpt = (dontcount = !cnt) ? NULL : fm;
- bp = bl0 = buf = zalloc(bufspc = 256);
- bp1 = NULL;
-
- clearerr(stdin);
-
- trunclen = 0;
- putpromptchar(1, '\0');
-
- *lenp = bp - buf;
- if (wp) {
- *wp = bp - bl0 - lensb;
- if (pmpt != rpmpt) {
- *wp %= columns;
- if (*wp == columns - 1) {
- addbufspc(1);
- *wp = 0;
- *bp++ = ' ';
- ++*lenp;
- pmpth++;
- }
- if (!*wp && *lenp) {
- addbufspc(1);
- (*wp)++;
- *bp++ = ' ';
- ++*lenp;
- }
- }
- }
- if (pmpt == lpmpt)
- lppth = pmpth;
-
- return buf;
- }
-
- /**/
- int
- putpromptchar(int doprint, int endchar)
- {
- char buf3[PATH_MAX], *ss;
- int t0, arg, test, sep;
- struct tm *tm;
- time_t timet;
- Nameddir nd;
-
- if (isset(PROMPTSUBST)) {
- int olderr = errflag;
-
- HEAPALLOC {
- fm = dupstring(fm);
- if (!parsestr(fm))
- singsub(&fm);
- } LASTALLOC;
- /* Ignore errors in prompt substitution */
- errflag = olderr;
- }
- for (; *fm && *fm != endchar; fm++) {
- arg = 0;
- if (*fm == '%') {
- if (idigit(*++fm)) {
- arg = zstrtol(fm, &fm, 10);
- }
- if (*fm == '(') {
- int tc;
-
- if (idigit(*++fm)) {
- arg = zstrtol(fm, &fm, 10);
- }
- test = 0;
- ss = pwd;
- switch (tc = *fm) {
- case 'c':
- case '.':
- case '~':
- if ((nd = finddir(ss))) {
- arg--;
- ss += strlen(nd->dir);
- }
- case '/':
- case 'C':
- for (; *ss; ss++)
- if (*ss == '/')
- arg--;
- if (arg <= 0)
- test = 1;
- break;
- case 't':
- case 'T':
- case 'd':
- case 'D':
- case 'w':
- timet = time(NULL);
- tm = localtime(&timet);
- switch (tc) {
- case 't':
- test = (arg == tm->tm_min);
- break;
- case 'T':
- test = (arg == tm->tm_hour);
- break;
- case 'd':
- test = (arg == tm->tm_mday);
- break;
- case 'D':
- test = (arg == tm->tm_mon);
- break;
- case 'w':
- test = (arg == tm->tm_wday);
- break;
- }
- break;
- case '?':
- if (lastval == arg)
- test = 1;
- break;
- case '#':
- if (geteuid() == arg)
- test = 1;
- break;
- case 'g':
- if (getegid() == arg)
- test = 1;
- break;
- case 'L':
- if (shlvl >= arg)
- test = 1;
- break;
- case 'S':
- if (time(NULL) - shtimer.tv_sec >= arg)
- test = 1;
- break;
- case 'v':
- if (arrlen(psvar) >= arg)
- test = 1;
- break;
- case '_':
- test = (cmdsp >= arg);
- break;
- default:
- test = -1;
- break;
- }
- if (!*fm || !(sep = *++fm))
- return 0;
- fm++;
- if (!putpromptchar(test == 1 && doprint, sep) || !*++fm ||
- !putpromptchar(test == 0 && doprint, ')')) {
- return 0;
- }
- continue;
- }
- if (!doprint)
- switch(*fm) {
- case '[':
- while(idigit(*++fm));
- while(*++fm != ']');
- continue;
- case '<':
- while(*++fm != '<');
- continue;
- case '>':
- while(*++fm != '>');
- continue;
- case 'D':
- if(fm[1]=='{')
- while(*++fm != '}');
- continue;
- default:
- continue;
- }
- switch (*fm) {
- case '~':
- if ((nd = finddir(pwd))) {
- sprintf(buf3, "~%s%s", nd->nam, pwd + strlen(nd->dir));
- stradd(buf3);
- break;
- }
- case 'd':
- case '/':
- stradd(pwd);
- break;
- case 'c':
- case '.':
- if ((nd = finddir(pwd)))
- sprintf(buf3, "~%s%s", nd->nam, pwd + strlen(nd->dir));
- else
- strcpy(buf3, pwd);
- if (!arg)
- arg++;
- for (ss = buf3 + strlen(buf3); ss > buf3; ss--)
- if (*ss == '/' && !--arg) {
- ss++;
- break;
- }
- if (*ss == '/' && ss[1] && (ss != buf3))
- ss++;
- stradd(ss);
- break;
- case 'C':
- strcpy(buf3, pwd);
- if (!arg)
- arg++;
- for (ss = buf3 + strlen(buf3); ss > buf3; ss--)
- if (*ss == '/' && !--arg) {
- ss++;
- break;
- }
- if (*ss == '/' && ss[1] && (ss != buf3))
- ss++;
- stradd(ss);
- break;
- case 'h':
- case '!':
- addbufspc(DIGBUFSIZE);
- sprintf(bp, "%d", curhist);
- bp += strlen(bp);
- break;
- case 'M':
- stradd(hostnam);
- break;
- case 'm':
- if (!arg)
- arg++;
- for (ss = hostnam; *ss; ss++)
- if (*ss == '.' && !--arg)
- break;
- t0 = *ss;
- *ss = '\0';
- stradd(hostnam);
- *ss = t0;
- break;
- case 'S':
- txtchangeset(TXTSTANDOUT, TXTNOSTANDOUT);
- txtset(TXTSTANDOUT);
- tsetcap(TCSTANDOUTBEG, 1);
- break;
- case 's':
- txtchangeset(TXTNOSTANDOUT, TXTSTANDOUT);
- txtset(TXTDIRTY);
- txtunset(TXTSTANDOUT);
- tsetcap(TCSTANDOUTEND, 1);
- break;
- case 'B':
- txtchangeset(TXTBOLDFACE, TXTNOBOLDFACE);
- txtset(TXTDIRTY);
- txtset(TXTBOLDFACE);
- tsetcap(TCBOLDFACEBEG, 1);
- break;
- case 'b':
- txtchangeset(TXTNOBOLDFACE, TXTBOLDFACE);
- txtchangeset(TXTNOSTANDOUT, TXTSTANDOUT);
- txtchangeset(TXTNOUNDERLINE, TXTUNDERLINE);
- txtset(TXTDIRTY);
- txtunset(TXTBOLDFACE);
- tsetcap(TCALLATTRSOFF, 1);
- break;
- case 'U':
- txtchangeset(TXTUNDERLINE, TXTNOUNDERLINE);
- txtset(TXTUNDERLINE);
- tsetcap(TCUNDERLINEBEG, 1);
- break;
- case 'u':
- txtchangeset(TXTNOUNDERLINE, TXTUNDERLINE);
- txtset(TXTDIRTY);
- txtunset(TXTUNDERLINE);
- tsetcap(TCUNDERLINEEND, 1);
- break;
- case '[':
- if (idigit(*++fm))
- trunclen = zstrtol(fm, &fm, 10);
- else
- trunclen = arg;
- if (trunclen) {
- bp1 = bp;
- while (*fm && *fm != ']') {
- if (*fm == '\\' && fm[1])
- ++fm;
- addbufspc(1);
- *bp++ = *fm++;
- }
- addbufspc(2);
- if (bp1 == bp)
- *bp++ = '<';
- *bp = '\0';
- zsfree(truncstr);
- truncstr = ztrdup(bp = bp1);
- bp1 = NULL;
- } else {
- while (*fm && *fm != ']') {
- if (*fm == '\\' && fm[1])
- fm++;
- fm++;
- }
- }
- if(!*fm)
- return 0;
- break;
- case '<':
- case '>':
- if((trunclen = arg)) {
- bp1 = bp;
- addbufspc(1);
- *bp++ = *fm++;
- while (*fm && *fm != *bp1) {
- if (*fm == '\\' && fm[1])
- ++fm;
- addbufspc(1);
- *bp++ = *fm++;
- }
- addbufspc(1);
- *bp = '\0';
- zsfree(truncstr);
- truncstr = ztrdup(bp = bp1);
- bp1 = NULL;
- } else {
- char ch = *fm++;
- while(*fm && *fm != ch) {
- if (*fm == '\\' && fm[1])
- fm++;
- fm++;
- }
- }
- if(!*fm)
- return 0;
- break;
- case '{':
- if (!dontcount++)
- bracepos = bp - buf;
- break;
- case '}':
- if (!--dontcount && bracepos != -1) {
- lensb += (bp - buf) - bracepos;
- bracepos = -1;
- }
- break;
- case 't':
- case '@':
- case 'T':
- case '*':
- case 'w':
- case 'W':
- case 'D':
- {
- char *tmfmt, *dd;
-
- switch (*fm) {
- case 'T':
- tmfmt = "%k:%M";
- break;
- case '*':
- tmfmt = "%k:%M:%S";
- break;
- case 'w':
- tmfmt = "%a %e";
- break;
- case 'W':
- tmfmt = "%m/%d/%y";
- break;
- case 'D':
- tmfmt = "%y-%m-%d";
- if (fm[1] == '{') {
- for (ss = fm + 2, dd = buf3; *ss && *ss != '}'; ++ss, ++dd)
- *dd = *((*ss == '\\' && ss[1]) ? ++ss : ss);
- if (*ss == '}') {
- *dd = '\0';
- fm = ss;
- tmfmt = buf3;
- }
- }
- break;
- default:
- tmfmt = "%l:%M%p";
- break;
- }
- timet = time(NULL);
- tm = localtime(&timet);
- addbufspc(80); /* 80 is arbitrary :-( */
- ztrftime(bp, 79, tmfmt, tm);
- if (*bp == ' ')
- chuck(bp);
- bp += strlen(bp);
- break;
- }
- case 'n':
- stradd(get_username());
- break;
- case 'l':
- if (*ttystrname) {
- ss = (strncmp(ttystrname, "/dev/tty", 8) ?
- ttystrname + 5 : ttystrname + 8);
- stradd(ss);
- } else
- stradd("()");
- break;
- case '?':
- addbufspc(DIGBUFSIZE);
- sprintf(bp, "%ld", (long)lastval);
- bp += strlen(bp);
- break;
- case '%':
- addbufspc(1);
- *bp++ = '%';
- break;
- case ')':
- addbufspc(1);
- *bp++ = ')';
- break;
- case '#':
- addbufspc(1);
- *bp++ = (geteuid())? '%' : '#';
- break;
- case 'v':
- if (!arg)
- arg = 1;
- if (arrlen(psvar) >= arg)
- stradd(psvar[arg - 1]);
- break;
- case 'E':
- tsetcap(TCCLEAREOL, 1);
- break;
- case '_':
- if (cmdsp) {
- if (arg > cmdsp || arg <= 0)
- arg = cmdsp;
- for (t0 = cmdsp - arg; arg--; t0++) {
- stradd(cmdnames[cmdstack[t0]]);
- if (arg) {
- addbufspc(1);
- *bp++=' ';
- }
- }
- }
- break;
- case 'r':
- if (pmpt == sprompt) {
- stradd(rstring);
- break;
- }
- case 'R':
- if (pmpt == sprompt) {
- stradd(Rstring);
- break;
- }
- case '\0':
- return 0;
- default:
- addbufspc(2);
- *bp++ = '%';
- pputc(*fm);
- break;
- }
- } else if (doprint) {
- addbufspc(1);
- pputc(*fm == Meta ? *++fm ^ 32 : *fm);
- }
- }
-
- return *fm;
- }
-
- /**/
- void
- pputc(char c)
- {
- if (!dontcount) {
- if (pmpt == rpmpt) {
- if (c == '\t' || c == '\n')
- c = ' ';
- } else if (c == '\t') {
- int t0 = 7 - (7 & (bp - bl0 - lensb));
- lensb -= t0;
- } else if (c == '\n') {
- *bp++ = c;
- bl0 = bp;
- lensb = 0;
- pmpth++;
- return;
- }
- }
- if (bp - bl0 == columns)
- pmpth++;
- *bp++ = c;
- }
-
- /**/
- void
- addbufspc(int need)
- {
- if((bp - buf) + need > bufspc) {
- char *oldbuf = buf;
- if(need & 255)
- need = (need | 255) + 1;
- buf = realloc(buf, bufspc += need);
- bp = buf + (bp - oldbuf);
- bl0 = buf + (bl0 - oldbuf);
- if(bp1)
- bp1 = buf + (bp1 - oldbuf);
- }
- }
-