home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / z / zsh220.zip / zsh2.2 / src / zle_misc.c < prev    next >
C/C++ Source or Header  |  1992-05-07  |  15KB  |  830 lines

  1. /*
  2.  *
  3.  * zle_misc.c - miscellaneous editor routines
  4.  *
  5.  * This file is part of zsh, the Z shell.
  6.  *
  7.  * This software is Copyright 1992 by Paul Falstad
  8.  *
  9.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  10.  * use this software as long as: there is no monetary profit gained
  11.  * specifically from the use or reproduction of this software, it is not
  12.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  13.  * included prominently in any copy made. 
  14.  *
  15.  * The author make no claims as to the fitness or correctness of this software
  16.  * for any use whatsoever, and it is provided as is. Any use of this software
  17.  * is at the user's own risk. 
  18.  *
  19.  */
  20.  
  21. #define ZLE
  22. #include "zsh.h"
  23.  
  24.  
  25. void selfinsert() /**/
  26. {
  27. int ncs = cs+mult;
  28.  
  29.     if (mult < 0) { mult = -mult; ncs = cs; }
  30.     if (insmode || ll == cs)
  31.         spaceinline(mult);
  32.     else if (mult+cs > ll)
  33.         spaceinline(ll-(mult+cs));
  34.     while (mult--)
  35.         line[cs++] = c;
  36.     cs = ncs;
  37. }
  38.  
  39. void selfinsertunmeta() /**/
  40. {
  41.     c &= 0x7f;
  42.     if (c == '\r') c = '\n';
  43.     selfinsert();
  44. }
  45.  
  46. void deletechar() /**/
  47. {
  48.     if (mult < 0) { mult = -mult; backwarddeletechar(); return; }
  49.     if (c == 4 && !ll)
  50.         {
  51.         eofsent = 1;
  52.         return;
  53.         }
  54.     if (!(cs+mult > ll || line[cs] == '\n'))
  55.         {
  56.         cs += mult;
  57.         backdel(mult);
  58.         }
  59.     else
  60.         feep();
  61. }
  62.  
  63. void backwarddeletechar() /**/
  64. {
  65.     if (mult < 0) { mult = -mult; deletechar(); return; }
  66.     if (mult > cs)
  67.         mult = cs;
  68.     backdel(mult);
  69. }
  70.  
  71. void videletechar() /**/
  72. {
  73.     if (mult < 0) { mult = -mult; vibackwarddeletechar(); return; }
  74.     if (c == 4 && !ll) {
  75.         eofsent = 1;
  76.         return;
  77.     }
  78.     if (!(cs+mult > ll || line[cs] == '\n')) {
  79.         cs += mult;
  80.         backkill(mult,0);
  81.         if (cs && (cs == ll || line[cs] == '\n')) cs--;
  82.     } else
  83.         feep();
  84. }
  85.  
  86. void vibackwarddeletechar() /**/
  87. {
  88.     if (mult < 0) { mult = -mult; videletechar(); return; }
  89.     if (mult > cs)
  90.         mult = cs;
  91.     if (cs-mult < viinsbegin) { feep(); return; }
  92.     backkill(mult,1);
  93. }
  94.  
  95. void vikillline() /**/
  96. {
  97.     if (viinsbegin > cs) { feep(); return; }
  98.     backdel(cs-viinsbegin);
  99. }
  100.  
  101. void killwholeline() /**/
  102. {
  103. int i,fg;
  104.  
  105.     if (mult < 0) return;
  106.     while (mult--)
  107.         {
  108.         if (fg = (cs && cs == ll))
  109.             cs--;
  110.         while (cs && line[cs-1] != '\n') cs--;
  111.         for (i = cs; i != ll && line[i] != '\n'; i++);
  112.         forekill(i-cs+(i != ll),fg);
  113.         }
  114. }
  115.  
  116. void killbuffer() /**/
  117. {
  118.     cs = 0;
  119.     forekill(ll,0);
  120. }
  121.  
  122. void backwardkillline() /**/
  123. {
  124. int i = 0;
  125.  
  126.     if (mult < 0) { mult = -mult; killline(); return; }
  127.     while (mult--)
  128.         {
  129.         while (cs && line[cs-1] != '\n') cs--,i++;
  130.         if (mult && cs && line[cs-1] == '\n')
  131.             cs--,i++;
  132.         }
  133.     forekill(i,1);
  134. }
  135.  
  136. void gosmacstransposechars() /**/
  137. {
  138. int cc;
  139.  
  140.     if (cs < 2 || line[cs-1] == '\n' || line[cs-2] == '\n')
  141.         {
  142.         if (line[cs] == '\n' || line[cs+1] == '\n')
  143.             {
  144.             feep();
  145.             return;
  146.             }
  147.         cs += (cs == 0 || line[cs-1] == '\n') ? 2 : 1;
  148.         }
  149.     cc = line[cs-2];
  150.     line[cs-2] = line[cs-1];
  151.     line[cs-1] = cc;
  152. }
  153.  
  154. void transposechars() /**/
  155. {
  156. int cc;
  157. int neg = mult < 0;
  158.  
  159.     if (neg) mult = -mult;
  160.     while (mult--) {
  161.         if (cs == 0 || line[cs-1] == '\n') {
  162.             if (ll == cs || line[cs] == '\n' || line[cs+1] == '\n') {
  163.                 feep();
  164.                 return;
  165.             }
  166.             cs++;
  167.         }
  168.         if (!neg) {
  169.             if (cs != ll && line[cs] != '\n') cs++;
  170.         } else {
  171.             if (cs != 0 && line[cs-1] != '\n') cs--;
  172.         }
  173.         cc = line[cs-2];
  174.         line[cs-2] = line[cs-1];
  175.         line[cs-1] = cc;
  176.     }
  177. }
  178.  
  179. void poundinsert() /**/
  180. {
  181.     if (*line != '#') {
  182.         cs = 0;
  183.         spaceinline(1);
  184.         *line = '#';
  185.     } else {
  186.         cs = 0;
  187.         foredel(1);
  188.     }
  189.     done = 1;
  190. }
  191.  
  192. void acceptline() /**/
  193. {
  194.     done = 1;
  195. }
  196.  
  197. void acceptandhold() /**/
  198. {
  199.     pushnode(bufstack,ztrdup((char *) line));
  200.     stackcs = cs;
  201.     done = 1;
  202. }
  203.  
  204. void killline() /**/
  205. {
  206. int i = 0;
  207.  
  208.     if (mult < 0) { mult = -mult; backwardkillline(); return; }
  209.     while (mult--) {
  210.         if (line[cs] == '\n')
  211.             cs++,i++;
  212.         while (cs != ll && line[cs] != '\n') cs++,i++;
  213.     }
  214.     backkill(i,0);
  215. }
  216.  
  217. void killregion() /**/
  218. {
  219.     if (mark > ll)
  220.         mark = ll;
  221.     if (mark > cs)
  222.         forekill(mark-cs,0);
  223.     else
  224.         backkill(cs-mark,1);
  225. }
  226.  
  227. void copyregionaskill() /**/
  228. {
  229.     if (mark > ll)
  230.         mark = ll;
  231.     if (mark > cs)
  232.         cut(cs,mark-cs,0);
  233.     else
  234.         cut(mark,cs-mark,1);
  235. }
  236.  
  237. static int kct,yankb,yanke;
  238.  
  239. void yank() /**/
  240. {
  241. int cc;
  242. char *buf = cutbuf;
  243.  
  244.     if (!cutbuf) {
  245.         feep();
  246.         return;
  247.     }
  248.     if (mult < 0) return;
  249.     if (vibufspec) {
  250.         vibufspec = tolower(vibufspec);
  251.         vibufspec += (idigit(vibufspec)) ? -'1'+26 : -'a';
  252.         if (!(buf = vibuf[vibufspec])) {
  253.             feep();
  254.             vibufspec = 0;
  255.             return;
  256.         }
  257.         vibufspec = 0;
  258.     }
  259.     yankb = cs;
  260.     while (mult--) {
  261.         kct = kringnum;
  262.         cc = strlen(buf);
  263.         spaceinline(cc);
  264.         strncpy((char *) line+cs,buf,cc);
  265.         cs += cc;
  266.         yanke = cs;
  267.     }
  268. }
  269.  
  270. void viputafter() /**/
  271. {
  272. int cc;
  273. char *buf = cutbuf;
  274.  
  275.     if (!cutbuf) {
  276.         feep();
  277.         return;
  278.     }
  279.     if (mult < 0) return;
  280.     if (vibufspec) {
  281.         vibufspec = tolower(vibufspec);
  282.         vibufspec += (idigit(vibufspec)) ? -'1'+26 : -'a';
  283.         if (!(buf = vibuf[vibufspec])) {
  284.             feep();
  285.             vibufspec = 0;
  286.             return;
  287.         }
  288.         vibufspec = 0;
  289.     }
  290.     if (strchr(buf,'\n')) {
  291.         cs = findeol();
  292.         if (cs == ll) { spaceinline(1); line[cs] = '\n'; }
  293.     }
  294.     if (cs != ll) cs++;
  295.     yankb = cs;
  296.     while (mult--) {
  297.         kct = kringnum;
  298.         cc = strlen(buf);
  299.         spaceinline(cc);
  300.         strncpy((char *) line+cs,buf,cc);
  301.         cs += cc;
  302.         yanke = cs;
  303.     }
  304.     cs = yankb;
  305. }
  306.  
  307. void yankpop() /**/
  308. {
  309. int cc;
  310.  
  311.     if (!(lastcmd & ZLE_YANK) || !kring[kct]) {
  312.         feep();
  313.         return;
  314.     }
  315.     cs = yankb;
  316.     foredel(yanke-yankb);
  317.     cc = strlen(kring[kct]);
  318.     spaceinline(cc);
  319.     strncpy((char *) line+cs,kring[kct],cc);
  320.     cs += cc;
  321.     yanke = cs;
  322.     kct = (kct-1) & (KRINGCT-1);
  323. }
  324.  
  325. void overwritemode() /**/
  326. {
  327.     insmode ^= 1;
  328. }
  329.  
  330. void undefinedkey() /**/
  331. {
  332.     feep();
  333. }
  334.  
  335. void quotedinsert() /**/
  336. {
  337. #ifndef TIO
  338. struct sgttyb sob;
  339.     sob = shttyinfo.sgttyb;
  340.     sob.sg_flags = (sob.sg_flags|RAW) & ~ECHO;
  341.     ioctl(SHTTY,TIOCSETN,&sob);
  342. #endif
  343.     c = getkey(0);
  344. #ifndef TIO
  345.     setterm();
  346. #endif
  347.     if (c) selfinsert(); else feep();
  348. }
  349.  
  350. void digitargument() /**/
  351. {
  352.     if (!(lastcmd & ZLE_ARG))
  353.         mult = 0;
  354.     mult = mult*10+(c&0xf);
  355.     if (lastcmd & ZLE_NEGARG) mult = -mult;
  356. }
  357.  
  358. void negargument() /**/
  359. {
  360.     if (lastcmd & ZLE_ARG) feep();
  361. }
  362.  
  363. void universalargument() /**/
  364. {
  365.     if (!(lastcmd & ZLE_ARG))
  366.         mult = 4;
  367.     else
  368.         mult *= 4;
  369. }
  370.  
  371. void copyprevword() /**/
  372. {
  373. int len,t0;
  374.  
  375.     for (t0 = cs-1; t0 >= 0; t0--)
  376.         if (iword(line[t0]))
  377.             break;
  378.     for (; t0 >= 0; t0--)
  379.         if (!iword(line[t0]))
  380.             break;
  381.     if (t0)
  382.         t0++;
  383.     len = cs-t0;
  384.     spaceinline(len);
  385.     strncpy((char *) line+cs,(char *) line+t0,len);
  386.     cs += len;
  387. }
  388.  
  389. void sendbreak() /**/
  390. {
  391.     errflag = done = 1;
  392. }
  393.  
  394. void undo() /**/
  395. {
  396. char *s;
  397. struct undoent *ue;
  398.  
  399.     ue = undos+undoct;
  400.     if (!ue->change)
  401.         {
  402.         feep();
  403.         return;
  404.         }
  405.     line[ll] = '\0';
  406.     s = ztrdup((char *) line+ll-ue->suff);
  407.     sizeline((ll = ue->pref+ue->suff+ue->len)+1);
  408.     strncpy((char *) line+ue->pref,ue->change,ue->len);
  409.     strcpy((char *) line+ue->pref+ue->len,s);
  410.     free(s);
  411.     ue->change = NULL;
  412.     undoct = (undoct-1) & (UNDOCT-1);
  413.     cs = ue->cs;
  414. }
  415.  
  416. void quoteregion() /**/
  417. {
  418. char *s,*t;
  419. int x,y;
  420.  
  421.     if (mark > ll)
  422.         mark = ll;
  423.     if (mark < cs)
  424.         {
  425.         x = mark;
  426.         mark = cs;
  427.         cs = x;
  428.         }
  429.     s = hcalloc((y = mark-cs)+1);
  430.     strncpy(s,(char *) line+cs,y);
  431.     s[y] = '\0';
  432.     foredel(mark-cs);
  433.     t = makequote(s);
  434.     spaceinline(x = strlen(t));
  435.     strncpy((char *) line+cs,t,x);
  436.     mark = cs;
  437.     cs += x;
  438. }
  439.  
  440. void quoteline() /**/
  441. {
  442. char *s;
  443.  
  444.     line[ll] = '\0';
  445.     s = makequote((char *) line);
  446.     setline(s);
  447. }
  448.  
  449. char *makequote(s) /**/
  450. char *s;
  451. {
  452. int qtct = 0;
  453. char *l,*ol;
  454.  
  455.     for (l = s; *l; l++)
  456.         if (*l == '\'')
  457.             qtct++;
  458.     l = ol = halloc((qtct*3)+3+strlen(s));
  459.     *l++ = '\'';
  460.     for (; *s; s++)
  461.         if (*s == '\'')
  462.             {
  463.             *l++ = '\'';
  464.             *l++ = '\\';
  465.             *l++ = '\'';
  466.             *l++ = '\'';
  467.             }
  468.         else
  469.             *l++ = *s;
  470.     *l++ = '\'';
  471.     *l = '\0';
  472.     return ol;
  473. }
  474.  
  475. #define NAMLEN 70
  476.  
  477. int executenamedcommand() /**/
  478. {
  479. char buf[NAMLEN],*ptr;
  480. int len,ch,t0;
  481.  
  482.     strcpy(buf,"execute: ");
  483.     ptr = buf+9;
  484.     len = 0;
  485.     statusline = buf;
  486.     refresh();
  487.     for (;ch = getkey(1);refresh())
  488.         {
  489.         switch (ch)
  490.             {
  491.             case 8: case 127:
  492.                 if (len)
  493.                     {
  494.                     len--;
  495.                     *--ptr = '\0';
  496.                     }
  497.                 break;
  498.             case 23:
  499.                 while (len && (len--, *--ptr != '-'))
  500.                     *ptr = '\0';
  501.                 break;
  502.             case 21:
  503.                 len = 0;
  504.                 ptr = buf+9;
  505.                 *ptr = '\0';
  506.                 break;
  507.             case 10: case 13: goto brk;
  508.             case 7: case -1: statusline = NULL; return z_undefinedkey;
  509.             case 9: case 32:
  510.                 {
  511.                 Lklist ll;
  512.                 int ambig = 100;
  513.  
  514.                 heapalloc();
  515.                 ll = newlist();
  516.                 for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
  517.                     if (strpfx(buf+9,zlecmds[t0].name))
  518.                         {
  519.                         int xx;
  520.  
  521.                         addnode(ll,zlecmds[t0].name);
  522.                         xx = pfxlen(peekfirst(ll),zlecmds[t0].name);
  523.                         if (xx < ambig)
  524.                             ambig = xx;
  525.                         }
  526.                 permalloc();
  527.                 if (!full(ll))
  528.                     feep();
  529.                 else if (!nextnode(firstnode(ll)))
  530.                     {
  531.                     strcpy(buf+9,peekfirst(ll));
  532.                     ptr = buf+(len = strlen(buf));
  533.                     }
  534.                 else
  535.                     {
  536.                     strcpy(buf+9,peekfirst(ll));
  537.                     len = ambig;
  538.                     ptr = buf+9+len;
  539.                     *ptr = '\0';
  540.                     feep();
  541.                     listmatches(ll,NULL);
  542.                     }
  543.                 break;
  544.                 }
  545.             default:
  546.                 if (len == NAMLEN-10 || icntrl(ch))
  547.                     feep();
  548.                 else
  549.                     *ptr++ = ch, *ptr = '\0', len++;
  550.                 break;
  551.             }
  552.         }
  553. brk:
  554.     statusline = NULL;
  555.     ptr = buf+9;
  556.     for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
  557.         if (!strcmp(ptr,zlecmds[t0].name))
  558.             break;
  559.     if (t0 != ZLECMDCOUNT)
  560.         return lastnamed = t0;
  561.     else
  562.         return z_undefinedkey;
  563. }
  564.  
  565. void vijoin() /**/
  566. {
  567. int x;
  568.  
  569.     if ((x = findeol()) == ll)
  570.         {
  571.         feep();
  572.         return;
  573.         }
  574.     cs = x+1;
  575.     for (x = 1; cs != ll && iblank(line[cs]); cs++,x++);
  576.     backdel(x);
  577.     spaceinline(1);
  578.     line[cs] = ' ';
  579. }
  580.  
  581. void viswapcase() /**/
  582. {
  583.     if (cs < ll)
  584.         {
  585.         int ch = line[cs];
  586.  
  587.         if (islower(ch))
  588.             ch = tuupper(ch);
  589.         else if (isupper(ch))
  590.             ch = tulower(ch);
  591.         line[cs++] = ch;
  592.         }
  593. }
  594.  
  595. void vicapslockpanic() /**/
  596. {
  597. char ch;
  598.  
  599.     statusline = "press a lowercase key to continue";
  600.     refresh();
  601.     do
  602.         ch = getkey(0);
  603.     while (!islower(ch));
  604. }
  605.  
  606. void visetbuffer() /**/
  607. {
  608. int ch;
  609.  
  610.     ch = getkey(1);
  611.     if (!ialnum(ch)) {
  612.         feep();
  613.         return;
  614.     }
  615.     vibufspec = ch;
  616. }
  617.  
  618. static char *bp;
  619. static int lensb,countp;
  620.  
  621. void stradd(d) /**/
  622. char *d;
  623. {
  624.     while (*bp++ = *d++);
  625.     bp--;
  626. }
  627.  
  628. int putstr(d) /**/
  629. int d;
  630. {
  631.     *bp++ = d;
  632.     if (countp)
  633.         lensb++;
  634.     return 0;
  635. }
  636.  
  637. #define tstradd(X) \
  638.     if (termok && unset(SINGLELINEZLE)) { \
  639.         char tbuf[2048],*tptr = tbuf; \
  640.         if (tgetstr(X,&tptr)) \
  641.             tputs(tbuf,1,putstr); \
  642.     } \
  643.     break
  644.  
  645. /* get a prompt string */
  646.  
  647. char *putprompt(fm,lenp) /**/
  648. char *fm;int *lenp;
  649. {
  650. char *ss,*bl0;
  651. static char buf1[256],buf2[256],*buf;
  652. char buf3[MAXPATHLEN];
  653. int t0,bracepos = 0;
  654. struct tm *tm = NULL;
  655. time_t timet;
  656.  
  657.     lensb = 0; countp = 1;
  658.     if (!fm) { *lenp = 0; return ""; }
  659.     /* kludge alert! */
  660.     buf = (buf == buf1) ? buf2 : buf1;
  661.     bp = bl0 = buf;
  662.     if (!columns) columns = 80;
  663.     clearerr(stdin);
  664.     for(;*fm;fm++) {
  665.         if (bp-buf >= 220)
  666.             break;
  667.         if (*fm == '%')
  668.             switch (*++fm) {
  669.                 case '~':
  670.                     t0 = finddir(pwd);
  671.                     if (t0 != -1) {
  672.                         *bp++ = '~';
  673.                         stradd(usernames[t0]);
  674.                         stradd(pwd+strlen(userdirs[t0]));
  675.                         break;
  676.                     }
  677.                     if (!strncmp(pwd,home,t0 = strlen(home)) && t0 > 1) {
  678.                         *bp++ = '~';
  679.                         stradd(pwd+t0);
  680.                         break;
  681.                     }
  682.                 case 'd': case '/': stradd(pwd); break;
  683.                 case 'c': case '.':
  684.                     t0 = finddir(pwd);
  685.                     if (t0 != -1) {
  686.                         sprintf(buf3,"~%s%s",usernames[t0],
  687.                             pwd+strlen(userdirs[t0]));
  688.                     } else if (!strncmp(pwd,home,t0 = strlen(home)) && t0 > 1) {
  689.                         sprintf(buf3,"~%s",pwd+t0);
  690.                     } else {
  691.                         strcpy(buf3,pwd);
  692.                     }
  693.                     t0 = 1;
  694.                     if (idigit(fm[1])) { t0 = fm[1]-'0'; fm++; }
  695.                     for (ss = buf3+strlen(buf3); ss > buf3; ss--)
  696.                         if (*ss == '/' && !--t0) {
  697.                             ss++;
  698.                             break;
  699.                         }
  700.                     if (*ss == '/' && ss[1] && (ss != buf3)) ss++;
  701.                     stradd(ss);
  702.                     break;
  703.                 case 'C':
  704.                     strcpy(buf3,pwd);
  705.                     t0 = 1;
  706.                     if (idigit(fm[1])) { t0 = fm[1]-'0'; fm++; }
  707.                     for (ss = buf3+strlen(buf3); ss > buf3; ss--)
  708.                         if (*ss == '/' && !--t0) {
  709.                             ss++;
  710.                             break;
  711.                         }
  712.                     if (*ss == '/' && ss[1] && (ss != buf3)) ss++;
  713.                     stradd(ss);
  714.                     break;
  715.                 case 'h': case '!':
  716.                     sprintf(bp,"%d",curhist);
  717.                     bp += strlen(bp);
  718.                     break;
  719.                 case 'M': stradd(hostnam); break;
  720.                 case 'm':
  721.                     if (idigit(fm[1]))
  722.                         t0 = (*++fm)-'0';
  723.                     else
  724.                         t0 = 1;
  725.                     for (ss = hostnam; *ss; ss++)
  726.                         if (*ss == '.' && !--t0)
  727.                             break;
  728.                     t0 = *ss;
  729.                     *ss = '\0';
  730.                     stradd(hostnam);
  731.                     *ss = t0;
  732.                     break;
  733.                 case 'S': tstradd("so"); /* <- this is a macro */
  734.                 case 's': tstradd("se");
  735.                 case 'B': tstradd("md");
  736.                 case 'b': tstradd("me");
  737.                 case 'U': tstradd("us");
  738.                 case 'u': tstradd("ue");
  739.                 case '{': bracepos = bp-buf; countp = 0; break;
  740.                 case '}': lensb += (bp-buf)-bracepos; countp = 1; break;
  741.                 case 't': case '@':
  742.                     timet = time(NULL);
  743.                     tm = localtime(&timet);
  744.                     ztrftime(bp,16,"%l:%M%p",tm);
  745.                     if (*bp == ' ')
  746.                         chuck(bp);
  747.                     bp += strlen(bp);
  748.                     break;
  749.                 case 'T':
  750.                     timet = time(NULL);
  751.                     tm = localtime(&timet);
  752.                     ztrftime(bp,16,"%k:%M",tm);
  753.                     bp += strlen(bp);
  754.                     break;
  755.                 case '*':
  756.                     timet = time(NULL);
  757.                     tm = localtime(&timet);
  758.                     ztrftime(bp,16,"%k:%M:%S",tm);
  759.                     bp += strlen(bp);
  760.                     break;
  761.                 case 'n': stradd(username); break;
  762.                 case 'w':
  763.                     timet = time(NULL);
  764.                     tm = localtime(&timet);
  765.                     ztrftime(bp,16,"%a %e",tm);
  766.                     bp += strlen(bp);
  767.                     break;
  768.                 case 'W':
  769.                     timet = time(NULL);
  770.                     tm = localtime(&timet);
  771.                     ztrftime(bp,16,"%m/%d/%y",tm);
  772.                     bp += strlen(bp);
  773.                     break;
  774.                 case 'D':
  775.                      strcpy(buf3, "%y-%m-%d");
  776.                      if (fm[1] == '{') {
  777.                          for (ss = fm + 1, t0 = 0; *ss; ++ss)
  778.                              if (*ss == '{')
  779.                                  ++t0;
  780.                              else if (*ss == '}')
  781.                                  if (--t0 == 0)
  782.                                      break;
  783.                          if (*ss == '}' && t0 == 0) {
  784.                              t0 = (ss - 1) - (fm + 1);
  785.                              strncpy(buf3, fm + 2, t0);
  786.                              buf3[t0] = 0;
  787.                              fm = ss;
  788.                          }
  789.                      }
  790.                       timet = time(NULL);
  791.                       tm = localtime(&timet);
  792.                      ztrftime(bp,16,buf3,tm);
  793.                       bp += strlen(bp);
  794.                       break;
  795.                 case 'l':
  796.                     if (*ttystrname) stradd((strncmp(ttystrname,"/dev/tty",8) ? 
  797.                         ttystrname+5 : ttystrname+8));
  798.                     else stradd("()");
  799.                     break;
  800.                 case '?':
  801.                     sprintf(bp,"%d",lastval);
  802.                     bp += strlen(bp);
  803.                     break;
  804.                 case '%': *bp++ = '%'; break;
  805.                 case '#': *bp++ = (geteuid()) ? '%' : '#'; break;
  806.                 case 'r': stradd(rstring); break;
  807.                 case 'R': stradd(Rstring); break;
  808.                 default: *bp++ = '%'; *bp++ = *fm; break;
  809.             }
  810.         else if (*fm == '!') {
  811.             sprintf(bp,"%d",curhist);
  812.             bp += strlen(bp);
  813.         } else {
  814.             if (fm[0] == '\\' && fm[1])
  815.                 fm++;
  816.             if ((*bp++ = *fm) == '\n')
  817.                 bl0 = bp, lensb = 0;
  818.         }
  819.     }
  820.     *lenp = (bp-bl0)-lensb;
  821.     *lenp %= columns;
  822.     if (*lenp == columns-1) {
  823.         *lenp = 0;
  824.         *bp++ = ' ';
  825.     }
  826.     *bp = '\0';
  827.     return buf;
  828. }
  829.  
  830.