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 }