예제 #1
0
파일: search.c 프로젝트: ricksladkey/vile
/* extra args -- marking if called from globals, and should mark lines, and
	fromscreen, if the searchpattern is on the screen, so we don't need to
	ask for it.  */
int
fsearch(int f, int n, int marking, int fromscreen)
{
    int status = TRUE;
    int wrapok;
    MARK curpos;
    int didmark = FALSE;
    int didwrap;

    assert(curwp != 0);

    if (f && n < 0)
	return rsearch(f, -n, FALSE, FALSE);

    if (n == 0)
	n = 1;

    wrapok = marking || window_b_val(curwp, MDWRAPSCAN);

    last_srch_direc = FORWARD;

    /* ask the user for a regular expression to search for.  if
     * "marking", then we were called to do line marking for the
     * global command.
     */

    if (!marking) {
	status = readpattern("Search: ", &searchpat, &gregexp,
			     lastkey, fromscreen);
	if (status != TRUE)
	    return status;
    }

    ignorecase = window_b_val(curwp, MDIGNCASE);

    if (curwp == 0)
	return FALSE;

    curpos = DOT;
    scanboundry(wrapok, curpos, FORWARD);
    didwrap = FALSE;
    while (marking || n--) {
	movenext(&(DOT), FORWARD);
	status = scanner(gregexp, FORWARD, wrapok, &didwrap);
	if (status == ABORT) {
	    mlwarn("[Aborted]");
	    DOT = curpos;
	    return status;
	}
	/* if found, mark the line */
	if (status && marking) {
	    /* if we were on a match when we started, then
	       scanner returns TRUE, even though it's
	       on a boundary. quit if we find ourselves
	       marking a line twice */
	    if (lismarked(DOT.l))
		break;
	    lsetmarked(DOT.l);
	    /* and, so the next movenext gets to next line */
	    DOT.o = llength(DOT.l);
	    didmark = TRUE;
	}
	if (!marking && didwrap) {
	    mlwrite("[Search wrapped past end of buffer]");
	    didwrap = FALSE;
	}
	if (status != TRUE)
	    break;
    }

    if (!marking && !status)
	movenext(&(DOT), REVERSE);

    if (marking) {		/* restore dot and offset */
	DOT = curpos;
    } else if (status) {
	savematch(DOT, gregexp->mlen);
	if (samepoint(DOT, curpos)) {
	    mlwrite(onlyonemsg);
	}
    }

    /* Complain if not there.  */
    if ((marking && didmark == FALSE) ||
	(!marking && status == FALSE)) {
	not_found_msg(wrapok, FORWARD);
	return FALSE;
    }

    attrib_matches();
    return TRUE;
}
예제 #2
0
파일: search.c 프로젝트: ricksladkey/vile
/*
 * backhunt -- repeat previous forward search
 */
int
backhunt(int f, int n)
{
    int status = TRUE;
    int wrapok;
    MARK curpos;
    int didwrap;

    assert(curwp != 0);

    wrapok = window_b_val(curwp, MDWRAPSCAN);

    if (f && n < 0)		/* search forwards */
	return (forwhunt(f, -n));

    if (n == 0)
	n = 1;

    /* Make sure a pattern exists */
    if (tb_length(searchpat) == 0) {
	mlforce("[No pattern set]");
	return FALSE;
    }

    ignorecase = window_b_val(curwp, MDIGNCASE);

    if (curwp == 0)
	return FALSE;

    /* find n'th occurrence of pattern
     */
    curpos = DOT;
    scanboundry(wrapok, DOT, REVERSE);
    didwrap = FALSE;
    while (n--) {
	movenext(&(DOT), REVERSE);
	status = scanner(gregexp, REVERSE, wrapok, &didwrap);
	if (didwrap) {
	    mlwrite("[Search wrapped past start of buffer]");
	    didwrap = FALSE;
	}
	if (status != TRUE)
	    break;
    }

    if (status == TRUE) {
	savematch(DOT, gregexp->mlen);
	if (samepoint(DOT, curpos)) {
	    mlwrite(onlyonemsg);
	}
    } else if (status == FALSE) {
	movenext(&(DOT), FORWARD);
	not_found_msg(wrapok, REVERSE);
    } else if (status == ABORT) {
	mlwarn("[Aborted]");
	DOT = curpos;
	return status;
    }

    attrib_matches();
    return status;
}
예제 #3
0
파일: search.c 프로젝트: mahyarap/nano
/* Look for needle, starting at (current, current_x).  begin is the line
 * where we first started searching, at column begin_x.  The return
 * value specifies whether we found anything.  If we did, set needle_len
 * to the length of the string we found if it isn't NULL. */
bool findnextstr(
#ifndef DISABLE_SPELLER
	bool whole_word_only,
#endif
	const filestruct *begin, size_t begin_x,
	const char *needle, size_t *needle_len)
{
    size_t found_len;
	/* The length of the match we find. */
    size_t current_x_find = 0;
	/* The location in the current line of the match we find. */
    ssize_t current_y_find = openfile->current_y;
    filestruct *fileptr = openfile->current;
    const char *rev_start = fileptr->data, *found = NULL;
    time_t lastkbcheck = time(NULL);

    /* rev_start might end up 1 character before the start or after the
     * end of the line.  This won't be a problem because strstrwrapper()
     * will return immediately and say that no match was found, and
     * rev_start will be properly set when the search continues on the
     * previous or next line. */
    rev_start +=
#ifndef NANO_TINY
	ISSET(BACKWARDS_SEARCH) ?
	((openfile->current_x == 0) ? -1 : move_mbleft(fileptr->data, openfile->current_x)) :
#endif
	move_mbright(fileptr->data, openfile->current_x);

    /* Look for needle in the current line we're searching. */
    enable_nodelay();
    while (TRUE) {
	if (time(NULL) - lastkbcheck > 1) {
	    int input = parse_kbinput(edit);

	    lastkbcheck = time(NULL);

	    if (input && func_from_key(&input) == do_cancel) {
		statusbar(_("Cancelled"));
		return FALSE;
	    }
	}

	found = strstrwrapper(fileptr->data, needle, rev_start);

	/* We've found a potential match. */
	if (found != NULL) {
#ifndef DISABLE_SPELLER
	    bool found_whole = FALSE;
		/* Is this potential match a whole word? */
#endif

	    /* Set found_len to the length of the potential match. */
	    found_len =
#ifdef HAVE_REGEX_H
		ISSET(USE_REGEXP) ?
		regmatches[0].rm_eo - regmatches[0].rm_so :
#endif
		strlen(needle);

#ifndef DISABLE_SPELLER
	    /* If we're searching for whole words, see if this potential
	     * match is a whole word. */
	    if (whole_word_only) {
		char *word = mallocstrncpy(NULL, found, found_len + 1);
		word[found_len] = '\0';

		found_whole = is_whole_word(found - fileptr->data,
			fileptr->data, word);
		free(word);
	    }

	    /* If we're searching for whole words and this potential
	     * match isn't a whole word, continue searching. */
	    if (!whole_word_only || found_whole)
#endif
		break;
	}

	if (search_last_line) {
	    /* We've finished processing the file, so get out. */
	    not_found_msg(needle);
	    disable_nodelay();
	    return FALSE;
	}

	/* Move to the previous or next line in the file. */
#ifndef NANO_TINY
	if (ISSET(BACKWARDS_SEARCH)) {
	    fileptr = fileptr->prev;
	    current_y_find--;
	} else {
#endif
	    fileptr = fileptr->next;
	    current_y_find++;
#ifndef NANO_TINY
	}
#endif

	if (fileptr == NULL) {
	    /* We've reached the start or end of the buffer, so wrap around. */
#ifndef NANO_TINY
	    if (ISSET(BACKWARDS_SEARCH)) {
		fileptr = openfile->filebot;
		current_y_find = editwinrows - 1;
	    } else {
#endif
		fileptr = openfile->fileage;
		current_y_find = 0;
#ifndef NANO_TINY
	    }
#endif
	    statusbar(_("Search Wrapped"));
	}

	if (fileptr == begin)
	    /* We've reached the original starting line. */
	    search_last_line = TRUE;

	rev_start = fileptr->data;
#ifndef NANO_TINY
	if (ISSET(BACKWARDS_SEARCH))
	    rev_start += strlen(fileptr->data);
#endif
    }

    /* We found an instance. */
    current_x_find = found - fileptr->data;

    /* Ensure we haven't wrapped around again! */
    if (search_last_line &&
#ifndef NANO_TINY
	((!ISSET(BACKWARDS_SEARCH) && current_x_find > begin_x) ||
	(ISSET(BACKWARDS_SEARCH) && current_x_find < begin_x))
#else
	current_x_find > begin_x
#endif
	) {
	not_found_msg(needle);
	disable_nodelay();
	return FALSE;
    }

    disable_nodelay();
    /* We've definitely found something. */
    openfile->current = fileptr;
    openfile->current_x = current_x_find;
    openfile->placewewant = xplustabs();
    openfile->current_y = current_y_find;

    /* needle_len holds the length of needle. */
    if (needle_len != NULL)
	*needle_len = found_len;

    return TRUE;
}
예제 #4
0
파일: search.c 프로젝트: ricksladkey/vile
/* ARGSUSED */
static int
rsearch(int f, int n, int dummy GCC_UNUSED, int fromscreen)
{
    int status;
    int wrapok;
    MARK curpos;
    int didwrap;

    assert(curwp != 0);

    if (f && n < 0)		/* reverse direction */
	return fsearch(f, -n, FALSE, fromscreen);

    if (n == 0)
	n = 1;

    wrapok = window_b_val(curwp, MDWRAPSCAN);

    last_srch_direc = REVERSE;

    /* ask the user for the regular expression to search for, and
     * find n'th occurrence.
     */
    status = readpattern("Reverse search: ", &searchpat, &gregexp,
			 EOS, fromscreen);
    if (status != TRUE)
	return status;

    ignorecase = window_b_val(curwp, MDIGNCASE);

    if (curwp == 0)
	return FALSE;

    curpos = DOT;
    scanboundry(wrapok, DOT, REVERSE);
    didwrap = FALSE;
    while (n--) {
	movenext(&(DOT), REVERSE);
	status = scanner(gregexp, REVERSE, wrapok, &didwrap);
	if (didwrap) {
	    mlwrite(
		       "[Search wrapped past start of buffer]");
	    didwrap = FALSE;
	}
	if (status != TRUE)
	    break;
    }

    if (status == TRUE) {
	savematch(DOT, gregexp->mlen);
	if (samepoint(DOT, curpos)) {
	    mlwrite(onlyonemsg);
	}
    } else if (status == FALSE) {
	movenext(&(DOT), FORWARD);
	not_found_msg(wrapok, REVERSE);
    } else if (status == ABORT) {
	mlwarn("[Aborted]");
	DOT = curpos;
	return status;
    }
    attrib_matches();
    return status;
}
예제 #5
0
파일: search.c 프로젝트: ris21/yoda
/* Step through each replace word and prompt user before replacing.
 * Parameters real_current and real_current_x are needed in order to
 * allow the cursor position to be updated when a word before the cursor
 * is replaced by a shorter word.
 *
 * needle is the string to seek.  We replace it with answer.  Return -1
 * if needle isn't found, else the number of replacements performed.  If
 * canceled isn't NULL, set it to TRUE if we canceled. */
ssize_t do_replace_loop(
#ifndef DISABLE_SPELLER
	bool whole_word_only,
#endif
	bool *canceled, const linestruct *real_current, size_t
	*real_current_x, const char *needle)
{
    ssize_t numreplaced = -1;
    size_t match_len;
    bool replaceall = FALSE;
#ifndef NANO_TINY
    bool old_mark_set = openfile->mark_set;
    linestruct *top, *bot;
    size_t top_x, bot_x;
    bool right_side_up = FALSE;
	/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
	 * FALSE if (current, current_x) is. */

    if (old_mark_set) {
	/* If the mark is on, frame the region, and turn the mark off. */
	mark_order((const linestruct **)&top, &top_x,
	    (const linestruct **)&bot, &bot_x, &right_side_up);
	openfile->mark_set = FALSE;

	/* Start either at the top or the bottom of the marked region. */
	if (!ISSET(BACKWARDS_SEARCH)) {
	    openfile->current = top;
	    openfile->current_x = (top_x == 0 ? 0 : top_x - 1);
	} else {
	    openfile->current = bot;
	    openfile->current_x = bot_x;
	}
    }
#endif /* !NANO_TINY */

    if (canceled != NULL)
	*canceled = FALSE;

    findnextstr_wrap_reset();
    while (findnextstr(
#ifndef DISABLE_SPELLER
	whole_word_only,
#endif
	real_current, *real_current_x, needle, &match_len)) {
	int i = 0;

#ifndef NANO_TINY
	if (old_mark_set) {
	    /* When we've found an occurrence outside of the marked region,
	     * stop the fanfare. */
	    if (openfile->current->lineno > bot->lineno ||
		openfile->current->lineno < top->lineno ||
		(openfile->current == bot && openfile->current_x > bot_x) ||
		(openfile->current == top && openfile->current_x < top_x))
		break;
	}
#endif

	/* Indicate that we found the search string. */
	if (numreplaced == -1)
	    numreplaced = 0;

	if (!replaceall) {
	    size_t xpt = xplustabs();
	    char *exp_word = display_string(openfile->current->data,
		xpt, strnlenpt(openfile->current->data,
		openfile->current_x + match_len) - xpt, FALSE);

	    edit_refresh();

	    curs_set(0);

	    do_replace_highlight(TRUE, exp_word);

	    /* TRANSLATORS: This is a prompt. */
	    i = do_yesno_prompt(TRUE, _("Replace this instance?"));

	    do_replace_highlight(FALSE, exp_word);

	    free(exp_word);

	    curs_set(1);

	    if (i == -1) {	/* We canceled the replace. */
		if (canceled != NULL)
		    *canceled = TRUE;
		break;
	    }
	}

	if (i > 0 || replaceall) {	/* Yes, replace it!!!! */
	    char *copy;
	    size_t length_change;

#ifndef NANO_TINY
	    add_undo(REPLACE);
#endif
	    if (i == 2)
		replaceall = TRUE;

	    copy = replace_line(needle);

	    length_change = strlen(copy) - strlen(openfile->current->data);

#ifndef NANO_TINY
	    /* If the mark was on and (mark_begin, mark_begin_x) was the
	     * top of it, don't change mark_begin_x. */
	    if (!old_mark_set || !right_side_up) {
		/* Keep mark_begin_x in sync with the text changes. */
		if (openfile->current == openfile->mark_begin &&
			openfile->mark_begin_x > openfile->current_x) {
		    if (openfile->mark_begin_x < openfile->current_x +
			match_len)
			openfile->mark_begin_x = openfile->current_x;
		    else
			openfile->mark_begin_x += length_change;
		    bot_x = openfile->mark_begin_x;
		}
	    }

	    /* If the mark was on and (current, current_x) was the top
	     * of it, don't change real_current_x. */
	    if (!old_mark_set || right_side_up) {
#endif
		/* Keep real_current_x in sync with the text changes. */
		if (openfile->current == real_current &&
			openfile->current_x <= *real_current_x) {
		    if (*real_current_x < openfile->current_x + match_len)
			*real_current_x = openfile->current_x + match_len;
		    *real_current_x += length_change;
#ifndef NANO_TINY
		    bot_x = *real_current_x;
		}
#endif
	    }

	    /* Set the cursor at the last character of the replacement
	     * text, so searching will resume after the replacement
	     * text.  Note that current_x might be set to (size_t)-1
	     * here. */
#ifndef NANO_TINY
	    if (!ISSET(BACKWARDS_SEARCH))
#endif
		openfile->current_x += match_len + length_change - 1;

	    /* Clean up. */
	    openfile->totsize += mbstrlen(copy) -
		mbstrlen(openfile->current->data);
	    free(openfile->current->data);
	    openfile->current->data = copy;

#ifndef DISABLE_COLOR
	    /* Reset the precalculated multiline-regex hints only when
	     * the first replacement has been made. */
	    if (numreplaced == 0)
		reset_multis(openfile->current, TRUE);
#endif

	    if (!replaceall) {
#ifndef DISABLE_COLOR
		/* If color syntaxes are available and turned on, we
		 * need to call edit_refresh(). */
		if (openfile->colorstrings != NULL &&
			!ISSET(NO_COLOR_SYNTAX))
		    edit_refresh();
		else
#endif
		    update_line(openfile->current, openfile->current_x);
	    }

	    set_modified();
	    numreplaced++;
	}
    }

    if (numreplaced == -1)
	not_found_msg(needle);

#ifndef NANO_TINY
    if (old_mark_set)
	openfile->mark_set = TRUE;
#endif

    /* If the NO_NEWLINES flag isn't set, and text has been added to the
     * magicline, make a new magicline. */
    if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
	new_magicline();

    return numreplaced;
}