home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------------*
- *
- * wish - windowing user friendly shell
- * ------------------------------------
- *
- * Copyright (c) 1988-1993 Hellmuth Michaelis
- *
- * Eggerstedtstr. 28
- * 22765 Hamburg
- * Germany
- *
- * Tel: +49 / 40 / 384298 (private)
- * Tel: +49 / 40 / 55903-170 (at work)
- * e-mail: hm@hcshh.hcs.de
- *
- * --------oOo--------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *---------------------------------------------------------------------------*
- *
- * last edit-date: [Wed Sep 22 13:28:09 1993]
- *
- * -hm history on commandline
- * -hm integrating line handling from terminal.c from my sh
- * -hm debugging line editor
- *
- *---------------------------------------------------------------------------*/
-
- #include "wish.h" /* local includes */
-
- static char overstrike; /* overstrike mode */
- static char kbuf[HISLNLEN]; /* kill buffer */
- static int kbuf_init = 0; /* static kill buffer */
- static char *beg; /* line start (first char on line) */
- static char *pnt; /* next insertion position (cursor) */
- static char *end; /* line end (first free pos on line) */
- static char *sbeg; /* first character on screen */
- static int lmax; /* maximum charcount requested from caller */
-
- static void pmstr(char *); /* forward decl */
- static void pnstr(int, char *);
- void dis_hist(void);
-
- /*---------------------------------------------------------------------------*
- * return current (cursor) column
- *---------------------------------------------------------------------------*/
- int curcol(void)
- {
- return((int)(pnt - sbeg));
- }
-
- /*---------------------------------------------------------------------------*
- * return true, if commandline empty ( == operate on file window on CR )
- *---------------------------------------------------------------------------*/
- int cr_on_files(void)
- {
- return((int)(beg == end));
- }
-
- /*---------------------------------------------------------------------------*
- * init commandline history system
- *---------------------------------------------------------------------------*/
- void init_history(void)
- {
- overstrike = 0; /* insert is default */
-
- cur_his = 0; /* current history pointer */
- strcpy(cbuff,hislines[cur_his]);
-
- sbeg = cbuff; /* screen begin at start of buffer */
- beg = cbuff + strlen(cbuff); /* position beg after prompt */
- pnt = end = beg; /* point = end = buffer begin */
-
- kbuf[0] = '\0'; /* init kill - buffer */
- kbuf_init = 1; /* static kbuf */
-
- lmax = HISLNLEN-1; /* max line length */
-
- wmove(cmnd_w,C_LINE,0); /* beg of line */
- waddstr(cmnd_w, cbuff); /* write prompt */
- }
-
- /*---------------------------------------------------------------------------*
- * save current commandline to history stack
- *---------------------------------------------------------------------------*/
- void save_line(void)
- {
- strncpy(hislines[cur_his],cbuff,HISLNLEN-1);
- if(cur_his == HISLINES-1)
- cur_his = 0;
- else
- cur_his++;
- hislines[cur_his][3] = '\0';
- dis_hist();
- }
-
- /*---------------------------------------------------------------------------*
- * get previous history line
- *---------------------------------------------------------------------------*/
- void prev_line(void)
- {
- if(cur_his == 0)
- cur_his = HISLINES-1;
- else
- cur_his--;
-
- dis_hist();
- }
-
- /*---------------------------------------------------------------------------*
- * get next history line
- *---------------------------------------------------------------------------*/
- void next_line(void)
- {
- if(cur_his == HISLINES-1)
- cur_his = 0;
- else
- cur_his++;
-
- dis_hist();
- }
-
- /*---------------------------------------------------------------------------*
- * valid new line from history stack, display it
- *---------------------------------------------------------------------------*/
- void dis_hist(void)
- {
- strncpy(cbuff,hislines[cur_his],HISLNLEN-1);
-
- if((strlen(cbuff)) < COLS)
- { /* new line will fit onto screen */
- wmove(cmnd_w,C_LINE,0); /* move to start of line */
- wclrtoeol(cmnd_w); /* clear line */
- wmove(cmnd_w,C_LINE,0); /* move to start of line */
- waddstr(cmnd_w, cbuff); /* write new line */
- sbeg = cbuff; /* new screen begin */
- }
- else
- { /* line will not fit onto screen, search end & write new */
- wmove(cmnd_w,C_LINE,0); /* start of line */
- wclrtoeol(cmnd_w); /* clear to end of line */
- sbeg = cbuff; /* start of buffer */
- while((strlen(sbeg) + 1) > COLS) /* find segment */
- sbeg += COLS/2; /* start */
- waddstr(cmnd_w, sbeg); /* write last segment */
- }
- pnt = end = (cbuff + strlen(cbuff));
- beg = cbuff + 3; /* position beg after prompt */
- }
-
- /*---------------------------------------------------------------------------*
- * move cursor forward
- *---------------------------------------------------------------------------*/
- void right_line(void)
- {
- if(pnt < end) /* something to move ? */
- {
- pnt++; /* next char */
- if(pnt > (sbeg + COLS)) /* moving on screen ? */
- {
- sbeg += COLS/2; /* new screen begin */
- wmove(cmnd_w,C_LINE,0); /* start of screen */
- wclrtoeol(cmnd_w); /* clear line */
- pmstr(sbeg); /* write new segment */
- }
- }
- }
-
- /*---------------------------------------------------------------------------*
- * move cursor back one character
- *---------------------------------------------------------------------------*/
- void left_line(void)
- {
- if(pnt > beg) /* allowed to move ?? */
- {
- pnt--; /* prev char */
- if(pnt < sbeg) /* move on screen ?? */
- {
- sbeg -= COLS/2; /* back 1/2 length */
- wmove(cmnd_w,C_LINE,0); /* start of screen */
- wclrtoeol(cmnd_w); /* clear line */
- pmstr(sbeg); /* print this part of buffer */
- }
- }
- }
-
- /*---------------------------------------------------------------------------*
- * append / insert / overstrike a (printable) character
- *---------------------------------------------------------------------------*/
- int cmdline(int c)
- {
- if((end-beg) < lmax) /* space in buffer ? */
- {
- if(pnt == end) /************ append **********/
- {
- *pnt++ = c; /* store char */
- end++; /* new end ptr */
- *end = '\0'; /* new terminator */
-
- if((end-sbeg+1) > COLS)
- {
- sbeg += COLS/2;
- wmove(cmnd_w,C_LINE,0);
- wclrtoeol(cmnd_w);
- waddstr(cmnd_w, sbeg);
- }
- else
- {
- waddch(cmnd_w,c); /* echo char */
- }
- }
- else if(!overstrike) /************** insert **********/
- {
- register char *p;
- register char *q;
-
- p = end-1; /* last char */
- q = end; /* last char + 1 */
- while(q > pnt) /* shift right buffer */
- *q-- = *p--;
-
- *pnt = c; /* store chr into gap */
- end++; /* increment end ptr */
- *end = '\0'; /* new terminator */
-
- if( (pnt+1) > (sbeg + COLS)) /* scroll right ? */
- {
- sbeg += COLS/2; /* new screen beg */
- }
- wmove(cmnd_w,C_LINE,0); /* start of line */
- pmstr(sbeg); /* print string */
- pnt++; /* new point */
- }
- else /************** overstrike ****************/
- {
- *pnt++ = c; /* store char */
-
- if((pnt-sbeg+1) > COLS)
- {
- sbeg += COLS/2;
- wmove(cmnd_w,C_LINE,0);
- wclrtoeol(cmnd_w);
- pmstr(sbeg);
- }
- else
- {
- waddch(cmnd_w,c); /* echo char */
- }
- }
- return(GOOD);
- }
- else
- {
- flash(); /* no no .. */
- return(BAD); /* don't accept it */
- }
- }
-
- /*---------------------------------------------------------------------------*
- * delete character left of cursor
- *---------------------------------------------------------------------------*/
- void handlebs(void)
- {
- register char *p;
- register char *q;
-
- if(pnt == beg) /* at start of buffer ? */
- return; /* yes */
-
- q = pnt; /* next char */
- pnt--; /* point backward */
- p = pnt; /* this char */
- while(q < end) /* shift left buffer */
- *p++ = *q++;
- end--; /* new end pointer */
- *end = '\0'; /* new end terminator */
-
- if(pnt < sbeg) /* moved into previous segment ? */
- {
- sbeg -= COLS/2; /* new segment start */
- }
- wmove(cmnd_w,C_LINE,0); /* start of screen line */
- wclrtoeol(cmnd_w); /* clear line */
- pmstr(sbeg); /* write segment */
- }
-
- /*---------------------------------------------------------------------------*
- * delete character under cursor
- *---------------------------------------------------------------------------*/
- void del_char(void)
- {
- register char *p;
- register char *q;
-
- if(pnt == end) /* at start of buffer ? */
- return; /* yes */
-
- p = pnt; /* current char */
- q = pnt+1; /* next char */
-
- while(q < end) /* shift left buffer */
- *p++ = *q++;
-
- end--; /* new end pointer */
- *end = '\0'; /* new end terminator */
-
- wmove(cmnd_w,C_LINE,0); /* start of screen line */
- wclrtoeol(cmnd_w); /* clear line */
- pmstr(sbeg); /* write new segment */
- }
-
- /*---------------------------------------------------------------------------*
- * print string, maximum length is COLS
- *---------------------------------------------------------------------------*/
- static void pmstr(char *str)
- {
- char buf[256];
- register int i = 0;
-
- while((*str) && (i < COLS))
- buf[i++] = *str++;
- buf[i] = '\0';
- waddstr(cmnd_w, buf);
- }
-
- /*---------------------------------------------------------------------------*
- * print string, maximum length parameter <n>
- *---------------------------------------------------------------------------*/
- static void pnstr(int n, char *str)
- {
- char buf[256];
- register int i = 0;
-
- while((*str) && (i < n))
- buf[i++] = *str++;
- buf[i] = '\0';
- waddstr(cmnd_w, buf);
- }
-
- /*---------------------------------------------------------------------------*
- * delete from cursor to end of line
- *---------------------------------------------------------------------------*/
- void clear_toeol(void)
- {
- strcpy(kbuf, pnt); /* save to kill buffer */
- wclrtoeol(cmnd_w); /* clear line */
- end = pnt; /* new end ptr */
- *end = '\0'; /* terminate line */
- }
-
- /*---------------------------------------------------------------------------*
- * move cursor to end of line
- *---------------------------------------------------------------------------*/
- void eol_line(void)
- {
- if(pnt == end) /* already at end ? */
- return; /* yes */
-
- if((strlen(cbuff) < COLS) && (sbeg == cbuff))
- {
- pnt = end; /* set point to end */
- }
- else
- {
- wmove(cmnd_w,C_LINE,0); /* start of line */
- wclrtoeol(cmnd_w); /* clear to end of line */
- sbeg = cbuff; /* start of buffer */
- while((strlen(sbeg) + 1) > COLS) /* find segment */
- sbeg += COLS/2; /* start */
- waddstr(cmnd_w, sbeg); /* write last segment */
- pnt = end; /* new point */
- }
- }
-
- /*---------------------------------------------------------------------------*
- * move cursor to begin of line
- *---------------------------------------------------------------------------*/
- void bol_line(void)
- {
- if(pnt == beg) /* already at begin of buffer */
- return; /* nothing to do ! */
-
- pnt = beg; /* point = buffer start */
-
- if(sbeg != cbuff) /* not in first screen segment */
- {
- wmove(cmnd_w,C_LINE,0); /* cursor -> start of screen */
- wclrtoeol(cmnd_w); /* clear to end of line */
- pmstr(cbuff); /* write from start of buffer */
- sbeg = cbuff; /* screen begin = buffer start */
- }
- }
-
- /*---------------------------------------------------------------------------*
- * yank text from kill-buffer to current point
- *---------------------------------------------------------------------------*/
- void yank(void)
- {
- if(kbuf[0] == '\0') /* kill buffer empty ? */
- return; /* yes, exit */
-
- if((end - beg) >= lmax) /* space in buffer ? */
- { /* no... */
- if((overstrike) && (pnt == end)) /* perhaps overstr in the middle ? */
- return; /* no... */
- if(!overstrike) /* insert / append ? */
- return; /* yes */
- }
-
- /* here if either space in buffer or overwrite not at end */
-
- if(pnt == end) /************ append **********/
- {
- /* append kill buffer to buffer, observe buffer max length */
-
- strncat(cbuff, kbuf, lmax);
- end = cbuff + strlen(cbuff);
- if((end-sbeg+1) > COLS)
- {
- while((end-sbeg+1) > COLS)
- sbeg += COLS/2;
- wmove(cmnd_w,C_LINE,0);
- wclrtoeol(cmnd_w);
- waddstr(cmnd_w, sbeg); /* write whole new segment */
- }
- else
- {
- waddstr(cmnd_w, pnt); /* write new end */
- }
- pnt = end; /* set new pnt */
- }
- else if(!overstrike) /************** insert **********/
- {
- char tail[HISLNLEN]; /* temp storage */
- register int i; /* gp... */
- register char *p = pnt; /* save point pos */
-
- strcpy(tail, pnt); /* save string frm point on */
- strncpy(pnt, kbuf, lmax); /* insert up to max */
- pnt = cbuff + strlen(cbuff);
- strcat(pnt, tail); /* append saved tail */
- end = cbuff + strlen(cbuff);
-
- if((pnt-sbeg+1) > COLS)
- { /* new point is outside current segment */
- while((pnt-sbeg+1) > COLS)
- sbeg += COLS/2;
- wmove(cmnd_w,C_LINE,0);
- wclrtoeol(cmnd_w);
- pmstr(sbeg); /* print string */
- }
- else
- { /* new point is inside current segment */
- if((strlen(sbeg)) < COLS) /* line > than screen ? */
- i = (sbeg + strlen(sbeg)) - p; /* no */
- else
- i = (sbeg + COLS) - p; /* yes */
- pnstr(i, p); /* new tail */
- p += i;
- while(p-- > pnt)
- wmove(cmnd_w, C_LINE, (curcol()-1));
- }
- }
- else /************** overstrike ****************/
- {
- register int j = lmax;
- register char *k = kbuf;
-
- while(j-- && *k)
- *pnt++ = *k++; /* copy kbuf over buffer */
-
- if(pnt > end) /* buffer grown bigger ? */
- {
- end = pnt; /* set new end ptr */
- *end = '\0'; /* terminate buffer */
- }
-
- if((pnt-sbeg+1) > COLS)
- { /* new point is outside current segment */
- while((pnt-sbeg+1) > COLS)
- sbeg += COLS/2;
- wmove(cmnd_w,C_LINE,0);
- wclrtoeol(cmnd_w);
- pmstr(sbeg); /* print string */
- }
- else
- { /* new point is inside current segment */
- waddstr(cmnd_w, kbuf);
- }
- }
- }
-
- /*----------------------- E O F -------------------------------------------*/
-