aboutsummaryrefslogtreecommitdiffstats
path: root/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'search.c')
-rw-r--r--search.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/search.c b/search.c
new file mode 100644
index 0000000..4182020
--- /dev/null
+++ b/search.c
@@ -0,0 +1,307 @@
+/* $Id: search.c,v 1.31 2004/03/23 16:44:02 ukai Exp $ */
+#include "fm.h"
+#include "regex.h"
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+
+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", conv_to_system(str));
+ again:
+ if (fflush(migemow) != 0) {
+ switch (errno) {
+ case EINTR:
+ goto again;
+ default:
+ goto err;
+ }
+ }
+ tmp = Str_conv_from_system(Strfgets(migemor));
+ Strchop(tmp);
+ if (tmp->length == 0)
+ goto err;
+ return conv_search_string(tmp->ptr, SystemCharset);
+ err:
+ /* XXX: backend migemo is not working? */
+ init_migemo();
+ migemo_active = migemo_running = 0;
+ return str;
+}
+#endif /* USE_MIGEMO */
+
+#ifdef USE_M17N
+/* normalize search string */
+char *
+conv_search_string(char *str, wc_ces f_ces)
+{
+ if (SearchConv && !WcOption.pre_conv &&
+ Currentbuf->document_charset != f_ces)
+ str = wtf_conv_fit(str, Currentbuf->document_charset);
+ return str;
+}
+#endif
+
+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;
+ if (l->bpos) {
+ pos += l->bpos;
+ while (l->bpos && l->prev)
+ l = l->prev;
+ }
+ begin = l;
+#ifdef USE_M17N
+ while (pos < l->size && l->propBuf[pos] & PC_WCHAR2)
+ 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 USE_M17N
+ while (pos > 0 && l->propBuf[pos] & PC_WCHAR2)
+ 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;
+ q++;
+#ifdef USE_M17N
+ while (q - l->lineBuf < l->size
+ && l->propBuf[q - l->lineBuf] & PC_WCHAR2)
+ q++;
+#endif
+ 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;
+ q++;
+#ifdef USE_M17N
+ while (q - l->lineBuf < l->size
+ && l->propBuf[q - l->lineBuf] & PC_WCHAR2)
+ q++;
+#endif
+ }
+ 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;
+}