w3m

Unnamed repository; edit this file to name it for gitweb.
git clone https://logand.com/git/w3m.git/
Log | Files | Refs | README

search.c (6536B)


      1 /* $Id$ */
      2 #include "fm.h"
      3 #include "regex.h"
      4 #include <signal.h>
      5 #include <errno.h>
      6 #include <unistd.h>
      7 
      8 static void
      9 set_mark(Line *l, int pos, int epos)
     10 {
     11     for (; pos < epos && pos < l->size; pos++)
     12 	l->propBuf[pos] |= PE_MARK;
     13 }
     14 
     15 #ifdef USE_MIGEMO
     16 /* Migemo: romaji --> kana+kanji in regexp */
     17 static FILE *migemor = NULL, *migemow = NULL;
     18 static int migemo_running;
     19 static int migemo_pid = 0;
     20 
     21 void
     22 init_migemo()
     23 {
     24     migemo_active = migemo_running = use_migemo;
     25     if (migemor != NULL)
     26 	fclose(migemor);
     27     if (migemow != NULL)
     28 	fclose(migemow);
     29     migemor = migemow = NULL;
     30     if (migemo_pid)
     31 	kill(migemo_pid, SIGKILL);
     32     migemo_pid = 0;
     33 }
     34 
     35 static int
     36 open_migemo(char *migemo_command)
     37 {
     38     migemo_pid = open_pipe_rw(&migemor, &migemow);
     39     if (migemo_pid < 0)
     40 	goto err0;
     41     if (migemo_pid == 0) {
     42 	/* child */
     43 	setup_child(FALSE, 2, -1);
     44 	myExec(migemo_command);
     45 	/* XXX: ifdef __EMX__, use start /f ? */
     46     }
     47     return 1;
     48   err0:
     49     migemo_pid = 0;
     50     migemo_active = migemo_running = 0;
     51     return 0;
     52 }
     53 
     54 static char *
     55 migemostr(char *str)
     56 {
     57     Str tmp = NULL;
     58     if (migemor == NULL || migemow == NULL)
     59 	if (open_migemo(migemo_command) == 0)
     60 	    return str;
     61     fprintf(migemow, "%s\n", conv_to_system(str));
     62   again:
     63     if (fflush(migemow) != 0) {
     64 	switch (errno) {
     65 	case EINTR:
     66 	    goto again;
     67 	default:
     68 	    goto err;
     69 	}
     70     }
     71     tmp = Str_conv_from_system(Strfgets(migemor));
     72     Strchop(tmp);
     73     if (tmp->length == 0)
     74 	goto err;
     75     return conv_search_string(tmp->ptr, SystemCharset);
     76   err:
     77     /* XXX: backend migemo is not working? */
     78     init_migemo();
     79     migemo_active = migemo_running = 0;
     80     return str;
     81 }
     82 #endif				/* USE_MIGEMO */
     83 
     84 #ifdef USE_M17N
     85 /* normalize search string */
     86 char *
     87 conv_search_string(char *str, wc_ces f_ces)
     88 {
     89     if (SearchConv && !WcOption.pre_conv &&
     90 	Currentbuf->document_charset != f_ces)
     91 	str = wtf_conv_fit(str, Currentbuf->document_charset);
     92     return str;
     93 }
     94 #endif
     95 
     96 int
     97 forwardSearch(Buffer *buf, char *str)
     98 {
     99     char *p, *first, *last;
    100     Line *l, *begin;
    101     int wrapped = FALSE;
    102     int pos;
    103 
    104 #ifdef USE_MIGEMO
    105     if (migemo_active > 0) {
    106 	if (((p = regexCompile(migemostr(str), IgnoreCase)) != NULL)
    107 	    && ((p = regexCompile(str, IgnoreCase)) != NULL)) {
    108 	    message(p, 0, 0);
    109 	    return SR_NOTFOUND;
    110 	}
    111     }
    112     else
    113 #endif
    114     if ((p = regexCompile(str, IgnoreCase)) != NULL) {
    115 	message(p, 0, 0);
    116 	return SR_NOTFOUND;
    117     }
    118     l = buf->currentLine;
    119     if (l == NULL) {
    120 	return SR_NOTFOUND;
    121     }
    122     pos = buf->pos;
    123     if (l->bpos) {
    124 	pos += l->bpos;
    125 	while (l->bpos && l->prev)
    126 	    l = l->prev;
    127     }
    128     begin = l;
    129 #ifdef USE_M17N
    130     while (pos < l->size && l->propBuf[pos] & PC_WCHAR2)
    131 	pos++;
    132 #endif
    133     if (pos < l->size && regexMatch(&l->lineBuf[pos], l->size - pos, 0) == 1) {
    134 	matchedPosition(&first, &last);
    135 	pos = first - l->lineBuf;
    136 	while (pos >= l->len && l->next && l->next->bpos) {
    137 	    pos -= l->len;
    138 	    l = l->next;
    139 	}
    140 	buf->pos = pos;
    141 	if (l != buf->currentLine)
    142 	    gotoLine(buf, l->linenumber);
    143 	arrangeCursor(buf);
    144 	set_mark(l, pos, pos + last - first);
    145 	return SR_FOUND;
    146     }
    147     for (l = l->next;; l = l->next) {
    148 	if (l == NULL) {
    149 	    if (buf->pagerSource) {
    150 		l = getNextPage(buf, 1);
    151 		if (l == NULL) {
    152 		    if (WrapSearch && !wrapped) {
    153 			l = buf->firstLine;
    154 			wrapped = TRUE;
    155 		    }
    156 		    else {
    157 			break;
    158 		    }
    159 		}
    160 	    }
    161 	    else if (WrapSearch) {
    162 		l = buf->firstLine;
    163 		wrapped = TRUE;
    164 	    }
    165 	    else {
    166 		break;
    167 	    }
    168 	}
    169 	if (l->bpos)
    170 	    continue;
    171 	if (regexMatch(l->lineBuf, l->size, 1) == 1) {
    172 	    matchedPosition(&first, &last);
    173 	    pos = first - l->lineBuf;
    174 	    while (pos >= l->len && l->next && l->next->bpos) {
    175 		pos -= l->len;
    176 		l = l->next;
    177 	    }
    178 	    buf->pos = pos;
    179 	    buf->currentLine = l;
    180 	    gotoLine(buf, l->linenumber);
    181 	    arrangeCursor(buf);
    182 	    set_mark(l, pos, pos + last - first);
    183 	    return SR_FOUND | (wrapped ? SR_WRAPPED : 0);
    184 	}
    185 	if (wrapped && l == begin)	/* no match */
    186 	    break;
    187     }
    188     return SR_NOTFOUND;
    189 }
    190 
    191 int
    192 backwardSearch(Buffer *buf, char *str)
    193 {
    194     char *p, *q, *found, *found_last, *first, *last;
    195     Line *l, *begin;
    196     int wrapped = FALSE;
    197     int pos;
    198 
    199 #ifdef USE_MIGEMO
    200     if (migemo_active > 0) {
    201 	if (((p = regexCompile(migemostr(str), IgnoreCase)) != NULL)
    202 	    && ((p = regexCompile(str, IgnoreCase)) != NULL)) {
    203 	    message(p, 0, 0);
    204 	    return SR_NOTFOUND;
    205 	}
    206     }
    207     else
    208 #endif
    209     if ((p = regexCompile(str, IgnoreCase)) != NULL) {
    210 	message(p, 0, 0);
    211 	return SR_NOTFOUND;
    212     }
    213     l = buf->currentLine;
    214     if (l == NULL) {
    215 	return SR_NOTFOUND;
    216     }
    217     pos = buf->pos;
    218     if (l->bpos) {
    219 	pos += l->bpos;
    220 	while (l->bpos && l->prev)
    221 	    l = l->prev;
    222     }
    223     begin = l;
    224     if (pos > 0) {
    225 	pos--;
    226 #ifdef USE_M17N
    227 	while (pos > 0 && l->propBuf[pos] & PC_WCHAR2)
    228 	    pos--;
    229 #endif
    230 	p = &l->lineBuf[pos];
    231 	found = NULL;
    232 	found_last = NULL;
    233 	q = l->lineBuf;
    234 	while (regexMatch(q, &l->lineBuf[l->size] - q, q == l->lineBuf) == 1) {
    235 	    matchedPosition(&first, &last);
    236 	    if (first <= p) {
    237 		found = first;
    238 		found_last = last;
    239 	    }
    240 	    if (q - l->lineBuf >= l->size)
    241 		break;
    242 	    q++;
    243 #ifdef USE_M17N
    244 	    while (q - l->lineBuf < l->size
    245 		   && l->propBuf[q - l->lineBuf] & PC_WCHAR2)
    246 		q++;
    247 #endif
    248 	    if (q > p)
    249 		break;
    250 	}
    251 	if (found) {
    252 	    pos = found - l->lineBuf;
    253 	    while (pos >= l->len && l->next && l->next->bpos) {
    254 		pos -= l->len;
    255 		l = l->next;
    256 	    }
    257 	    buf->pos = pos;
    258 	    if (l != buf->currentLine)
    259 		gotoLine(buf, l->linenumber);
    260 	    arrangeCursor(buf);
    261 	    set_mark(l, pos, pos + found_last - found);
    262 	    return SR_FOUND;
    263 	}
    264     }
    265     for (l = l->prev;; l = l->prev) {
    266 	if (l == NULL) {
    267 	    if (WrapSearch) {
    268 		l = buf->lastLine;
    269 		wrapped = TRUE;
    270 	    }
    271 	    else {
    272 		break;
    273 	    }
    274 	}
    275 	found = NULL;
    276 	found_last = NULL;
    277 	q = l->lineBuf;
    278 	while (regexMatch(q, &l->lineBuf[l->size] - q, q == l->lineBuf) == 1) {
    279 	    matchedPosition(&first, &last);
    280 	    found = first;
    281 	    found_last = last;
    282 	    if (q - l->lineBuf >= l->size)
    283 		break;
    284 	    q++;
    285 #ifdef USE_M17N
    286 	    while (q - l->lineBuf < l->size
    287 		   && l->propBuf[q - l->lineBuf] & PC_WCHAR2)
    288 		q++;
    289 #endif
    290 	}
    291 	if (found) {
    292 	    pos = found - l->lineBuf;
    293 	    while (pos >= l->len && l->next && l->next->bpos) {
    294 		pos -= l->len;
    295 		l = l->next;
    296 	    }
    297 	    buf->pos = pos;
    298 	    gotoLine(buf, l->linenumber);
    299 	    arrangeCursor(buf);
    300 	    set_mark(l, pos, pos + found_last - found);
    301 	    return SR_FOUND | (wrapped ? SR_WRAPPED : 0);
    302 	}
    303 	if (wrapped && l == begin)	/* no match */
    304 	    break;
    305     }
    306     return SR_NOTFOUND;
    307 }