/* $Id: search.c,v 1.28 2003/03/05 18:19:17 ukai Exp $ */ #include "fm.h" #include "regex.h" #include #include #include static void set_mark(Line *l, int pos, int epos) { for (; pos < epos && pos < l->size; pos++) l->propBuf[pos] |= PE_MARK; } #ifdef USE_MIGEMO /* Migemo: romaji --> kana+kanji in regexp */ static FILE *migemor = NULL, *migemow = NULL; static int migemo_running; static int migemo_pid = 0; void init_migemo() { migemo_active = migemo_running = use_migemo; if (migemor != NULL) fclose(migemor); if (migemow != NULL) fclose(migemow); migemor = migemow = NULL; if (migemo_pid) kill(migemo_pid, SIGKILL); migemo_pid = 0; } static int open_migemo(char *migemo_command) { migemo_pid = open_pipe_rw(&migemor, &migemow); if (migemo_pid < 0) goto err0; if (migemo_pid == 0) { /* child */ setup_child(FALSE, 2, -1); myExec(migemo_command); /* XXX: ifdef __EMX__, use start /f ? */ } return 1; err0: migemo_pid = 0; migemo_active = migemo_running = 0; return 0; } static char * migemostr(char *str) { Str tmp = NULL; if (migemor == NULL || migemow == NULL) if (open_migemo(migemo_command) == 0) return str; fprintf(migemow, "%s\n", str); again: if (fflush(migemow) != 0) { switch (errno) { case EINTR: goto again; default: goto err; } } tmp = Strfgets(migemor); Strchop(tmp); if (tmp->length == 0) goto err; return tmp->ptr; err: /* XXX: backend migemo is not working? */ init_migemo(); migemo_active = migemo_running = 0; return str; } #endif /* USE_MIGEMO */ int forwardSearch(Buffer *buf, char *str) { char *p, *first, *last; Line *l, *begin; int wrapped = FALSE; int pos; #ifdef USE_MIGEMO if (migemo_active > 0) { if (((p = regexCompile(migemostr(str), IgnoreCase)) != NULL) && ((p = regexCompile(str, IgnoreCase)) != NULL)) { message(p, 0, 0); return SR_NOTFOUND; } } else #endif if ((p = regexCompile(str, IgnoreCase)) != NULL) { message(p, 0, 0); return SR_NOTFOUND; } l = buf->currentLine; if (l == NULL) { return SR_NOTFOUND; } pos = buf->pos + 1; if (l->bpos) { pos += l->bpos; while (l->bpos && l->prev) l = l->prev; } begin = l; #ifdef JP_CHARSET if (l->propBuf[pos] & PC_KANJI2) pos++; #endif if (pos < l->size && regexMatch(&l->lineBuf[pos], l->size - pos, 0) == 1) { matchedPosition(&first, &last); pos = first - l->lineBuf; while (pos >= l->len && l->next && l->next->bpos) { pos -= l->len; l = l->next; } buf->pos = pos; if (l != buf->currentLine) gotoLine(buf, l->linenumber); arrangeCursor(buf); set_mark(l, pos, pos + last - first); return SR_FOUND; } for (l = l->next;; l = l->next) { if (l == NULL) { if (buf->pagerSource) { l = getNextPage(buf, 1); if (l == NULL) { if (WrapSearch && !wrapped) { l = buf->firstLine; wrapped = TRUE; } else { break; } } } else if (WrapSearch) { l = buf->firstLine; wrapped = TRUE; } else { break; } } if (l->bpos) continue; if (regexMatch(l->lineBuf, l->size, 1) == 1) { matchedPosition(&first, &last); pos = first - l->lineBuf; while (pos >= l->len && l->next && l->next->bpos) { pos -= l->len; l = l->next; } buf->pos = pos; buf->currentLine = l; gotoLine(buf, l->linenumber); arrangeCursor(buf); set_mark(l, pos, pos + last - first); return SR_FOUND | (wrapped ? SR_WRAPPED : 0); } if (wrapped && l == begin) /* no match */ break; } return SR_NOTFOUND; } int backwardSearch(Buffer *buf, char *str) { char *p, *q, *found, *found_last, *first, *last; Line *l, *begin; int wrapped = FALSE; int pos; #ifdef USE_MIGEMO if (migemo_active > 0) { if (((p = regexCompile(migemostr(str), IgnoreCase)) != NULL) && ((p = regexCompile(str, IgnoreCase)) != NULL)) { message(p, 0, 0); return SR_NOTFOUND; } } else #endif if ((p = regexCompile(str, IgnoreCase)) != NULL) { message(p, 0, 0); return SR_NOTFOUND; } l = buf->currentLine; if (l == NULL) { return SR_NOTFOUND; } pos = buf->pos; if (l->bpos) { pos += l->bpos; while (l->bpos && l->prev) l = l->prev; } begin = l; if (pos > 0) { pos--; #ifdef JP_CHARSET if (l->propBuf[pos] & PC_KANJI2) pos--; #endif p = &l->lineBuf[pos]; found = NULL; found_last = NULL; q = l->lineBuf; while (regexMatch(q, &l->lineBuf[l->size] - q, q == l->lineBuf) == 1) { matchedPosition(&first, &last); if (first <= p) { found = first; found_last = last; } if (q - l->lineBuf >= l->size) break; #ifdef JP_CHARSET if (l->propBuf[q - l->lineBuf] & PC_KANJI1) q += 2; else #endif q++; if (q > p) break; } if (found) { pos = found - l->lineBuf; while (pos >= l->len && l->next && l->next->bpos) { pos -= l->len; l = l->next; } buf->pos = pos; if (l != buf->currentLine) gotoLine(buf, l->linenumber); arrangeCursor(buf); set_mark(l, pos, pos + found_last - found); return SR_FOUND; } } for (l = l->prev;; l = l->prev) { if (l == NULL) { if (WrapSearch) { l = buf->lastLine; wrapped = TRUE; } else { break; } } found = NULL; found_last = NULL; q = l->lineBuf; while (regexMatch(q, &l->lineBuf[l->size] - q, q == l->lineBuf) == 1) { matchedPosition(&first, &last); found = first; found_last = last; if (q - l->lineBuf >= l->size) break; #ifdef JP_CHARSET if (l->propBuf[q - l->lineBuf] & PC_KANJI1) q += 2; else #endif q++; } if (found) { pos = found - l->lineBuf; while (pos >= l->len && l->next && l->next->bpos) { pos -= l->len; l = l->next; } buf->pos = pos; gotoLine(buf, l->linenumber); arrangeCursor(buf); set_mark(l, pos, pos + found_last - found); return SR_FOUND | (wrapped ? SR_WRAPPED : 0); } if (wrapped && l == begin) /* no match */ break; } return SR_NOTFOUND; }