home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / screen-3.5.1 / part02 / search.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-08  |  7.8 KB  |  334 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: search.c,v 1.1.1.1 1993/06/16 23:51:17 jnweiger Exp $ FAU")
  25.  
  26. #include <sys/types.h>
  27.  
  28. #include "config.h"
  29. #include "screen.h"
  30. #include "mark.h"
  31. #include "extern.h"
  32.  
  33. #ifdef COPY_PASTE
  34.  
  35. extern struct win *fore;
  36. extern struct display *display;
  37.  
  38. /********************************************************************
  39.  *  VI style Search
  40.  */
  41.  
  42. static int  matchword __P((char *, int, int, int));
  43. static void searchend __P((char *, int));
  44. static void backsearchend __P((char *, int));
  45.  
  46. void
  47. Search(dir)
  48. int dir;
  49. {
  50.   struct markdata *markdata;
  51.   if (dir == 0)
  52.     {
  53.       markdata = (struct markdata *)d_lay->l_data;
  54.       if (markdata->isdir > 0)
  55.     searchend(0, 0);
  56.       else if (markdata->isdir < 0)
  57.     backsearchend(0, 0);
  58.       else
  59.     Msg(0, "No previous pattern");
  60.     }
  61.   else
  62.     Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr)-1, (dir > 0 ? searchend : backsearchend), INP_COOKED);
  63. }
  64.  
  65. static void
  66. searchend(buf, len)
  67. char *buf;
  68. int len;
  69. {
  70.   int x = 0, sx, ex, y;
  71.   struct markdata *markdata;
  72.  
  73.   markdata = (struct markdata *)d_lay->l_data;
  74.   markdata->isdir = 1;
  75.   if (len)
  76.     strcpy(markdata->isstr, buf);
  77.   sx = markdata->cx + 1;
  78.   ex = d_width - 1;
  79.   for (y = markdata->cy; y < fore->w_histheight + d_height; y++, sx = 0)
  80.     {
  81.       if ((x = matchword(markdata->isstr, y, sx, ex)) >= 0)
  82.         break;
  83.     }
  84.   if (y >= fore->w_histheight + d_height)
  85.     {
  86.       GotoPos(markdata->cx, W2D(markdata->cy));
  87.       Msg(0, "Pattern not found");
  88.     }
  89.   else
  90.     revto(x, y);
  91. }
  92.  
  93. static void
  94. backsearchend(buf, len)
  95. char *buf;
  96. int len;
  97. {
  98.   int sx, ex, x = -1, y;
  99.   struct markdata *markdata;
  100.  
  101.   markdata = (struct markdata *)d_lay->l_data;
  102.   markdata->isdir = -1;
  103.   if (len)
  104.     strcpy(markdata->isstr, buf);
  105.   ex = markdata->cx - 1;
  106.   for (y = markdata->cy; y >= 0; y--, ex = d_width - 1)
  107.     {
  108.       sx = 0;
  109.       while ((sx = matchword(markdata->isstr, y, sx, ex)) >= 0)
  110.     x = sx++;
  111.       if (x >= 0)
  112.     break;
  113.     }
  114.   if (y < 0)
  115.     {
  116.       GotoPos(markdata->cx, W2D(markdata->cy));
  117.       Msg(0, "Pattern not found");
  118.     }
  119.   else
  120.     revto(x, y);
  121. }
  122.  
  123. static int
  124. matchword(pattern, y, sx, ex)
  125. char *pattern;
  126. int y, sx, ex;
  127. {
  128.   char *ip, *ipe, *cp, *pp;
  129.  
  130.   ip = iWIN(y) + sx;
  131.   ipe = iWIN(y) + d_width;
  132.   for (;sx <= ex; sx++)
  133.     {
  134.       cp = ip++;
  135.       pp = pattern;
  136.       while (*cp++ == *pp++)
  137.     if (*pp == 0)
  138.       return sx;
  139.     else if (cp == ipe)
  140.       break;
  141.     }
  142.   return -1;
  143. }
  144.  
  145.  
  146. /********************************************************************
  147.  *  Emacs style ISearch
  148.  */
  149.  
  150. static char *isprompts[] = {
  151.   "I-search backward: ", "failing I-search backward: ",
  152.   "I-search: ", "failing I-search: "
  153. };
  154.  
  155.  
  156. static int  is_redo __P((struct markdata *));
  157. static void is_process __P((char *, int));
  158. static int  is_bm __P((char *, int, int, int, int));
  159.  
  160.  
  161. static int
  162. is_bm(str, l, p, end, dir)
  163. char *str;
  164. int l, p, end, dir;
  165. {
  166.   int tab[256];
  167.   int i, q;
  168.   char *s, c;
  169.   int w = d_width;
  170.  
  171.   debug2("is_bm: searching for %s len %d\n", str, l);
  172.   debug3("start at %d end %d dir %d\n", p, end, dir);
  173.   if (p < 0 || p + l > end)
  174.     return -1;
  175.   if (l == 0)
  176.     return p;
  177.   if (dir < 0)
  178.     str += l - 1;
  179.   for (i = 0; i < 256; i++)
  180.     tab[i] = l * dir;
  181.   for (i = 0; i < l - 1; i++, str += dir)
  182.     tab[(int)(unsigned char) *str] = (l - 1 - i) * dir;
  183.   if (dir > 0)
  184.     p += l - 1;
  185.   debug1("first char to match: %c\n", *str);
  186.   while (p >= 0 && p < end)
  187.     {
  188.       q = p;
  189.       s = str;
  190.       for (i = 0;;)
  191.     {
  192.           c = iWIN(q / w)[q % w];
  193.       if (i == 0)
  194.             p += tab[(int)(unsigned char) c];
  195.       if (c != *s)
  196.         break;
  197.       q -= dir;
  198.       s -= dir;
  199.       if (++i == l)
  200.         return q + (dir > 0 ? 1 : -l);
  201.     }
  202.     }
  203.   return -1;
  204. }
  205.  
  206.  
  207. /*ARGSUSED*/
  208. static void
  209. is_process(p, n)
  210. char *p;
  211. int n;
  212. {
  213.   int pos, x, y, dir;
  214.   struct markdata *markdata;
  215.  
  216.   if (n == 0)
  217.     return;
  218.   markdata = (struct markdata *)d_lay->l_next->l_data;
  219.   ASSERT(p);
  220.  
  221.   pos = markdata->cx + markdata->cy * d_width;
  222.   GotoPos(markdata->cx, W2D(markdata->cy));
  223.  
  224.   switch (*p)
  225.     {
  226.     case '\007':    /* CTRL-G */
  227.       pos = markdata->isstartpos;
  228.       /*FALLTHROUGH*/
  229.     case '\033':    /* ESC */
  230.       *p = 0;
  231.       break;
  232.     case '\013':    /* CTRL-K */
  233.     case '\027':    /* CTRL-W */
  234.       markdata->isistrl = 1;
  235.       /*FALLTHROUGH*/
  236.     case '\b':
  237.     case '\177':
  238.       if (markdata->isistrl == 0)
  239.     return;
  240.       markdata->isistrl--;
  241.       pos = is_redo(markdata);
  242.       *p = '\b';
  243.       break;
  244.     case '\023':    /* CTRL-S */
  245.     case '\022':     /* CTRL-R */
  246.       if (markdata->isistrl >= sizeof(markdata->isistr))
  247.     return;
  248.       dir = (*p == '\023') ? 1 : -1;
  249.       pos += dir;
  250.       if (markdata->isdir == dir && markdata->isistrl == 0)
  251.     {
  252.       strcpy(markdata->isistr, markdata->isstr);
  253.       markdata->isistrl = markdata->isstrl = strlen(markdata->isstr);
  254.       break;
  255.     }
  256.       markdata->isdir = dir;
  257.       markdata->isistr[markdata->isistrl++] = *p;
  258.       break;
  259.     default:
  260.       if (*p < ' ' || markdata->isistrl >= sizeof(markdata->isistr)
  261.       || markdata->isstrl >= sizeof(markdata->isstr) - 1)
  262.     return;
  263.       markdata->isstr[markdata->isstrl++] = *p;
  264.       markdata->isistr[markdata->isistrl++] = *p;
  265.       markdata->isstr[markdata->isstrl] = 0;
  266.       debug2("New char: %c - left %d\n", *p, sizeof(markdata->isistr) - markdata->isistrl);
  267.     }
  268.   if (*p && *p != '\b')
  269.     pos = is_bm(markdata->isstr, markdata->isstrl, pos, d_width * (fore->w_histheight + d_height), markdata->isdir);
  270.   if (pos >= 0)
  271.     {
  272.       x = pos % d_width;
  273.       y = pos / d_width;
  274.       LAY_CALL_UP
  275.     (
  276.           RefreshLine(STATLINE, 0, d_width - 1, 0);
  277.           revto(x, y);
  278.           if (W2D(markdata->cy) == STATLINE)
  279.         {
  280.           revto_line(markdata->cx, markdata->cy, STATLINE > 0 ? STATLINE - 1 : 1);
  281.         }
  282.         );
  283.     }
  284.   if (*p)
  285.     inp_setprompt(isprompts[markdata->isdir + (pos < 0) + 1], markdata->isstrl ? markdata->isstr : "");
  286.   GotoPos(markdata->cx, W2D(markdata->cy));
  287. }
  288.  
  289. static int
  290. is_redo(markdata)
  291. struct markdata *markdata;
  292. {
  293.   int i, pos, dir;
  294.   char c;
  295.  
  296.   pos = markdata->isstartpos;
  297.   dir = markdata->isstartdir;
  298.   markdata->isstrl = 0;
  299.   for (i = 0; i < markdata->isistrl; i++)
  300.     {
  301.       c = markdata->isistr[i];
  302.       if (c == '\022')
  303.     pos += (dir = -1);
  304.       else if (c == '\023')
  305.     pos += (dir = 1);
  306.       else
  307.     markdata->isstr[markdata->isstrl++] = c;
  308.       if (pos >= 0)
  309.         pos = is_bm(markdata->isstr, markdata->isstrl, pos, d_width * (fore->w_histheight + d_height), dir);
  310.     }
  311.   markdata->isstr[markdata->isstrl] = 0;
  312.   markdata->isdir = dir;
  313.   return pos;
  314. }
  315.  
  316. void
  317. ISearch(dir)
  318. int dir;
  319. {
  320.   struct markdata *markdata;
  321.   markdata = (struct markdata *)d_lay->l_data;
  322.   markdata->isdir = markdata->isstartdir = dir;
  323.   markdata->isstartpos = markdata->cx + markdata->cy * d_width;
  324.   markdata->isistrl = markdata->isstrl = 0;
  325.   if (W2D(markdata->cy) == STATLINE)
  326.     {
  327.       revto_line(markdata->cx, markdata->cy, STATLINE > 0 ? STATLINE - 1 : 1);
  328.     }
  329.   Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, is_process, INP_RAW);
  330.   GotoPos(markdata->cx, W2D(markdata->cy));
  331. }
  332.  
  333. #endif /* COPY_PASTE */
  334.