home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / src / search.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  9.8 KB  |  504 lines

  1. /*
  2.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include "config.h"
  8. #include "slang.h"
  9. #include "buffer.h"
  10. #include "vfile.h"
  11. #include "search.h"
  12. #include "misc.h"
  13. #include "ins.h"
  14. #include "paste.h"
  15. #include "ledit.h"
  16.  
  17. int Case_Sensitive = 0;
  18. static SLsearch_Type Search_Struct;
  19.  
  20. int search(char *str, int dir, int n)
  21. {
  22.    unsigned char *beg, *end, *p;
  23.    Line *line;
  24.    int key_len;
  25.    unsigned int num = 0;
  26.  
  27.    if (0 == (key_len = SLsearch_init (str, dir, Case_Sensitive, &Search_Struct)))
  28.      return 0;
  29.    
  30.    line = CLine;
  31.  
  32.    if (dir == 1)
  33.      {
  34.     beg = line->data + Point;
  35.     end = line->data + line->len;
  36.     do
  37.       {
  38.          if (NULL != (p = SLsearch (beg, end, &Search_Struct)))
  39.            {
  40.           CLine = line;
  41.           LineNum += num;
  42.           Point = (int) (p - line->data);
  43.           return(1);
  44.            }
  45.          line = line->next; num++;
  46.          if (line == NULL) return(0);
  47.          beg = line->data;
  48.          end = line->data + line->len;
  49.       }
  50.     while(--n);
  51.      }
  52.    else if (dir == -1)
  53.      {
  54.     beg = line->data;
  55.     if (Point == 0) end = beg;
  56.     else
  57.       {
  58.          int tmp = Point - 1 + key_len;
  59.          if (tmp > line->len) tmp = line->len;
  60.          end = line->data + tmp;
  61.       }
  62.     
  63.     do
  64.       {
  65.          if (NULL != (p = SLsearch (beg, end, &Search_Struct)))
  66.            {
  67.           CLine = line;
  68.           LineNum -= num;
  69.  
  70.           Point = (int) (p - line->data);
  71.           return(1);
  72.            }
  73.          line = line->prev;
  74.          num++;
  75.          if (line == NULL) return(0);
  76.          beg = line->data;
  77.          end = line->data + line->len;
  78.       }
  79.     while (--n);
  80.      }
  81.    return(0);
  82. }
  83.  
  84. int search_forward(char *s)
  85. {
  86.    return( search(s, 1, 0));
  87. }
  88. int search_backward(char *s)
  89. {
  90.    return( search(s, -1, 0));
  91. }
  92.  
  93. int forward_search_line(char *s)
  94. {
  95.    return( search(s, 1, 1));
  96. }
  97.  
  98. int backward_search_line(char *s)
  99. {
  100.    return( search(s, -1, 1));
  101. }
  102.  
  103. #ifdef upcase
  104. #undef upcase
  105. #endif
  106.  
  107. #define upcase(ch) (cs ? ch : UPPER_CASE(ch))
  108.  
  109. int bol_search(char *str, int dir)
  110. {
  111.    Line *tthis;
  112.    int max, n, cs = Case_Sensitive;
  113.    unsigned int num;
  114.    unsigned char *s, ch1, ch2;
  115.    
  116.    max = strlen(str);
  117.    if ((dir > 0) && Point)
  118.      {
  119.     num = 1;
  120.     tthis = CLine->next;
  121.      }
  122.    else if ((dir < 0) && !Point)
  123.      {
  124.     tthis = CLine->prev;
  125.     num = 1;
  126.      }
  127.    else
  128.      {
  129.     tthis = CLine;
  130.     num = 0;
  131.      }   
  132.     
  133.    while (tthis != NULL)
  134.      {
  135.     if (max <= tthis->len)
  136.       {
  137.          s = tthis->data;
  138.          for (n = 0; n < max; n++)
  139.            {
  140.           ch1 = upcase(s[n]);
  141.           ch2 = upcase(str[n]);
  142.           if (ch1 != ch2) break;
  143.            }
  144.          if (n == max)
  145.            {
  146.           Point = 0;
  147.           CLine = tthis;
  148.           if (dir > 0) LineNum += num; else LineNum -= num;
  149.           return(1);
  150.            }
  151.       }
  152.     num++;
  153.     if (dir > 0) tthis = tthis->next; else tthis = tthis->prev;
  154.      }
  155.    return(0);
  156. }
  157.  
  158. int bol_fsearch(char *s)
  159. {
  160.    return bol_search(s, 1);
  161. }
  162.  
  163. int bol_bsearch(char *s)
  164. {
  165.    return bol_search(s, -1);
  166. }
  167.  
  168.  
  169. static SLRegexp_Type reg;
  170.  
  171. static int re_search_dir(unsigned char *pat, int dir)
  172. {
  173.    int psave, skip, n, epos;
  174.    unsigned char rbuf[512], *match;
  175.    Line *l;
  176.    
  177.    reg.case_sensitive = Case_Sensitive;
  178.    reg.buf = rbuf;
  179.    reg.pat = pat;
  180.    reg.buf_len = 512;
  181.    
  182.    if (SLang_regexp_compile(®)) 
  183.      {
  184.     msg_error("Unable to compile pattern.");
  185.     return(0);
  186.      }
  187.    
  188.    if (reg.osearch)
  189.      {
  190.     if (reg.must_match_bol)
  191.       {
  192.          if (!bol_search((char *) pat, dir)) return (0);
  193.       }
  194.     else if (!search((char *) pat, dir, 0)) return (0);
  195.     
  196.     reg.beg_matches[0] = Point;
  197.     n = strlen((char *) pat);
  198.     reg.end_matches[0] = n;
  199.     return n + 1;
  200.      }
  201.  
  202.    if (reg.must_match_bol)
  203.      {
  204.     if (dir < 0) 
  205.       {
  206.          if (Point == 0)
  207.            {
  208.           if (!backwchars(&Number_One)) return 0;
  209.            }
  210.       }
  211.     else if (Point)
  212.       {
  213.          if (CLine->next == NULL) return (0);
  214.          CLine = CLine->next; LineNum++; Point = 0;
  215.       }
  216.      }
  217.    
  218.    
  219.    if (reg.must_match && (0 != reg.must_match_str[1])) skip = 0; else skip = 1;
  220.    while (1)
  221.      {
  222.     psave = Point; 
  223.     if (!skip)
  224.       {
  225.          l = CLine;
  226.          if (!search((char *) reg.must_match_str, dir, 0)) return (0);
  227.  
  228.          if (l != CLine)
  229.            {
  230.           if (dir < 0) eol(); else Point = 0;
  231.           /* if ((dir == -1) && (!reg.must_match_bol)) eol(); else Point = 0; */
  232.           psave = Point;
  233.            }
  234.       }
  235.     
  236.     Point = psave;
  237.     if (dir == 1)
  238.       {
  239.          match = SLang_regexp_match(CLine->data + Point, CLine->len - Point, ®);
  240.          if (match != NULL)
  241.            {
  242.           /* adjust offsets */
  243.           reg.offset = Point;
  244.            }
  245.       }
  246.     
  247.     else if (NULL != (match = SLang_regexp_match(CLine->data,
  248.                              Point, /* was CLine->len */
  249.                              ®)))
  250.       {
  251.          if (Point && (reg.beg_matches[0] >= Point)) match = NULL;
  252.          else
  253.            {
  254.           epos = Point - 1;
  255.           /* found a match on line now find one closest to current point */
  256.           while (epos >= 0)
  257.             {
  258.                match = SLang_regexp_match(CLine->data + epos, 
  259.                           Point - epos, /* was: CLine->len - epos, */
  260.                           ®);
  261.                if (match != NULL) break;
  262.                epos--;
  263.             }
  264.            }
  265.       }
  266.     if (match != NULL)
  267.       {
  268.          Point = (int) (match - CLine->data);
  269.          n = reg.end_matches[0];
  270.          return (n + 1);
  271.       }
  272.     if (dir > 0)
  273.       {
  274.          if (CLine->next == NULL) break;
  275.          CLine = CLine->next; LineNum++; Point = 0;
  276.       }
  277.     else 
  278.       {
  279.          if (CLine->prev == NULL) break;
  280.          CLine = CLine->prev; LineNum--;
  281.          eol ();
  282.       }
  283.      }
  284.    return (0);
  285. }
  286.  
  287. int re_search_forward(char *pat)
  288. {
  289.    int n, p, len;
  290.    Line *l;
  291.    
  292.    p = Point; n = LineNum; l = CLine;
  293.    if (0 != (len = re_search_dir((unsigned char *) pat, 1))) return (len);
  294.    Point = p; LineNum = n; CLine = l;
  295.    return (0);
  296. }
  297.  
  298. int re_search_backward(char *pat)
  299. {
  300.    int n, p, len;
  301.    Line *l;
  302.    
  303.    p = Point; n = LineNum; l = CLine;
  304.    if (0 != (len = re_search_dir((unsigned char *) pat, -1))) return (len);
  305.    Point = p; LineNum = n; CLine = l;
  306.    return (0);
  307. }
  308.  
  309. int replace_match(char *s, int *literal)
  310. {
  311.    int n, nmax;
  312.    char ch;
  313.    unsigned char *p;
  314.    
  315.    if ((reg.pat == NULL) || (reg.beg_matches[0] == -1) 
  316.        || (reg.end_matches[0] + reg.beg_matches[0] + reg.offset >= CLine->len)) return (0);
  317.    
  318.    if (*literal)
  319.      {
  320.     Point = reg.beg_matches[0] + reg.offset;
  321.     n = reg.end_matches[0];
  322.     generic_deln(&n);
  323.     insert_string(s);
  324.     return (1);
  325.      }
  326.    /* This is painful --- \& means whole expression, \x x = 1..9 means a 
  327.       sub expression */
  328.    
  329.    /* must work with relative numbers since ins/del may do a realloc */
  330.    Point = reg.end_matches[0] + reg.offset + reg.beg_matches[0];
  331.    while ((ch = *s++) != 0)
  332.      {
  333.     if ((ch != '\\') || ((ch = *s++) == '\\'))
  334.       {
  335.          if (ch != '\n') ins(ch);
  336.          /* Note that I should do a 'newline' call.  However, as soon as
  337.             I do this, I lose the nth_match strings.  Clearly, I need to
  338.         re-think this!  */
  339.          continue;
  340.       }
  341.     if (ch == 0) break;
  342.     if (ch == '&') ch = '0';
  343.     
  344.     if ((ch >= '0') && (ch <= '9'))
  345.       {
  346.          nmax = ch - '0';
  347.          if ((n = reg.beg_matches[nmax]) == -1) continue;
  348.          nmax = reg.end_matches[nmax] + reg.beg_matches[nmax];
  349.       }
  350.     else continue;
  351.     
  352.     p = CLine->data + reg.offset;
  353.     while (n < nmax)
  354.       {
  355.          ins((char) *(p + n));
  356.          n++;
  357.       }
  358.      }
  359.    push_spot();
  360.    Point = reg.beg_matches[0] + reg.offset;
  361.    n = reg.end_matches[0];
  362.    generic_deln(&n);
  363.    pop_spot();
  364.    return (1);
  365. }
  366.  
  367.  
  368. static int push_string(char *b, int n)
  369. {
  370.    char *s;
  371.    s = (char *) SLMALLOC(n + 1);
  372.    if (s == NULL)
  373.      {
  374.     SLang_Error = SL_MALLOC_ERROR;
  375.     return (0);
  376.      }
  377.    if (n) MEMCPY(s, b, n);
  378.    *(s + n) = 0;
  379.    
  380.    SLang_push_malloced_string (s);
  381.    return (SLang_Error == 0);
  382. }
  383.       
  384. void regexp_nth_match (int *np)
  385. {
  386.    int b = 0, n = *np;
  387.    
  388.    if ((reg.pat == NULL) || (reg.beg_matches[0] == -1)
  389.        || (reg.end_matches[0] + reg.beg_matches[0] + reg.offset >= CLine->len))
  390.      {
  391.     SLang_Error = UNKNOWN_ERROR;
  392.     return;
  393.      }
  394.  
  395.    if ((n <= 0) || (n > 9)) n = 0;
  396.    else
  397.      {
  398.     if ((b = reg.beg_matches[n]) == -1) n = 0;
  399.     else
  400.       {
  401.          n = reg.end_matches[n];
  402.       }
  403.      }
  404.    b += reg.offset;
  405.    push_string((char *) CLine->data + b, n);
  406. }
  407.  
  408.  
  409.  
  410. int search_file(char *file, char *pat, int *np)
  411. {
  412.    unsigned char rbuf[512], *buf;
  413.    unsigned int n;
  414.    VFILE *vp;
  415.    int n_matches = 0, n_max = *np, key_len = 1;
  416.    
  417.    reg.case_sensitive = Case_Sensitive;
  418.    reg.buf = rbuf;
  419.    reg.pat = (unsigned char *) pat;
  420.    reg.buf_len = 512;
  421.    
  422.    if (SLang_regexp_compile(®)) 
  423.      {
  424.     msg_error("Unable to compile pattern.");
  425.     return(0);
  426.      }
  427.    
  428.    if (reg.osearch)
  429.      {
  430.         key_len = SLsearch_init ((char *) reg.pat, 1, reg.case_sensitive, &Search_Struct);
  431.      }
  432.    else if (reg.must_match)
  433.      {
  434.     key_len = SLsearch_init ((char *) reg.must_match_str, 1, reg.case_sensitive, &Search_Struct);
  435.      }
  436.  
  437.    if (!key_len) return 0;
  438.    if (NULL == (vp = vopen(file, 0, VFILE_TEXT))) return(0);
  439.    while (NULL != (buf = (unsigned char *) vgets(vp, &n)))
  440.      {
  441.     if (reg.must_match)
  442.       {
  443.          if (key_len > n) continue;
  444.          if (NULL == SLsearch (buf, buf + n, &Search_Struct))
  445.            {
  446.           continue;
  447.            }
  448.          if (reg.osearch) 
  449.            {
  450.           goto match_found;
  451.            }
  452.       }
  453.     
  454.     if (!SLang_regexp_match(buf, (int) n, ®)) continue;
  455.     
  456.     match_found:
  457.     n_matches++;
  458.     n_max--;
  459.     
  460.     if (!push_string((char *) buf, n) || (n_max == 0)) break;
  461.      }
  462.    vclose(vp);
  463.    return(n_matches);
  464. }
  465.  
  466. int insert_file_region (char *file, char *rbeg, char *rend)
  467. {
  468.    VFILE *vp;
  469.    unsigned int n;
  470.    unsigned int len = (unsigned int) strlen (rbeg);
  471.    int num = 0;
  472.    unsigned char *buf;
  473.    
  474.    if (NULL == (vp = vopen(file, 0, VFILE_TEXT))) return (-1);
  475.    
  476.    while (NULL != (buf = (unsigned char *) vgets(vp, &n)))
  477.      {
  478.     if (n < len) continue;
  479.     
  480.     if (!strncmp ((char *) buf, rbeg, len))
  481.       {
  482.          Suspend_Screen_Update = 1;
  483.          quick_insert(buf, (int) n);
  484.          num++;
  485.          
  486.          len = (unsigned int) strlen (rend);
  487.          
  488.          while(NULL != (buf = (unsigned char *) vgets(vp, &n)))
  489.            {
  490.           if ((n >= len) && !strncmp ((char *) buf, rend, len))
  491.             break;
  492.  
  493.           quick_insert(buf, (int) n);
  494.           if (SLang_Error) break;
  495.           num++;
  496.            }
  497.          break;
  498.       }
  499.      }
  500.    vclose (vp);
  501.    return num;
  502. }
  503.  
  504.