1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/tc.prompt.c,v 3.0 1991/07/04 21:49:28 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 "config.h" 38: #if !defined(lint) && !defined(pdp11) 39: static char *rcsid() 40: { return "$Id: tc.prompt.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; } 41: #endif 42: 43: #include "sh.h" 44: #include "ed.h" 45: /* 46: * kfk 21oct1983 -- add @ (time) and / ($cwd) in prompt. 47: * PWP 4/27/87 -- rearange for tcsh. 48: * mrdch@com.tau.edu.il 6/26/89 - added ~, T and .# - rearanged to switch() 49: * instead of if/elseif 50: */ 51: 52: char *month_list[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 53: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 54: void 55: printprompt(promptno, str) 56: int promptno; 57: Char *str; 58: { 59: Char *p, *z, *q; 60: register Char attributes = 0; 61: static int print_prompt_did_ding = 0; 62: register char *cz; 63: struct tm *t; 64: long lclock; 65: Char buff[BUFSIZ]; 66: Char *cp; 67: 68: (void) time(&lclock); 69: t = localtime(&lclock); 70: 71: PromptBuf[0] = '\0'; 72: p = PromptBuf; 73: switch (promptno) { 74: default: 75: case 0: 76: cp = value(STRprompt); 77: break; 78: case 1: 79: cp = value(STRp_2); 80: break; 81: case 2: 82: cp = value(STRp_3); 83: break; 84: } 85: 86: for (; *cp; cp++) { 87: if (*cp == '%') { 88: cp++; 89: switch (*cp) { 90: case 'R': 91: if (str != NULL) 92: while (*str) 93: *p++ = attributes | *str++; 94: break; 95: case '#': 96: *p++ = attributes | ((uid == 0) ? '#' : '>'); 97: break; 98: case '!': 99: case 'h': 100: Itoa(eventno + 1, buff); 101: for (z = buff; *z; z++) 102: *p++ = attributes | *z; 103: break; 104: case 'T': /* 24 hour format */ 105: case '@': 106: case 't': /* 12 hour am/pm format */ 107: { 108: char ampm = 'a'; 109: int hr = t->tm_hour; 110: 111: /* addition by Hans J. Albertsson */ 112: /* and another adapted from Justin Bur */ 113: if (adrof(STRampm) || *cp != 'T') { 114: if (hr >= 12) { 115: if (hr > 12) 116: hr -= 12; 117: ampm = 'p'; 118: } 119: else if (hr == 0) 120: hr = 12; 121: } /* else do a 24 hour clock */ 122: 123: /* "DING!" stuff by Hans also */ 124: if (t->tm_min || print_prompt_did_ding 125: /* || !adrof(STRprompt_ding) */ ) { 126: if (t->tm_min) 127: print_prompt_did_ding = 0; 128: Itoa(hr, buff); 129: *p++ = attributes | buff[0]; 130: if (buff[1]) 131: *p++ = attributes | buff[1]; 132: *p++ = attributes | ':'; 133: Itoa(t->tm_min, buff); 134: if (buff[1]) { 135: *p++ = attributes | buff[0]; 136: *p++ = attributes | buff[1]; 137: } 138: else { 139: *p++ = attributes | '0'; 140: *p++ = attributes | buff[0]; 141: } 142: if (adrof(STRampm) || *cp != 'T') { 143: *p++ = attributes | ampm; 144: *p++ = attributes | 'm'; 145: } 146: } 147: else { /* we need to ding */ 148: int i = 0; 149: 150: (void) Strcpy(buff, STRDING); 151: while (buff[i]) { 152: *p++ = attributes | buff[i++]; 153: } 154: print_prompt_did_ding = 1; 155: } 156: } 157: break; 158: 159: case 'M': 160: /* 161: * Bug pointed out by Laurent Dami <dami@cui.unige.ch>: don't 162: * derefrence that NULL (if HOST is not set)... 163: */ 164: if ((cz = getenv("HOST")) != NULL) 165: while (*cz) 166: *p++ = attributes | *cz++; 167: break; 168: 169: case 'm': 170: if ((cz = getenv("HOST")) != NULL) 171: while (*cz && *cz != '.') 172: *p++ = attributes | *cz++; 173: break; 174: 175: case '~': /* show ~ whenever possible - a la dirs */ 176: { 177: static Char *olddir = 0, *olduser = 0, *o_pth = 0; 178: 179: if (!(z = value(STRcwd))) 180: break; /* no cwd, so don't do anything */ 181: /* 182: * Have we changed directory? 183: */ 184: if (olddir != z) { 185: o_pth = olddir = z; 186: olduser = getusername(&o_pth); 187: } 188: if (olduser) { 189: *p++ = attributes | '~'; 190: for (q = olduser; *q; *p++ = attributes | *q++); 191: for (z = o_pth; *z; *p++ = attributes | *z++); 192: break; 193: } 194: } 195: /* fall through if ~ not matched */ 196: case '/': 197: case 'd': 198: if (z = value(STRcwd)) { 199: while (*z) 200: *p++ = attributes | *z++; 201: } 202: break; 203: case '.': 204: case 'c': 205: case 'C': 206: { 207: register int j, k; 208: Char scp; 209: 210: scp = *cp; 211: /* option to determine fix number of dirs from path */ 212: if (*(cp + 1) >= '1' && *(cp + 1) <= '9') { 213: j = *(cp + 1) - '0'; 214: cp++; 215: } 216: else { 217: j = 1; 218: } 219: if (!(z = value(STRcwd))) 220: break; 221: (void) Strcpy(buff, z); 222: if (!buff[1]) { /* if CWD == / */ 223: *p++ = attributes | buff[0]; 224: } 225: else { 226: if ((scp != 'C') && (q = value(STRhome)) && 227: Strncmp(buff, q, (k = Strlen(q))) == 0 && 228: (buff[k] == '/' || buff[k] == '\0')) { 229: buff[--k] = '~'; 230: q = &buff[k]; 231: } 232: else 233: q = buff; 234: for (z = q; *z; z++); /* find the end */ 235: while (j-- > 0) { 236: while ((z > q) && (*z != '/')) 237: z--; /* back up */ 238: if (j && z > q) 239: z--; 240: } 241: if (*z == '/' && z != q) 242: z++; 243: while (*z) 244: *p++ = attributes | *z++; 245: } 246: } 247: break; 248: case 'n': 249: if (z = value(STRuser)) 250: while (*z) 251: *p++ = attributes | *z++; 252: break; 253: case 'l': 254: if (z = value(STRtty)) 255: while (*z) 256: *p++ = attributes | *z++; 257: break; 258: case 'w': 259: for (cz = month_list[t->tm_mon]; *cz;) 260: *p++ = attributes | *cz++; 261: *p++ = attributes | ' '; 262: Itoa(t->tm_mday, buff); 263: *p++ = attributes | buff[0]; 264: if (buff[1]) 265: *p++ = attributes | buff[1]; 266: break; 267: case 'W': 268: Itoa(t->tm_mon + 1, buff); 269: if (buff[1]) { 270: *p++ = attributes | buff[0]; 271: *p++ = attributes | buff[1]; 272: } 273: else { 274: *p++ = attributes | '0'; 275: *p++ = attributes | buff[0]; 276: } 277: *p++ = attributes | '/'; 278: 279: Itoa(t->tm_mday, buff); 280: if (buff[1]) { 281: *p++ = attributes | buff[0]; 282: *p++ = attributes | buff[1]; 283: } 284: else { 285: *p++ = attributes | '0'; 286: *p++ = attributes | buff[0]; 287: } 288: *p++ = attributes | '/'; 289: 290: Itoa(t->tm_year, buff); 291: if (buff[1]) { 292: *p++ = attributes | buff[0]; 293: *p++ = attributes | buff[1]; 294: } 295: else { 296: *p++ = attributes | '0'; 297: *p++ = attributes | buff[0]; 298: } 299: break; 300: case 'D': 301: Itoa(t->tm_year, buff); 302: if (buff[1]) { 303: *p++ = attributes | buff[0]; 304: *p++ = attributes | buff[1]; 305: } 306: else { 307: *p++ = attributes | '0'; 308: *p++ = attributes | buff[0]; 309: } 310: *p++ = attributes | '-'; 311: 312: Itoa(t->tm_mon + 1, buff); 313: if (buff[1]) { 314: *p++ = attributes | buff[0]; 315: *p++ = attributes | buff[1]; 316: } 317: else { 318: *p++ = attributes | '0'; 319: *p++ = attributes | buff[0]; 320: } 321: *p++ = attributes | '-'; 322: 323: Itoa(t->tm_mday, buff); 324: if (buff[1]) { 325: *p++ = attributes | buff[0]; 326: *p++ = attributes | buff[1]; 327: } 328: else { 329: *p++ = attributes | '0'; 330: *p++ = attributes | buff[0]; 331: } 332: break; 333: case 'S': /* start standout */ 334: attributes |= STANDOUT; 335: break; 336: case 'B': /* start bold */ 337: attributes |= BOLD; 338: break; 339: case 'U': /* start underline */ 340: attributes |= UNDER; 341: break; 342: case 's': /* end standout */ 343: attributes &= ~STANDOUT; 344: break; 345: case 'b': /* end bold */ 346: attributes &= ~BOLD; 347: break; 348: case 'u': /* end underline */ 349: attributes &= ~UNDER; 350: break; 351: case 'L': 352: ClearToBottom(); 353: break; 354: case '?': 355: if (z = value(STRstatus)) 356: while (*z) 357: *p++ = attributes | *z++; 358: break; 359: case '%': 360: *p++ = attributes | '%'; 361: break; 362: case '{': /* literal characters start */ 363: #if LITERAL == 0 364: /* 365: * No literal capability, so skip all chars in the literal 366: * string 367: */ 368: while (*cp != '\0' && (*cp != '%' || cp[1] != '}')) 369: cp++; 370: #endif /* LITERAL == 0 */ 371: attributes |= LITERAL; 372: break; 373: case '}': /* literal characters end */ 374: attributes &= ~LITERAL; 375: break; 376: default: 377: *p++ = attributes | '%'; 378: *p++ = attributes | *cp; 379: break; 380: } 381: } 382: else if (*cp == '\\' | *cp == '^') { 383: *p++ = attributes | parseescape(&cp); 384: } 385: else if (*cp == '!') { /* EGS: handle '!'s in prompts */ 386: Itoa(eventno + 1, buff); 387: for (z = buff; *z; z++) 388: *p++ = attributes | *z; 389: } 390: else { 391: *p++ = attributes | *cp; /* normal character */ 392: } 393: } 394: *p = '\0'; 395: if (!editing) { 396: for (z = PromptBuf; z < p; z++) 397: (void) putraw(*z); 398: SetAttributes(0); 399: flush(); 400: } 401: }