/************************************************************* * File: mon/hist.c * Purpose: Part of core Monitor * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970304 Start of revision history * 971002 Made some functions static * 971002 Fixed probs with ^N and ^P past end/beginning of history * 980331 changed getchar to GETCHAR for imon95 */ #include #include #include #include #ifdef PMCC #define GETCHAR getchar #endif #define H_PREV CNTRL('P') #define H_NEXT CNTRL('N') #define H_FORW CNTRL('F') #define H_BACK CNTRL('B') #define H_BEGIN CNTRL('A') #define H_END CNTRL('E') #define H_DELETE CNTRL('D') char *hist[HISTMAX]; /* array of old commands */ int histi; /* index to hist[], indicates next slot */ int histo; /* index to hist[], indicates oldest entry */ int histr; /* index to hist[], used while walking back with H_PREV */ int histno; /* current history number */ int column; /* current column number */ char *gethistn(),*gethists(); static left(), right(), backspace(), putstr(); /* 971002 */ void addhist(),addchar(); /************************************************************* * histinit() * initialize history mechanism */ histinit() { histno = 1; } /************************************************************* * get_cmd(p) * get a line from stdin using lineedit and history */ get_cmd(p) char *p; { int c,oc,v,i; char *q,buf[20],*t; ioctl_cbreak(STDIN); *p = 0; histr = histi; column = 0; for (;;) { c = GETCHAR(); if (c == H_PREV) { if (histr != histo) { right(p,strlen(p)-column); backspace(column); histr = decmod(histr,HISTMAX); strcpy(p,hist[histr]); putstr(p); } } else if (c == H_NEXT) { if (histr != histi) { right(p,strlen(p)-column); backspace(column); histr = incmod(histr,HISTMAX); if (histr == histi) *p = 0; else strcpy(p,hist[histr]); putstr(p); } } else if (c == H_FORW) right(p,1); else if (c == H_BACK) left(1); else if (c == H_BEGIN) left(column); else if (c == H_END) right(p,strlen(&p[column])); else if (c == H_DELETE) { oc = column; strdchr(&p[column]); putstr(&p[column]); putstr(" "); left(strlen(&p[oc])+1); } else if (c == '\b') { left(1); oc = column; strdchr(&p[column]); putstr(&p[column]); putstr(" "); left(strlen(&p[oc])+1); } else if (c == '\n' || c == '\r') { putstr("\n"); break; } else addchar(p,c); } /* do C-shell history subs */ if (q = findbang(p)) { getword(buf,q); strdchr(buf); /* delete the bang */ if (!strempty(buf)) { for (i=strlen(buf)+1;i>0;i--) strdchr(q); if (strequ(buf,"!")) { /* repeat last cmd */ stristr(q,hist[decmod(histi,HISTMAX)]); printf("%s\n",p); } else if (atob(&v,buf,10)) { /* hist# */ if (t = gethistn(v)) { stristr(q,t); printf("%s\n",p); } else printf("%s: Event not found.\n",buf); } else { /* hist string */ if (t = gethists(buf)) { stristr(q,t); printf("%s\n",p); } else printf("%s: Event not found.\n",buf); } } } addhist(p); ioctl_restore(STDIN); } /************************************************************* * void addchar(p,c) * add char to line, updates 'column' */ void addchar(p,c) char *p; int c; { int oc; if (strlen(p) > LINESZ-40) return; oc = column; strichr(&p[column],c); putstr(&p[column]); left(strlen(&p[oc])-1); } Optdesc hi_opts[] = { {"[cnt]","display command history"}, {"cnt","list cnt lines of command history"}, {0}}; /************************************************************* * dohi() * The hi command */ dohi(ac,av) int ac; char *av[]; { int i,n,siz,l; U64 rv; if(ac == 2) { if(!get_rsa(&rv,av[1])) return(1); siz = rv.lo; } else { if (!atob(&siz,getMonEnv("moresz"),10)) { printf("%s: bad moresz value\n",getMonEnv("moresz")); return(1); } } ioctl_cbreak(STDIN); l = siz; i = decmod(histi,HISTMAX); n = histno-1; while (i != decmod(histo,HISTMAX)) { sprintf(prnbuf,"%5d %s",n,hist[i]); if (more(prnbuf,&l,(ac>1)?0:siz)) break; i = decmod(i,HISTMAX); n--; } return(0); } /************************************************************* * static backspace(n) * distructive backspace, updates 'column' */ static backspace(n) int n; { for (;n>0 && column > 0;n--) { printf("\b \b"); column--; } } /************************************************************* * static right(p,n) * move the cursor n places right, updates global 'column' */ static right(p,n) char *p; int n; { int len; len = strlen(p); for (;n>0 && column < len;n--) { putchar(p[column]); column++; } } /************************************************************* * static left(n) * move the cursor n places left, updating global 'column' */ static left(n) int n; { for (;n>0 && column > 0;n--) { putchar('\b'); column--; } } /************************************************************* * char *gethistn(n) * return ptr to hist entry n */ char *gethistn(n) int n; { int m,d; if (n < (histno - HISTMAX) || n > histno) return(0); m = histi; d = histno - n; for (;d>0;d--) m = decmod(m,HISTMAX); return(hist[m]); } /************************************************************* * char *gethists(p) * use strbequ to return ptr to matching hist string */ char *gethists(p) char *p; { int i; i = decmod(histi,HISTMAX); while (i != decmod(histo,HISTMAX)) { if (hist[i] == 0) break; if (strbequ(hist[i],p)) return(hist[i]); i = decmod(i,HISTMAX); } return(0); } /************************************************************* * void addhist(p) * add command line to history */ void addhist(p) char *p; { int i; /* discard empty lines */ if (strempty(p)) return; /* discard dup lines if adjacent */ i = decmod(histi,HISTMAX); if (hist[i] != 0) { if (strequ(p,hist[i])) return; } /* make space if input has reached output */ if (incmod(histi,HISTMAX) == histo) { if (hist[histo] != 0) free(hist[histo]); hist[histo] = 0; histo = incmod(histo,HISTMAX); } hist[histi] = (char *)malloc(strlen(p)+1); if (hist[histi] == 0) { printf("addhist: out of memory\n"); return; } strcpy(hist[histi],p); histi = incmod(histi,HISTMAX); histno++; } /************************************************************* * static putstr(p) * print string and update global 'column' */ static putstr(p) char *p; { int i; for (i=0;p[i] != 0;i++) { if (!noecho) putchar(p[i]); if (noecho && xvwmode && p[i] == '\n') putchar('\n'); if (p[i] == '\n') column = 0; else column++; } } /************************************************************* * char *findbang(p) * Find the bang character (!). Skips stuff inside quotes. */ char *findbang(p) char *p; { int quote; for (;*p;p++) { if (*p == '\'' || *p == '"') { quote = *p; p++; while (*p && *p != quote) p++; } else if (*p == '!') return(p); } return(0); }