home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / most423.zip / search.c < prev    next >
C/C++ Source or Header  |  1994-01-28  |  6KB  |  248 lines

  1. #include <stdio.h>
  2.  
  3. #include "most.h"
  4. #include "externs.h"
  5. #include "buffer.h"
  6. #include "line.h"
  7. #include "file.h"
  8. #include "display.h"
  9. #include "window.h"
  10.  
  11. int CASE_SENSITIVE = 0;
  12. char SEARCH_STR[80];
  13. int SEARCH_DIR = 1;
  14.  
  15. #define upcase(ch) ((!CASE_SENSITIVE && (ch <= 'z') && (ch >= 'a')) ? ch &= 0xDF : ch)
  16.  
  17. /* This routine returns the 1 + position of first match of key in str.
  18.    key is modified to match the case of str. */
  19. /* We should try to optimize this routine */
  20. /* searches from beg up to but not including end */
  21. unsigned char *forw_search_region(unsigned char *beg,unsigned char *end, unsigned char *key)
  22. {
  23.     char ch, ch2,char1,work[80];
  24.     unsigned char *pos;
  25.     int key_len,j, str_len;
  26.  
  27.     if (CASE_SENSITIVE)
  28.       {
  29.           strcpy(work,key);
  30.           key_len = strlen(key);
  31.       }
  32.     else
  33.       {
  34.           /* upcase key */
  35.           key_len = 0;
  36.           while (ch = key[key_len],ch != '\0')
  37.             {
  38.                 ch = upcase(ch);
  39.                 work[key_len++] = ch;        /* null char is ok */
  40.             }
  41.       }
  42.     
  43.     str_len = (int) (end - beg);
  44.     if (str_len < key_len) return (EOB);
  45.     str_len = str_len - key_len; /* effective length */
  46.     end -= key_len;
  47.           
  48.     char1 = work[0];
  49.     
  50.     while(1)
  51.       {
  52.           while (ch = *beg, ch = upcase(ch), ch != char1)
  53.             {
  54.                 if (beg > end) return(EOB);
  55.                 beg++;
  56.             }
  57.           beg++;
  58.           /* so we have a position of possible match */
  59.  
  60.           j = 1;
  61.      pos = beg;  /* save this position so we start from here again */
  62.      while(1)
  63.        {
  64.           ch = *beg++;
  65.           if ((ch == 8) && (beg + 2 < end) &&  (MOST_V_OPT == 0) &&
  66.           ((work[j - 1] == upcase(*beg)) || (*beg == '_')))
  67.         {
  68.            ch = *(beg + 1);
  69.            beg += 2;
  70.         }
  71.           else if ((ch == '_') && (beg + 2 < end))
  72.         {
  73.            ch = *beg++;
  74.            if (ch == 8) ch = *beg++;
  75.            else 
  76.              {
  77.             ch = '_';
  78.             beg--;
  79.              }
  80.         }
  81.           ch = upcase(ch),
  82.           ch2 = work[j++];
  83.           if ((ch != ch2) || (j > key_len)) break;
  84.        }
  85.      
  86.  
  87.           if (j > key_len) return pos - 1;
  88.                 /* make key match 'key' in beg */
  89.      /* beg = pos - 1;   skip back to beginning of match 
  90.       for (j = 0; j < key_len; j++) key[j] = *beg++;
  91.       return(pos - 1); */
  92.           
  93.           else beg = pos;
  94.       }
  95. }
  96.  
  97.  
  98. unsigned char *back_search_region(unsigned char *beg,unsigned char *end, unsigned char *key)
  99. {
  100.     char ch, ch2,char1,work[80];
  101.     unsigned char *pos;
  102.     int key_len,j, str_len;
  103.  
  104.     if (CASE_SENSITIVE)
  105.       {
  106.           strcpy(work,key);
  107.           key_len = strlen(key);
  108.       }
  109.     else
  110.       {
  111.           /* upcase key */
  112.           key_len = 0;
  113.           while (ch = key[key_len],ch != '\0')
  114.             {
  115.                 ch = upcase(ch);
  116.                 work[key_len++] = ch;        /* null char is ok */
  117.             }
  118.       }
  119.     
  120.     str_len = (int) (end - beg);
  121.     if (str_len < key_len) return (EOB);
  122.     str_len = str_len - key_len; /* effective length */
  123.     beg += key_len;
  124.           
  125.     char1 = work[key_len - 1];
  126.     
  127.     while(1)
  128.       {
  129.           while (ch = *end, ch = upcase(ch), ch != char1)
  130.             {
  131.                 if (beg > end) return(EOB);
  132.                 end--;
  133.             }
  134.           end--;
  135.           /* so we have a position of possible match */
  136.  
  137.      j = key_len - 2;
  138.      pos = end;  /* save this position so we start from here again */
  139.  
  140.      while (1)
  141.        {
  142.           ch = *end--;
  143.           if ((ch == 8) && (beg <= end - 2) &&  (MOST_V_OPT == 0) &&
  144.           ((work[j + 1] == upcase(*end)) || (*end == '_')))
  145.         {
  146.            ch = *(end - 1);
  147.            end -= 2;
  148.         }
  149.           else if ((ch == '_') && (beg <= end - 2) && (MOST_V_OPT == 0))
  150.         {
  151.            ch = *end--;
  152.            if (ch == 8) ch = *end--;
  153.            else 
  154.              {
  155.             ch = '_';
  156.             end++;
  157.              }
  158.         }
  159.           ch = upcase(ch),
  160.           ch2 = work[j];
  161.           if ((ch != ch2) || (j < 0)) break;
  162.           j--;
  163.        }
  164.           if (j < 0) return end + 2;
  165.           else end = pos;
  166.       }
  167. }
  168.  
  169.  
  170.  
  171. int search(unsigned char *from, int repeat, int *col)
  172. {
  173.     /* return the line match was found as well as line number,
  174.        search from i on; assume that line_array match the i so we need
  175.        no initial lookup */
  176.  
  177.    int test, save_line, the_col, row, s_len;
  178.    char string[80];
  179.    unsigned char *pos;
  180.    int ofs, found_ofs, pos_ofs;
  181.  
  182.    if ((from < BEG) || (from > EOB)) return(-1);
  183.    ofs = C_POS - BEG;
  184.    save_line = C_LINE;
  185.    found_ofs = EOB - BEG;
  186.    *col = 0;
  187.    s_len = strlen(SEARCH_STR);
  188.    pos = from;
  189.    if (SEARCH_STR[0] != '\0')
  190.      {
  191.     test = repeat && (pos < EOB) && (pos >= BEG);
  192.     while(test)
  193.       {
  194.          if (SEARCH_DIR == 1)
  195.            {
  196.           more_time:
  197.           pos = forw_search_region(pos,EOB,(unsigned char*) SEARCH_STR);
  198.           if ((pos >= EOB) && (BUF->fd != -1)) 
  199.             {
  200.                pos_ofs = EOB - BEG;
  201.                read_file_dsc(10);
  202.                /* This might need an adjustment */
  203.                pos = BEG + (pos_ofs - s_len);
  204.                if (pos < BEG) pos = BEG;
  205.                goto more_time;
  206.             }
  207.            }
  208.          else
  209.          pos = back_search_region(BEG,pos,(unsigned char*) SEARCH_STR);
  210.            
  211.                 
  212.                 if (pos < EOB)
  213.                   {
  214.                       repeat--;
  215.                       found_ofs = pos - BEG;
  216.                       if (SEARCH_DIR == 1)
  217.                         pos += s_len;
  218.                       else pos--;
  219.                   }
  220.                 test = repeat && (pos < EOB) && (pos >= BEG);
  221.             }
  222.       }
  223.     
  224.     if (repeat) /* not found */
  225.       {
  226.           *col = 0;
  227.           if (SEARCH_STR[0] == '\0')
  228.             message("Search string not specified.",1);
  229.           else
  230.             {
  231.                 (void) sprintf(string,"%s NOT FOUND.",SEARCH_STR);
  232.                 message(string,1);
  233.             }
  234.           
  235.           row = -1;
  236.       }
  237.     else /* if ( !MOST_T_OPT && !MOST_B_OPT) */   /* expand tabs to get col correct */
  238.       {
  239.           find_row_column(BEG + found_ofs,&row,&the_col);
  240.           *col = apparant_distance(BEG + found_ofs);
  241.       }
  242.     C_POS = BEG + ofs;
  243.     C_LINE = save_line;
  244.     if (row > 0) CURS_POS = BEG + found_ofs;
  245.     return( row );
  246. }
  247.  
  248.