#include "config.h" #include #include #include "most.h" #include "window.h" #include "line.h" #include "file.h" #include "display.h" int Most_Case_Sensitive = 0; char Most_Search_Str[256]; int Most_Search_Dir = 1; #define upcase(ch) ((!Most_Case_Sensitive && (ch <= 'z') && (ch >= 'a')) ? ch &= 0xDF : ch) /* This routine returns the 1 + position of first match of key in str. key is modified to match the case of str. */ /* We should try to optimize this routine */ /* searches from beg up to but not including end */ static unsigned char *forw_search_region(unsigned char *beg,unsigned char *end, unsigned char *key) { char ch, ch2,char1,work[256]; unsigned char *pos; int key_len,j, str_len; if (Most_Case_Sensitive) { strcpy(work, (char *) key); key_len = strlen((char *) key); } else { /* upcase key */ key_len = 0; while (ch = key[key_len],ch != '\0') { ch = upcase(ch); work[key_len++] = ch; /* null char is ok */ } } str_len = (int) (end - beg); if (str_len < key_len) return (Most_Eob); str_len = str_len - key_len; /* effective length */ end -= key_len; char1 = work[0]; while(1) { while (ch = *beg, ch = upcase(ch), ch != char1) { if (beg > end) return(Most_Eob); beg++; } beg++; /* so we have a position of possible match */ j = 1; pos = beg; /* save this position so we start from here again */ while(1) { ch = *beg++; if ((ch == 8) && (beg + 2 < end) && (Most_V_Opt == 0) && ((work[j - 1] == upcase(*beg)) || (*beg == '_'))) { ch = *(beg + 1); beg += 2; } else if ((ch == '_') && (beg + 2 < end)) { ch = *beg++; if (ch == 8) ch = *beg++; else { ch = '_'; beg--; } } ch = upcase(ch), ch2 = work[j++]; if ((ch != ch2) || (j > key_len)) break; } if (j > key_len) return pos - 1; /* make key match 'key' in beg */ /* beg = pos - 1; skip back to beginning of match for (j = 0; j < key_len; j++) key[j] = *beg++; return(pos - 1); */ else beg = pos; } } static unsigned char *back_search_region(unsigned char *beg,unsigned char *end, unsigned char *key) { char ch, ch2,char1,work[256]; unsigned char *pos; int key_len,j, str_len; if (Most_Case_Sensitive) { strcpy(work, (char *) key); key_len = strlen((char *) key); } else { /* upcase key */ key_len = 0; while (ch = key[key_len],ch != '\0') { ch = upcase(ch); work[key_len++] = ch; /* null char is ok */ } } str_len = (int) (end - beg); if (str_len < key_len) return (Most_Eob); str_len = str_len - key_len; /* effective length */ beg += key_len; char1 = work[key_len - 1]; while(1) { while (ch = *end, ch = upcase(ch), ch != char1) { if (beg > end) return(Most_Eob); end--; } end--; /* so we have a position of possible match */ j = key_len - 2; pos = end; /* save this position so we start from here again */ while (1) { ch = *end--; if ((ch == 8) && (beg <= end - 2) && (Most_V_Opt == 0) && ((work[j + 1] == upcase(*end)) || (*end == '_'))) { ch = *(end - 1); end -= 2; } else if ((ch == '_') && (beg <= end - 2) && (Most_V_Opt == 0)) { ch = *end--; if (ch == 8) ch = *end--; else { ch = '_'; end++; } } ch = upcase(ch), ch2 = work[j]; if ((ch != ch2) || (j < 0)) break; j--; } if (j < 0) return end + 2; else end = pos; } } int most_search(unsigned char *from, int repeat, int *col) { /* return the line match was found as well as line number, search from i on; assume that line_array match the i so we need no initial lookup */ int test, save_line, the_col, row, s_len; char string[300]; unsigned char *pos; int ofs, found_ofs, pos_ofs; if ((from < Most_Beg) || (from > Most_Eob)) return(-1); ofs = Most_C_Pos - Most_Beg; save_line = Most_C_Line; found_ofs = Most_Eob - Most_Beg; *col = 0; s_len = strlen(Most_Search_Str); pos = from; if (Most_Search_Str[0] != '\0') { test = repeat && (pos < Most_Eob) && (pos >= Most_Beg); while(test) { if (Most_Search_Dir == 1) { more_time: pos = forw_search_region(pos,Most_Eob,(unsigned char*) Most_Search_Str); if ((pos >= Most_Eob) && (Most_Buf->fd != -1)) { pos_ofs = Most_Eob - Most_Beg; most_read_file_dsc(10); /* This might need an adjustment */ pos = Most_Beg + (pos_ofs - s_len); if (pos < Most_Beg) pos = Most_Beg; goto more_time; } } else pos = back_search_region(Most_Beg,pos,(unsigned char*) Most_Search_Str); if (pos < Most_Eob) { repeat--; found_ofs = pos - Most_Beg; if (Most_Search_Dir == 1) pos += s_len; else pos--; } test = repeat && (pos < Most_Eob) && (pos >= Most_Beg); } } if (repeat) /* not found */ { *col = 0; if (Most_Search_Str[0] == '\0') most_message("Search string not specified.",1); else { (void) sprintf(string,"Search failed: %s",Most_Search_Str); most_message(string,1); } row = -1; } else /* if ( !Most_T_Opt && !Most_B_Opt) */ /* expand tabs to get col correct */ { most_find_row_column(Most_Beg + found_ofs,&row,&the_col); if (Most_B_Opt) *col = the_col + 40; else *col = 1 + most_apparant_distance(Most_Beg + found_ofs); } Most_C_Pos = Most_Beg + ofs; Most_C_Line = save_line; if (row > 0) Most_Curs_Pos = Most_Beg + found_ofs; return( row ); }