aboutsummaryrefslogblamecommitdiffstats
path: root/search.c
blob: f6ea92c1e45693e5bfe95808a9f3d0c3d0876bd8 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                         
                  
                   
                  
                   
 

                                    
                                              
                                   
 
                                             
                                             
                          
                          


             
                                                



                             
                   
                                  
                   



                                 
                                                  
                       
                  
                          
                   

                                                
     
             
       
                   
                                       









                                             
        
                               


                       
         
                            
                         
                    
      
                                             
                                       
               

                                                
   
                                     




                           
                 
                            






                                                                    
                                                      
                           
     
                         
                    
                           
     
                       




                                  


                                    
                                                                               
                                       
                                 
                                                           




                                         
                           
                                             
                        





















                                                 

                                                      


                                                                        
                                     
                                                               


                              

                                         
                                                 
                                                         


                                                      
                       

   
                                      
 
                                                    


                        
                 
                            






                                                                    
                                                      
                           
     
                         
                    
                           
     







                                  




                                        
                          
                       
                                                                               
                                           
                             
                              
                                  
                                          








                                                       
                                     
                                                               




                                             
                               
                                                       
                            











                                     
                          
                       
                                                                               


                                                                        
                  
                              
                                  
                                          






                                                       
                                     
                                                               


                              
                                         
                                                       
                                                         


                                                      
                       
 
/* $Id: search.c,v 1.27 2003/01/30 16:26:18 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 + 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);
	    if (wrapped && l == begin && buf->pos == first - l->lineBuf)
		/* exactly same match */
		break;
	    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);
	    if (wrapped && l == begin && buf->pos == first - l->lineBuf)
		/* exactly same match */
		;
	    else {
		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;
}