home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / me34src.zip / me3 / ed / history.c < prev    next >
C/C++ Source or Header  |  1995-01-14  |  4KB  |  144 lines

  1. /* history.c : general purpose remember lines of text for recall.
  2.  *   It looks like a stack with semi-random access.  The stack is fixed size
  3.  *   with all addations being at the top with a pointer to the interior of
  4.  *   the stack.  Old entries are pushed off the bottom as the stack
  5.  *   overflows.
  6.  *     --Bottom-->|oldest entry| ... |most recent entry|<--Top--
  7.  * Things a history package needs to implement:
  8.  *   Hsize(n): set the size of the history buffer to n bytes.
  9.  *      ??? how get
  10.  *   Hnext():  Move the stack pointer to the next entry (toward Top).
  11.  *     TRUE if successful, FALSE if can't move.
  12.  *   Hprev():  Move the stack pointer to the previous entry (toward Bottom).
  13.  *     TRUE if successful, FALSE if can't move.
  14.  *   Htop():  Move history pointer to Top (most recent entry of the history
  15.  *     stack).
  16.  *   Hbottom():  Move history pointer to Bottom (the oldest entry of the
  17.  *     history stack).
  18.  *   Hcurrent():  Return pointer to current history entry.
  19.  *   Hsearch(direction,matcher) pfi matcher;
  20.  *     Search for a pattern.  Matcher is called for each entry.  If a match
  21.  *       is found, Hsearch returns a pointer to it and leave pointer at the
  22.  *       entry else return NULL and don't move pointer.
  23.  *     The current entry is not matched.
  24.  *     The caller has to mess with the pattern.
  25.  *   Hadd(text):  Add a history entry to the end to the history stack.
  26.  *     Updates the pointer.
  27.  *   ?Hentries() : return the number of entries in the stack.
  28.  * C Durland
  29.  */
  30.  
  31. /* Copyright 1990, 1991 Craig Durland
  32.  *   Distributed under the terms of the GNU General Public License.
  33.  *   Distributed "as is", without warranties of any kind, but comments,
  34.  *     suggestions and bug reports are welcome.
  35.  */
  36.  
  37. #include <const.h>
  38. #include "led.h"
  39.  
  40. #define HBUFSIZE 1000
  41.  
  42. static char *get_hist();
  43. static int Hentries();
  44.  
  45. static int nth_hist = 0, num_hists = 0;
  46.  
  47. void Htop() { nth_hist = num_hists; }
  48. void Hbottom() { nth_hist = 0; }
  49.  
  50. char *Hcurrent()
  51. {
  52.   char *ptr = get_hist(nth_hist);
  53.   return ptr ? ptr : "";
  54. }
  55.  
  56. Hnext()
  57. {
  58.   if (nth_hist < num_hists-1) { ++nth_hist; return TRUE; }
  59.   return FALSE;
  60. }
  61.  
  62. Hprev()
  63. {
  64.   if (0 < nth_hist) { --nth_hist; return TRUE; }
  65.   return FALSE;
  66. }
  67.  
  68. char *Hsearch(search_forward,matcher) int (*matcher)();
  69. {
  70.   register char *ptr;
  71.   register int j;
  72.  
  73.   if (search_forward)
  74.   {
  75.     for (j = nth_hist+1; j < num_hists; j++)
  76.       if ((*matcher)(ptr = get_hist(j)))
  77.       {
  78.       found_it:
  79.     nth_hist = j;
  80.           return ptr;
  81.       }
  82.   }
  83.   else        /* search backwards */
  84.   {
  85.     for (j = nth_hist-1; 0 <= j; j-- )
  86.       if ((*matcher)(ptr = get_hist(j))) goto found_it;
  87.   }
  88.   return NULL;
  89. }
  90.  
  91. static char history[HBUFSIZE+1];
  92. static int hsize = HBUFSIZE, hidx = 0;
  93.  
  94.     /* Add test to the Top of the history stack.  If there is enough room in
  95.      *   the stack, just add text.  If not enough room, remove entries from
  96.      *   the Bottom of the stack until there is.
  97.      *   Notes:
  98.      *     Given:  len <= hsize
  99.      *       you can show: len -(hsize -hidx) <= hidx
  100.      *     Given:  len > (hsize -hidx)
  101.      *       you can show: len -(hsize -hidx) > 0
  102.      *     All entries are terminated by '\0' so if i < hidx, there is a
  103.      *       '\0' before i++ reaches hidx.
  104.      */
  105. int Hadd(text) char *text;
  106. {
  107.   int i,j, len = strlen(text) +1;
  108.  
  109.   if (len < 3) return TRUE;
  110.   if (hsize < len) return FALSE;    /* text won't fit in buffer */
  111.   Htop(); Hprev(); if (strcmp(Hcurrent(),text)==0) return TRUE;
  112.  
  113.   if (len>(hsize -hidx))    /* not enough room */
  114.   {
  115.     if ((i = len -(hsize -hidx)) < hidx) while (history[i++]) ;
  116.     j = i; i = 0; while (j<hidx) history[i++] = history[j++];
  117.     hidx = i;
  118.   }
  119.   strcpy(&history[hidx],text); hidx += len;
  120.   num_hists = Hentries();
  121.   Htop();
  122.   return TRUE;
  123. }
  124.  
  125. /* ******************************************************************** */
  126. /* ******************************************************************** */
  127. /* ******************************************************************** */
  128.  
  129. static int Hentries()        /* return the number of history lines */
  130. {
  131.   int j, n = 0;
  132.  
  133.   for (j = 0; j<hidx; j++) if (history[j]=='\0') n++;
  134.   return n;
  135. }
  136.  
  137. static char *get_hist(n)    /* return the nth line of the history */
  138. {
  139.   int j;
  140.  
  141.   for (j = 0; j<hidx && 0<n; j++) if (history[j]=='\0') n--;
  142.   return (n==0 && j<hidx) ? &history[j] : NULL;
  143. }
  144.