home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume39 / cwish / part02 / history.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-22  |  14.2 KB  |  507 lines

  1. /*---------------------------------------------------------------------------*
  2.  *
  3.  *                  wish - windowing user friendly shell
  4.  *                  ------------------------------------
  5.  *
  6.  *               Copyright (c) 1988-1993 Hellmuth Michaelis
  7.  *
  8.  *                  Eggerstedtstr. 28
  9.  *                  22765 Hamburg
  10.  *                  Germany
  11.  *
  12.  *                  Tel:    +49 / 40 / 384298    (private)
  13.  *                  Tel:    +49 / 40 / 55903-170 (at work)
  14.  *                  e-mail: hm@hcshh.hcs.de
  15.  *
  16.  *                          --------oOo--------
  17.  *
  18.  *   This program is free software; you can redistribute it and/or modify
  19.  *   it under the terms of the GNU General Public License as published by
  20.  *   the Free Software Foundation; either version 2 of the License, or
  21.  *   (at your option) any later version.
  22.  *
  23.  *   This program is distributed in the hope that it will be useful,
  24.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  25.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26.  *   GNU General Public License for more details.
  27.  *
  28.  *   You should have received a copy of the GNU General Public License
  29.  *   along with this program; if not, write to the Free Software
  30.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  31.  *
  32.  *---------------------------------------------------------------------------*
  33.  *
  34.  *    last edit-date: [Wed Sep 22 13:28:09 1993]
  35.  *
  36.  *    -hm    history on commandline
  37.  *    -hm    integrating line handling from terminal.c from my sh
  38.  *    -hm    debugging line editor
  39.  *
  40.  *---------------------------------------------------------------------------*/ 
  41.  
  42. #include "wish.h"        /* local includes */
  43.  
  44. static char overstrike;        /* overstrike mode */
  45. static char kbuf[HISLNLEN];    /* kill buffer */
  46. static int  kbuf_init = 0;    /* static kill buffer */
  47. static char *beg;        /* line start      (first char on line)    */
  48. static char *pnt;        /* next insertion position     (cursor)    */
  49. static char *end;        /* line end    (first free pos on line)    */
  50. static char *sbeg;        /* first character on screen        */
  51. static int lmax;        /* maximum charcount requested from caller */
  52.  
  53. static void pmstr(char *);        /* forward decl */
  54. static void pnstr(int, char *);
  55. void dis_hist(void);
  56.  
  57. /*---------------------------------------------------------------------------*
  58.  *    return current (cursor) column
  59.  *---------------------------------------------------------------------------*/
  60. int curcol(void)
  61. {
  62.     return((int)(pnt - sbeg));
  63. }
  64.  
  65. /*---------------------------------------------------------------------------*
  66.  *    return true, if commandline empty ( == operate on file window on CR )
  67.  *---------------------------------------------------------------------------*/
  68. int cr_on_files(void)
  69. {
  70.     return((int)(beg == end));
  71. }
  72.  
  73. /*---------------------------------------------------------------------------*
  74.  *    init commandline history system
  75.  *---------------------------------------------------------------------------*/
  76. void init_history(void)
  77. {
  78.     overstrike = 0;        /* insert is default */
  79.     
  80.     cur_his = 0;        /* current history pointer */
  81.     strcpy(cbuff,hislines[cur_his]);
  82.  
  83.     sbeg = cbuff;        /* screen begin at start of buffer */
  84.     beg = cbuff + strlen(cbuff);    /* position beg after prompt */
  85.     pnt = end = beg;    /* point = end = buffer begin */
  86.  
  87.     kbuf[0] = '\0';        /* init kill - buffer */
  88.     kbuf_init = 1;        /* static kbuf */
  89.     
  90.     lmax = HISLNLEN-1;    /* max line length */
  91.  
  92.     wmove(cmnd_w,C_LINE,0);    /* beg of line */
  93.     waddstr(cmnd_w, cbuff);    /* write prompt */
  94. }    
  95.  
  96. /*---------------------------------------------------------------------------*
  97.  *    save current commandline to history stack
  98.  *---------------------------------------------------------------------------*/
  99. void save_line(void)
  100. {
  101.     strncpy(hislines[cur_his],cbuff,HISLNLEN-1);
  102.     if(cur_his == HISLINES-1)
  103.         cur_his = 0;
  104.     else
  105.         cur_his++;
  106.     hislines[cur_his][3] = '\0';    
  107.     dis_hist();
  108. }    
  109.  
  110. /*---------------------------------------------------------------------------*
  111.  *    get previous history line
  112.  *---------------------------------------------------------------------------*/
  113. void prev_line(void)
  114. {
  115.     if(cur_his == 0)
  116.         cur_his = HISLINES-1;
  117.     else
  118.         cur_his--;
  119.  
  120.     dis_hist();
  121. }
  122.  
  123. /*---------------------------------------------------------------------------*
  124.  *    get next history line
  125.  *---------------------------------------------------------------------------*/
  126. void next_line(void)
  127. {
  128.     if(cur_his == HISLINES-1)
  129.         cur_his = 0;
  130.     else
  131.         cur_his++;
  132.  
  133.     dis_hist();
  134. }
  135.  
  136. /*---------------------------------------------------------------------------*
  137.  *    valid new line from history stack, display it
  138.  *---------------------------------------------------------------------------*/
  139. void dis_hist(void)
  140. {
  141.     strncpy(cbuff,hislines[cur_his],HISLNLEN-1);
  142.     
  143.     if((strlen(cbuff)) < COLS)
  144.     {                 /* new line will fit onto screen */
  145.         wmove(cmnd_w,C_LINE,0);    /* move to start of line */
  146.         wclrtoeol(cmnd_w);    /* clear line */
  147.         wmove(cmnd_w,C_LINE,0);    /* move to start of line */
  148.         waddstr(cmnd_w, cbuff);    /* write new line */
  149.         sbeg = cbuff;        /* new screen begin */
  150.     }
  151.     else
  152.     { /* line will not fit onto screen, search end & write new */
  153.         wmove(cmnd_w,C_LINE,0);        /* start of line */
  154.         wclrtoeol(cmnd_w);        /* clear to end of line */
  155.         sbeg = cbuff;            /* start of buffer */
  156.         while((strlen(sbeg) + 1) > COLS) /* find segment */
  157.             sbeg += COLS/2;        /*             start */
  158.         waddstr(cmnd_w, sbeg);        /* write last segment */
  159.     }
  160.     pnt = end = (cbuff + strlen(cbuff));
  161.     beg = cbuff + 3;    /* position beg after prompt */    
  162. }
  163.  
  164. /*---------------------------------------------------------------------------*
  165.  *        move cursor forward
  166.  *---------------------------------------------------------------------------*/
  167. void right_line(void)
  168. {
  169.     if(pnt < end)        /* something to move ? */
  170.     {
  171.         pnt++;        /* next char */
  172.         if(pnt > (sbeg + COLS))    /* moving on screen ? */
  173.         {
  174.             sbeg += COLS/2;    /* new screen begin */
  175.             wmove(cmnd_w,C_LINE,0);    /* start of screen */
  176.             wclrtoeol(cmnd_w);    /* clear line */
  177.             pmstr(sbeg);        /* write new segment */
  178.         }
  179.     }
  180. }
  181.  
  182. /*---------------------------------------------------------------------------*
  183.  *        move cursor back one character
  184.  *---------------------------------------------------------------------------*/
  185. void left_line(void)
  186. {
  187.     if(pnt > beg)    /* allowed to move ?? */
  188.     {
  189.         pnt--;            /* prev char */
  190.         if(pnt < sbeg)        /* move on screen ?? */
  191.         {
  192.             sbeg -= COLS/2;    /* back 1/2 length */
  193.             wmove(cmnd_w,C_LINE,0);    /* start of screen */
  194.             wclrtoeol(cmnd_w);    /* clear line */
  195.             pmstr(sbeg);        /* print this part of buffer */
  196.         }
  197.     }
  198. }
  199.  
  200. /*---------------------------------------------------------------------------*
  201.  *    append / insert / overstrike a (printable) character
  202.  *---------------------------------------------------------------------------*/
  203. int cmdline(int c)
  204. {
  205.     if((end-beg) < lmax)    /* space in buffer ? */
  206.     {
  207.         if(pnt == end)    /************ append **********/
  208.         {
  209.             *pnt++ = c;        /* store char */
  210.             end++;            /* new end ptr */
  211.             *end = '\0';        /* new terminator */
  212.  
  213.             if((end-sbeg+1) > COLS)
  214.             {
  215.                 sbeg += COLS/2;
  216.                 wmove(cmnd_w,C_LINE,0);
  217.                 wclrtoeol(cmnd_w);
  218.                 waddstr(cmnd_w, sbeg);
  219.             }
  220.             else
  221.             {
  222.                 waddch(cmnd_w,c);    /* echo char */
  223.             }
  224.         }
  225.         else if(!overstrike)    /************** insert **********/
  226.         {
  227.             register char *p;
  228.             register char *q;
  229.  
  230.             p = end-1;        /* last char */
  231.             q = end;        /* last char + 1 */
  232.             while(q > pnt)        /* shift right buffer */
  233.                 *q-- = *p--;
  234.  
  235.             *pnt = c;        /* store chr into gap */
  236.             end++;            /* increment end ptr */
  237.             *end = '\0';        /* new terminator */
  238.             
  239.             if( (pnt+1) > (sbeg + COLS)) /* scroll right ? */
  240.             {
  241.                 sbeg += COLS/2;    /* new screen beg */
  242.             }
  243.             wmove(cmnd_w,C_LINE,0);    /* start of line */
  244.             pmstr(sbeg);        /* print string */
  245.             pnt++;            /* new point */
  246.         }
  247.         else        /**************    overstrike ****************/
  248.         {
  249.             *pnt++ = c;        /* store char */
  250.  
  251.             if((pnt-sbeg+1) > COLS)
  252.             {
  253.                 sbeg += COLS/2;
  254.                 wmove(cmnd_w,C_LINE,0);
  255.                 wclrtoeol(cmnd_w);
  256.                 pmstr(sbeg);
  257.             }
  258.             else
  259.             {
  260.                 waddch(cmnd_w,c);    /* echo char */
  261.             }
  262.         }
  263.         return(GOOD);
  264.     }
  265.     else
  266.     {
  267.         flash();    /* no no .. */
  268.         return(BAD);    /* don't accept it */
  269.     }
  270. }
  271.  
  272. /*---------------------------------------------------------------------------*
  273.  *        delete character left of cursor
  274.  *---------------------------------------------------------------------------*/
  275. void handlebs(void)
  276. {
  277.     register char *p;
  278.     register char *q;
  279.  
  280.     if(pnt == beg)        /* at start of buffer ? */
  281.         return;        /* yes */
  282.  
  283.     q = pnt;        /* next char */
  284.     pnt--;            /* point backward */
  285.     p = pnt;        /* this char */
  286.     while(q < end)        /* shift left buffer */
  287.         *p++ = *q++;
  288.     end--;            /* new end pointer */
  289.     *end = '\0';        /* new end terminator */
  290.  
  291.     if(pnt < sbeg)            /* moved into previous segment ? */
  292.     {
  293.         sbeg -= COLS/2;        /* new segment start */
  294.     }
  295.     wmove(cmnd_w,C_LINE,0);    /* start of screen line */
  296.     wclrtoeol(cmnd_w);    /* clear line */
  297.     pmstr(sbeg);        /* write segment */
  298. }
  299.  
  300. /*---------------------------------------------------------------------------*
  301.  *        delete character under cursor
  302.  *---------------------------------------------------------------------------*/
  303. void del_char(void)
  304. {
  305.     register char *p;
  306.     register char *q;
  307.  
  308.     if(pnt == end)        /* at start of buffer ? */
  309.         return;        /* yes */
  310.  
  311.     p = pnt;        /* current char */
  312.     q = pnt+1;        /* next char */
  313.  
  314.     while(q < end)        /* shift left buffer */
  315.         *p++ = *q++;
  316.  
  317.     end--;            /* new end pointer */
  318.     *end = '\0';        /* new end terminator */
  319.  
  320.     wmove(cmnd_w,C_LINE,0);    /* start of screen line */
  321.     wclrtoeol(cmnd_w);    /* clear line */
  322.     pmstr(sbeg);        /* write new segment */
  323. }
  324.  
  325. /*---------------------------------------------------------------------------*
  326.  *        print string, maximum length is COLS
  327.  *---------------------------------------------------------------------------*/
  328. static void pmstr(char *str)
  329. {
  330.     char buf[256];
  331.     register int i = 0;
  332.     
  333.     while((*str) && (i < COLS))
  334.         buf[i++] = *str++;
  335.     buf[i] = '\0';
  336.     waddstr(cmnd_w, buf);
  337. }
  338.  
  339. /*---------------------------------------------------------------------------*
  340.  *        print string, maximum length parameter <n>
  341.  *---------------------------------------------------------------------------*/
  342. static void pnstr(int n, char *str)
  343. {
  344.     char buf[256];
  345.     register int i = 0;
  346.     
  347.     while((*str) && (i < n))
  348.         buf[i++] = *str++;
  349.     buf[i] = '\0';
  350.     waddstr(cmnd_w, buf);
  351. }
  352.  
  353. /*---------------------------------------------------------------------------*
  354.  *         delete from cursor to end of line
  355.  *---------------------------------------------------------------------------*/
  356. void clear_toeol(void)
  357. {
  358.     strcpy(kbuf, pnt);    /* save to kill buffer */
  359.     wclrtoeol(cmnd_w);    /* clear line */
  360.     end = pnt;        /* new end ptr */
  361.     *end = '\0';        /* terminate line */
  362. }
  363.  
  364. /*---------------------------------------------------------------------------*
  365.  *        move cursor to end of line
  366.  *---------------------------------------------------------------------------*/
  367. void eol_line(void)
  368. {
  369.     if(pnt == end)        /* already at end ? */
  370.         return;        /* yes */
  371.  
  372.     if((strlen(cbuff) < COLS) && (sbeg == cbuff))
  373.     {
  374.         pnt = end;    /* set point to end */
  375.     }        
  376.     else
  377.     {
  378.         wmove(cmnd_w,C_LINE,0);    /* start of line */
  379.         wclrtoeol(cmnd_w);    /* clear to end of line */
  380.         sbeg = cbuff;        /* start of buffer */
  381.         while((strlen(sbeg) + 1) > COLS) /* find segment */
  382.             sbeg += COLS/2;        /*             start */
  383.         waddstr(cmnd_w, sbeg);    /* write last segment */
  384.         pnt = end;        /* new point */
  385.     }
  386. }    
  387.  
  388. /*---------------------------------------------------------------------------*
  389.  *         move cursor to begin of line
  390.  *---------------------------------------------------------------------------*/
  391. void bol_line(void)
  392. {
  393.     if(pnt == beg)            /* already at begin of buffer */
  394.         return;            /* nothing to do ! */
  395.  
  396.     pnt = beg;            /* point = buffer start */
  397.     
  398.     if(sbeg != cbuff)        /* not in first screen segment */
  399.     {
  400.         wmove(cmnd_w,C_LINE,0);    /* cursor -> start of screen */
  401.         wclrtoeol(cmnd_w);    /* clear to end of line */
  402.         pmstr(cbuff);        /* write from start of buffer */
  403.         sbeg = cbuff;        /* screen begin = buffer start */
  404.     }
  405. }
  406.  
  407. /*---------------------------------------------------------------------------*
  408.  *        yank text from kill-buffer to current point
  409.  *---------------------------------------------------------------------------*/
  410. void yank(void)
  411. {
  412.     if(kbuf[0] == '\0')    /* kill buffer empty ? */
  413.         return;        /* yes, exit */
  414.  
  415.     if((end - beg) >= lmax)             /* space in buffer ? */
  416.     {                     /* no... */
  417.         if((overstrike) && (pnt == end)) /* perhaps overstr in the middle ? */
  418.             return;             /* no... */
  419.         if(!overstrike)             /* insert / append ? */
  420.             return;             /* yes */
  421.     }
  422.  
  423.     /* here if either space in buffer or overwrite not at end */
  424.         
  425.     if(pnt == end)        /************ append **********/
  426.     {
  427.         /* append kill buffer to buffer, observe buffer max length */
  428.         
  429.         strncat(cbuff, kbuf, lmax);
  430.         end = cbuff + strlen(cbuff);
  431.         if((end-sbeg+1) > COLS)
  432.         {
  433.             while((end-sbeg+1) > COLS)
  434.                 sbeg += COLS/2;
  435.             wmove(cmnd_w,C_LINE,0);
  436.             wclrtoeol(cmnd_w);
  437.             waddstr(cmnd_w, sbeg);    /* write whole new segment */
  438.         }
  439.         else
  440.         {
  441.             waddstr(cmnd_w, pnt);    /* write new end */
  442.         }
  443.         pnt = end;        /* set new pnt */
  444.     }
  445.     else if(!overstrike)    /************** insert **********/
  446.     {
  447.         char tail[HISLNLEN];    /* temp storage */
  448.         register int i;        /* gp... */
  449.         register char *p = pnt;    /* save point pos */
  450.         
  451.         strcpy(tail, pnt);    /* save string frm point on */
  452.         strncpy(pnt, kbuf, lmax); /* insert up to max */
  453.         pnt = cbuff + strlen(cbuff);
  454.         strcat(pnt, tail);    /* append saved tail */
  455.         end = cbuff + strlen(cbuff);
  456.  
  457.         if((pnt-sbeg+1) > COLS)
  458.         { /* new point is outside current segment */
  459.             while((pnt-sbeg+1) > COLS)
  460.                 sbeg += COLS/2;
  461.             wmove(cmnd_w,C_LINE,0);
  462.             wclrtoeol(cmnd_w);
  463.             pmstr(sbeg);        /* print string */
  464.         }
  465.         else
  466.         { /* new point is inside current segment */
  467.             if((strlen(sbeg)) < COLS) /* line > than screen ? */
  468.                 i = (sbeg + strlen(sbeg)) - p; /* no */
  469.             else
  470.                 i = (sbeg + COLS) - p; /* yes */
  471.             pnstr(i, p);        /* new tail */
  472.             p += i;
  473.             while(p-- > pnt)
  474.                 wmove(cmnd_w, C_LINE, (curcol()-1));
  475.         }
  476.     }
  477.     else        /**************    overstrike ****************/
  478.     {
  479.         register int j = lmax;
  480.         register char *k = kbuf;
  481.         
  482.         while(j-- && *k)
  483.             *pnt++ = *k++;    /* copy kbuf over buffer */
  484.         
  485.         if(pnt > end)    /* buffer grown bigger ? */
  486.         {
  487.             end = pnt;    /* set new end ptr */
  488.             *end = '\0';    /* terminate buffer */
  489.         }
  490.  
  491.         if((pnt-sbeg+1) > COLS)
  492.         { /* new point is outside current segment */
  493.             while((pnt-sbeg+1) > COLS)
  494.                 sbeg += COLS/2;
  495.             wmove(cmnd_w,C_LINE,0);
  496.             wclrtoeol(cmnd_w);
  497.             pmstr(sbeg);        /* print string */
  498.         }
  499.         else
  500.         { /* new point is inside current segment */
  501.             waddstr(cmnd_w, kbuf);
  502.         }
  503.     }
  504. }
  505.  
  506. /*----------------------- E O F -------------------------------------------*/
  507.