/* $Id: search.c,v 1.29 2003/03/05 18:56:30 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", 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;
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;
}