home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume25 / tcsh-6.01 / part05 / tc.prompt.c < prev    next >
C/C++ Source or Header  |  1991-12-19  |  10KB  |  423 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/tc.prompt.c,v 3.9 1991/12/19 22:34:14 christos Exp $ */
  2. /*
  3.  * tc.prompt.c: Prompt printing stuff
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: tc.prompt.c,v 3.9 1991/12/19 22:34:14 christos Exp $")
  40.  
  41. #include "ed.h"
  42.  
  43. /*
  44.  * kfk 21oct1983 -- add @ (time) and / ($cwd) in prompt.
  45.  * PWP 4/27/87 -- rearange for tcsh.
  46.  * mrdch@com.tau.edu.il 6/26/89 - added ~, T and .# - rearanged to switch()
  47.  *                 instead of if/elseif
  48.  * Luke Mewburn, s902113@minyos.xx.rmit.OZ.AU 6-Sep-91 - changed date format
  49.  */
  50.  
  51. char   *month_list[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  52.             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  53. char   *day_list[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  54. void
  55. printprompt(promptno, str)
  56.     int     promptno;
  57.     Char   *str;
  58. {
  59.     Char   *p, *z, *q, *ep, *cp;
  60.     register Char attributes = 0;
  61.     static int print_prompt_did_ding = 0;
  62.     register char *cz;
  63.     struct tm *t;
  64.     time_t  lclock;
  65.     Char    buff[BUFSIZE];
  66.     static  Char *ocp = NULL, *ostr = NULL;
  67.  
  68.     (void) time(&lclock);
  69.     t = localtime(&lclock);
  70.  
  71.     PromptBuf[0] = '\0';
  72.     p = PromptBuf;
  73.     ep = &PromptBuf[2*INBUFSIZE - 2];
  74.     switch (promptno) {
  75.     default:
  76.     case 0:
  77.     cp = value(STRprompt);
  78.     break;
  79.     case 1:
  80.     cp = value(STRprompt2);
  81.     break;
  82.     case 2:
  83.     cp = value(STRprompt3);
  84.     break;
  85.     case 3:
  86.     if (ocp != NULL) {
  87.         cp = ocp;
  88.         str = ostr;
  89.     }
  90.     else 
  91.         cp = value(STRprompt);
  92.     break;
  93.     }
  94.     if (promptno < 2) {
  95.     ocp = cp;
  96.     ostr = str;
  97.     }
  98.  
  99.     for (; *cp; cp++) {
  100.     if (p >= ep)
  101.         break;
  102.     if (*cp == '%') {
  103.         cp++;
  104.         switch (*cp) {
  105.         case 'R':
  106.         if (str != NULL)
  107.             while (*str) {
  108.             *p++ = attributes | *str++;
  109.             if (p >= ep) break;
  110.             }
  111.         break;
  112.         case '#':
  113.         *p++ = attributes | ((uid == 0) ? '#' : '>');
  114.         break;
  115.         case '!':
  116.         case 'h':
  117.         Itoa(eventno + 1, buff);
  118.         for (z = buff; *z; z++) {
  119.             *p++ = attributes | *z;
  120.             if (p >= ep) break;
  121.         }
  122.         break;
  123.         case 'T':        /* 24 hour format     */
  124.         case '@':
  125.         case 't':        /* 12 hour am/pm format */
  126.         {
  127.             char    ampm = 'a';
  128.             int     hr = t->tm_hour;
  129.  
  130.             if (p >= ep - 10) break;
  131.  
  132.             /* addition by Hans J. Albertsson */
  133.             /* and another adapted from Justin Bur */
  134.             if (adrof(STRampm) || *cp != 'T') {
  135.             if (hr >= 12) {
  136.                 if (hr > 12)
  137.                 hr -= 12;
  138.                 ampm = 'p';
  139.             }
  140.             else if (hr == 0)
  141.                 hr = 12;
  142.             }        /* else do a 24 hour clock */
  143.  
  144.             /* "DING!" stuff by Hans also */
  145.             if (t->tm_min || print_prompt_did_ding
  146.              /* || !adrof(STRprompt_ding) */ ) {
  147.             if (t->tm_min)
  148.                 print_prompt_did_ding = 0;
  149.             Itoa(hr, buff);
  150.             *p++ = attributes | buff[0];
  151.             if (buff[1]) 
  152.                 *p++ = attributes | buff[1];
  153.             *p++ = attributes | ':';
  154.             Itoa(t->tm_min, buff);
  155.             if (buff[1]) {
  156.                 *p++ = attributes | buff[0];
  157.                 *p++ = attributes | buff[1];
  158.             }
  159.             else {
  160.                 *p++ = attributes | '0';
  161.                 *p++ = attributes | buff[0];
  162.             }
  163.             if (adrof(STRampm) || *cp != 'T') {
  164.                 *p++ = attributes | ampm;
  165.                 *p++ = attributes | 'm';
  166.             }
  167.             }
  168.             else {    /* we need to ding */
  169.             int     i = 0;
  170.  
  171.             (void) Strcpy(buff, STRDING);
  172.             while (buff[i]) {
  173.                 *p++ = attributes | buff[i++];
  174.             }
  175.             print_prompt_did_ding = 1;
  176.             }
  177.         }
  178.         break;
  179.  
  180.         case 'M':
  181.         /*
  182.          * Bug pointed out by Laurent Dami <dami@cui.unige.ch>: don't
  183.          * derefrence that NULL (if HOST is not set)...
  184.          */
  185.         if ((cz = getenv("HOST")) != NULL)
  186.             while (*cz) {
  187.             if (p >= ep) break;
  188.             *p++ = attributes | *cz++;
  189.             }
  190.         break;
  191.  
  192.         case 'm':
  193.         if ((cz = getenv("HOST")) != NULL)
  194.             while (*cz && *cz != '.') {
  195.             if (p >= ep) break;
  196.             *p++ = attributes | *cz++;
  197.             }
  198.         break;
  199.  
  200.         case '~':        /* show ~ whenever possible - a la dirs */
  201.         {
  202.             static Char *olddir = 0, *olduser = 0, *oldpath = 0;
  203.             extern int tlength;    /* cache cleared */
  204.  
  205.             if (!(z = value(STRcwd)))
  206.             break;    /* no cwd, so don't do anything */
  207.             /*
  208.              * Have we changed directory?
  209.              */
  210.             if (tlength == 0 || olddir != z) {
  211.             oldpath = olddir = z;
  212.             olduser = getusername(&oldpath);
  213.             }
  214.             if (olduser) {
  215.             *p++ = attributes | '~';
  216.             if (p >= ep) break;
  217.             for (q = olduser; *q; *p++ = attributes | *q++)
  218.                 if (p >= ep) break;
  219.             for (z = oldpath; *z; *p++ = attributes | *z++)
  220.                 if (p >= ep) break;
  221.             break;
  222.             }
  223.         }
  224.         /* fall through if ~ not matched */
  225.         case '/':
  226.         if (z = value(STRcwd)) {
  227.             while (*z) {
  228.             *p++ = attributes | *z++;
  229.             if (p >= ep) break;
  230.             }
  231.         }
  232.         break;
  233.         case '.':
  234.         case 'c':
  235.         case 'C':
  236.         {
  237.             register int j, k;
  238.             Char    scp;
  239.  
  240.             scp = *cp;
  241.             /* option to determine fix number of dirs from path */
  242.             if (*(cp + 1) >= '1' && *(cp + 1) <= '9') {
  243.             j = *(cp + 1) - '0';
  244.             cp++;
  245.             }
  246.             else {
  247.             j = 1;
  248.             }
  249.             if (!(z = value(STRcwd)))
  250.             break;
  251.             (void) Strcpy(buff, z);
  252.             if (!buff[1]) {    /* if CWD == / */
  253.             *p++ = attributes | buff[0];
  254.             }
  255.             else {
  256.             if ((scp != 'C') && (q = value(STRhome)) &&
  257.                 Strncmp(buff, q, (k = Strlen(q))) == 0 &&
  258.                 (buff[k] == '/' || buff[k] == '\0')) {
  259.                 buff[--k] = '~';
  260.                 q = &buff[k];
  261.             }
  262.             else
  263.                 q = buff;
  264.             for (z = q; *z; z++);    /* find the end */
  265.             while (j-- > 0) {
  266.                 while ((z > q) && (*z != '/'))
  267.                 z--;    /* back up */
  268.                 if (j && z > q)
  269.                 z--;
  270.             }
  271.             if (*z == '/' && z != q)
  272.                 z++;
  273.             while (*z) {
  274.                 *p++ = attributes | *z++;
  275.                 if (p >= ep) break;
  276.             }
  277.             }
  278.         }
  279.         break;
  280.         case 'n':
  281.         if (z = value(STRuser))
  282.             while (*z) {
  283.             *p++ = attributes | *z++;
  284.             if (p >= ep) break;
  285.             }
  286.         break;
  287.         case 'l':
  288.         if (z = value(STRtty))
  289.             while (*z) {
  290.             *p++ = attributes | *z++;
  291.             if (p >= ep) break;
  292.             }
  293.         break;
  294.         case 'd':
  295.         for (cz = day_list[t->tm_wday]; *cz;) {
  296.             *p++ = attributes | *cz++;
  297.             if (p >= ep) break;
  298.         }
  299.         break;
  300.         case 'D':
  301.         Itoa(t->tm_mday, buff);
  302.         if (p >= ep - 3) break;
  303.         if (buff[1]) {
  304.             *p++ = attributes | buff[0];
  305.             *p++ = attributes | buff[1];
  306.         }
  307.         else {
  308.             *p++ = attributes | '0';
  309.             *p++ = attributes | buff[0];
  310.         }
  311.         break;
  312.         case 'w':
  313.         if (p >= ep - 20) break;
  314.         for (cz = month_list[t->tm_mon]; *cz;) 
  315.             *p++ = attributes | *cz++;
  316.         break;
  317.         case 'W':
  318.         if (p >= ep - 3) break;
  319.         Itoa(t->tm_mon + 1, buff);
  320.         if (buff[1]) {
  321.             *p++ = attributes | buff[0];
  322.             *p++ = attributes | buff[1];
  323.         }
  324.         else {
  325.             *p++ = attributes | '0';
  326.             *p++ = attributes | buff[0];
  327.         }
  328.         break;
  329.         case 'y':
  330.         if (p >= ep - 3) break;
  331.         Itoa(t->tm_year, buff);
  332.         if (buff[1]) {
  333.             *p++ = attributes | buff[0];
  334.             *p++ = attributes | buff[1];
  335.         }
  336.         else {
  337.             *p++ = attributes | '0';
  338.             *p++ = attributes | buff[0];
  339.         }
  340.         break;
  341.         case 'Y':
  342.         if (p >= ep - 5) break;
  343.         Itoa(t->tm_year + 1900, buff);
  344.         *p++ = attributes | buff[0];
  345.         *p++ = attributes | buff[1];
  346.         *p++ = attributes | buff[2];
  347.         *p++ = attributes | buff[3];
  348.         break;
  349.         case 'S':        /* start standout */
  350.         attributes |= STANDOUT;
  351.         break;
  352.         case 'B':        /* start bold */
  353.         attributes |= BOLD;
  354.         break;
  355.         case 'U':        /* start underline */
  356.         attributes |= UNDER;
  357.         break;
  358.         case 's':        /* end standout */
  359.         attributes &= ~STANDOUT;
  360.         break;
  361.         case 'b':        /* end bold */
  362.         attributes &= ~BOLD;
  363.         break;
  364.         case 'u':        /* end underline */
  365.         attributes &= ~UNDER;
  366.         break;
  367.         case 'L':
  368.         ClearToBottom();
  369.         break;
  370.         case '?':
  371.         if (z = value(STRstatus))
  372.             while (*z) {
  373.             *p++ = attributes | *z++;
  374.             if (p >= ep) break;
  375.             }
  376.         break;
  377.         case '%':
  378.         *p++ = attributes | '%';
  379.         break;
  380.         case '{':        /* literal characters start */
  381. #if LITERAL == 0
  382.         /*
  383.          * No literal capability, so skip all chars in the literal
  384.          * string
  385.          */
  386.         while (*cp != '\0' && (*cp != '%' || cp[1] != '}'))
  387.             cp++;
  388. #endif                /* LITERAL == 0 */
  389.         attributes |= LITERAL;
  390.         break;
  391.         case '}':        /* literal characters end */
  392.         attributes &= ~LITERAL;
  393.         break;
  394.         default:
  395.         if (p >= ep - 3) break;
  396.         *p++ = attributes | '%';
  397.         *p++ = attributes | *cp;
  398.         break;
  399.         }
  400.     }
  401.     else if (*cp == '\\' | *cp == '^') {
  402.         *p++ = attributes | parseescape(&cp);
  403.     }
  404.     else if (*cp == '!') {    /* EGS: handle '!'s in prompts */
  405.         Itoa(eventno + 1, buff);
  406.         for (z = buff; *z; z++) {
  407.         *p++ = attributes | *z;
  408.         if (p >= ep) break;
  409.         }
  410.     }
  411.     else {
  412.         *p++ = attributes | *cp;    /* normal character */
  413.     }
  414.     }
  415.     *p = '\0';
  416.     if (!editing) {
  417.     for (z = PromptBuf; z < p; z++)
  418.         (void) putraw(*z);
  419.     SetAttributes(0);
  420.     flush();
  421.     }
  422. }
  423.