Пример #1
0
/* This function is equivalent to strpbrk() for multibyte strings,
 * except in that it scans the string in reverse, starting at rev_start. */
char *mbrevstrpbrk(const char *s, const char *accept, const char
	*rev_start)
{
    assert(s != NULL && accept != NULL && rev_start != NULL);

#ifdef ENABLE_UTF8
    if (use_utf8) {
	if (*rev_start == '\0') {
	    if (rev_start == s)
		return NULL;
	    rev_start = s + move_mbleft(s, rev_start - s);
	}

	while (TRUE) {
	    if (mbstrchr(accept, rev_start) != NULL)
		return (char *)rev_start;

	    /* If we've reached the head of the string, we found nothing. */
	    if (rev_start == s)
		return NULL;

	    rev_start = s + move_mbleft(s, rev_start - s);
	}
    } else
#endif
	return revstrpbrk(s, accept, rev_start);
}
Пример #2
0
/* This function is equivalent to strpbrk() for multibyte strings,
 * except in that it scans the string in reverse, starting at
 * rev_start. */
char *mbrevstrpbrk(const char *s, const char *accept, const char
	*rev_start)
{
    assert(s != NULL && accept != NULL && rev_start != NULL);

#ifdef ENABLE_UTF8
    if (use_utf8) {
	bool begin_line = FALSE;

	while (!begin_line) {
	    const char *q = (*rev_start == '\0') ? NULL :
		mbstrchr(accept, rev_start);

	    if (q != NULL)
		return (char *)rev_start;

	    if (rev_start == s)
		begin_line = TRUE;
	    else
		rev_start = s + move_mbleft(s, rev_start - s);
	}

	return NULL;
    } else
#endif
	return revstrpbrk(s, accept, rev_start);
}
Пример #3
0
/* This function is equivalent to strcasestr() for multibyte strings,
 * except in that it scans the string in reverse, starting at rev_start. */
char *mbrevstrcasestr(const char *haystack, const char *needle, const
	char *rev_start)
{
#ifdef ENABLE_UTF8
    if (use_utf8) {
	size_t rev_start_len, needle_len;

	if (*needle == '\0')
	    return (char *)rev_start;

	needle_len = mbstrlen(needle);

	if (mbstrlen(haystack) < needle_len)
	    return NULL;

	rev_start_len = mbstrlen(rev_start);

	while (TRUE) {
	    if (rev_start_len >= needle_len &&
			mbstrncasecmp(rev_start, needle, needle_len) == 0)
		return (char *)rev_start;

	    /* If we've reached the head of the haystack, we found nothing. */
	    if (rev_start == haystack)
		return NULL;

	    rev_start = haystack + move_mbleft(haystack, rev_start - haystack);
	    rev_start_len++;
	}
    } else
#endif
	return revstrcasestr(haystack, needle, rev_start);
}
Пример #4
0
/* Move left one character. */
void do_statusbar_left(void)
{
    if (statusbar_x > 0) {
	size_t pww_save = statusbar_pww;

	statusbar_x = move_mbleft(answer, statusbar_x);
	statusbar_pww = statusbar_xplustabs();

	if (need_statusbar_update(pww_save))
	    update_statusbar_line(answer, statusbar_x);
    }
}
Пример #5
0
Файл: move.c Проект: rofl0r/nano
/* Move left one character. */
void do_left(void)
{
    size_t pww_save = openfile->placewewant;

    if (openfile->current_x > 0)
	openfile->current_x = move_mbleft(openfile->current->data,
		openfile->current_x);
    else if (openfile->current != openfile->fileage) {
	do_up_void();
	openfile->current_x = strlen(openfile->current->data);
    }

    openfile->placewewant = xplustabs();

    if (need_horizontal_update(pww_save))
	update_line(openfile->current, openfile->current_x);
}
Пример #6
0
/* Move left one character. */
void do_left(void)
{
    size_t was_column = xplustabs();

    if (openfile->current_x > 0)
	openfile->current_x = move_mbleft(openfile->current->data,
						openfile->current_x);
    else if (openfile->current != openfile->fileage) {
	do_up_void();
	openfile->current_x = strlen(openfile->current->data);
    }

    openfile->placewewant = xplustabs();

    if (need_horizontal_scroll(was_column, openfile->placewewant))
	update_line(openfile->current, openfile->current_x);
}
Пример #7
0
Файл: move.c Проект: sria91/nano
/* Move to the previous word in the file.  If allow_punct is TRUE, treat
 * punctuation as part of a word.  If allow_update is TRUE, update the
 * screen afterwards. */
void do_prev_word(bool allow_punct, bool allow_update)
{
    size_t pww_save = openfile->placewewant;
    filestruct *current_save = openfile->current;
    bool seen_a_word = FALSE, step_forward = FALSE;

    assert(openfile->current != NULL && openfile->current->data != NULL);

    /* Move backward until we pass over the start of a word. */
    while (TRUE) {
        /* If at the head of a line, move to the end of the preceding one. */
        if (openfile->current_x == 0) {
            if (openfile->current->prev == NULL)
                break;
            openfile->current = openfile->current->prev;
            openfile->current_x = strlen(openfile->current->data);
        }

        /* Step back one character. */
        openfile->current_x = move_mbleft(openfile->current->data,
                                          openfile->current_x);

        if (is_word_mbchar(openfile->current->data + openfile->current_x,
                           allow_punct)) {
            seen_a_word = TRUE;
            /* If at the head of a line now, this surely is a word start. */
            if (openfile->current_x == 0)
                break;
        } else if (seen_a_word) {
            /* This is space now: we've overshot the start of the word. */
            step_forward = TRUE;
            break;
        }
    }

    if (step_forward)
        /* Move one character forward again to sit on the start of the word. */
        openfile->current_x = move_mbright(openfile->current->data,
                                           openfile->current_x);
    openfile->placewewant = xplustabs();

    /* If allow_update is TRUE, update the screen. */
    if (allow_update)
        edit_redraw(current_save, pww_save);
}
Пример #8
0
/* This function is equivalent to strcasestr() for multibyte strings,
 * except in that it scans the string in reverse, starting at
 * rev_start. */
char *mbrevstrcasestr(const char *haystack, const char *needle, const
	char *rev_start)
{
#ifdef ENABLE_UTF8
    if (use_utf8) {
	bool begin_line = FALSE;
	size_t rev_start_len, needle_len;

	assert(haystack != NULL && needle != NULL && rev_start != NULL);

	if (*needle == '\0')
	    return (char *)rev_start;

	needle_len = mbstrlen(needle);

	if (mbstrlen(haystack) < needle_len)
	    return NULL;

	rev_start_len = mbstrlen(rev_start);

	while (!begin_line) {
	    if (rev_start_len >= needle_len &&
			mbstrncasecmp(rev_start, needle, needle_len) == 0 &&
			mblen(rev_start, MB_CUR_MAX) > 0)
		return (char *)rev_start;

	    if (rev_start == haystack)
		begin_line = TRUE;
	    else {
		rev_start = haystack + move_mbleft(haystack, rev_start -
			haystack);
		rev_start_len++;
	    }
	}

	return NULL;
    } else
#endif
	return revstrcasestr(haystack, needle, rev_start);
}
Пример #9
0
/* Is the word starting at position pos in buf a whole word? */
bool is_whole_word(size_t pos, const char *buf, const char *word)
{
    char *p = charalloc(mb_cur_max()), *r = charalloc(mb_cur_max());
    size_t word_end = pos + strlen(word);
    bool retval;

    assert(buf != NULL && pos <= strlen(buf) && word != NULL);

    parse_mbchar(buf + move_mbleft(buf, pos), p, NULL);
    parse_mbchar(buf + word_end, r, NULL);

    /* If we're at the beginning of the line or the character before the
     * word isn't a non-punctuation "word" character, and if we're at
     * the end of the line or the character after the word isn't a
     * non-punctuation "word" character, we have a whole word. */
    retval = (pos == 0 || !is_word_mbchar(p, FALSE)) &&
	(word_end == strlen(buf) || !is_word_mbchar(r, FALSE));

    free(p);
    free(r);

    return retval;
}
Пример #10
0
/* Move to the previous word in the prompt text.  If allow_punct is
 * TRUE, treat punctuation as part of a word.  Return TRUE if we started
 * on a word, and FALSE otherwise. */
bool do_statusbar_prev_word(bool allow_punct)
{
    size_t pww_save = statusbar_pww;
    char *char_mb;
    int char_mb_len;
    bool begin_line = FALSE, started_on_word = FALSE;

    assert(answer != NULL);

    char_mb = charalloc(mb_cur_max());

    /* Move backward until we find the character before the first letter
     * of the current word. */
    while (!begin_line) {
	char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);

	/* If we've found it, stop moving backward through the current
	 * line. */
	if (!is_word_mbchar(char_mb, allow_punct))
	    break;

	/* If we haven't found it, then we've started on a word, so set
	 * started_on_word to TRUE. */
	started_on_word = TRUE;

	if (statusbar_x == 0)
	    begin_line = TRUE;
	else
	    statusbar_x = move_mbleft(answer, statusbar_x);
    }

    /* Move backward until we find the last letter of the previous
     * word. */
    if (statusbar_x == 0)
	begin_line = TRUE;
    else
	statusbar_x = move_mbleft(answer, statusbar_x);

    while (!begin_line) {
	char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);

	/* If we've found it, stop moving backward through the current
	 * line. */
	if (is_word_mbchar(char_mb, allow_punct))
	    break;

	if (statusbar_x == 0)
	    begin_line = TRUE;
	else
	    statusbar_x = move_mbleft(answer, statusbar_x);
    }

    /* If we've found it, move backward until we find the character
     * before the first letter of the previous word. */
    if (!begin_line) {
	if (statusbar_x == 0)
	    begin_line = TRUE;
	else
	    statusbar_x = move_mbleft(answer, statusbar_x);

	while (!begin_line) {
	    char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
		NULL);

	    /* If we've found it, stop moving backward through the
	     * current line. */
	    if (!is_word_mbchar(char_mb, allow_punct))
		break;

	    if (statusbar_x == 0)
		begin_line = TRUE;
	    else
		statusbar_x = move_mbleft(answer, statusbar_x);
	}

	/* If we've found it, move forward to the first letter of the
	 * previous word. */
	if (!begin_line)
	    statusbar_x += char_mb_len;
    }

    free(char_mb);

    statusbar_pww = statusbar_xplustabs();

    if (need_statusbar_update(pww_save))
	update_statusbar_line(answer, statusbar_x);

    /* Return whether we started on a word. */
    return started_on_word;
}
Пример #11
0
Файл: move.c Проект: rofl0r/nano
/* Move to the previous word in the file.  If allow_punct is TRUE, treat
 * punctuation as part of a word.  If allow_update is TRUE, update the
 * screen afterwards.  Return TRUE if we started on a word, and FALSE
 * otherwise. */
bool do_prev_word(bool allow_punct, bool allow_update)
{
    size_t pww_save = openfile->placewewant;
    filestruct *current_save = openfile->current;
    char *char_mb;
    int char_mb_len;
    bool begin_line = FALSE, started_on_word = FALSE;

    assert(openfile->current != NULL && openfile->current->data != NULL);

    char_mb = charalloc(mb_cur_max());

    /* Move backward until we find the character before the first letter
     * of the current word. */
    while (!begin_line) {
	char_mb_len = parse_mbchar(openfile->current->data +
		openfile->current_x, char_mb, NULL);

	/* If we've found it, stop moving backward through the current
	 * line. */
	if (!is_word_mbchar(char_mb, allow_punct))
	    break;

	/* If we haven't found it, then we've started on a word, so set
	 * started_on_word to TRUE. */
	started_on_word = TRUE;

	if (openfile->current_x == 0)
	    begin_line = TRUE;
	else
	    openfile->current_x = move_mbleft(openfile->current->data,
		openfile->current_x);
    }

    /* Move backward until we find the last letter of the previous
     * word. */
    if (openfile->current_x == 0)
	begin_line = TRUE;
    else
	openfile->current_x = move_mbleft(openfile->current->data,
		openfile->current_x);

    for (; openfile->current != NULL;
	openfile->current = openfile->current->prev) {
	while (!begin_line) {
	    char_mb_len = parse_mbchar(openfile->current->data +
		openfile->current_x, char_mb, NULL);

	    /* If we've found it, stop moving backward through the
	     * current line. */
	    if (is_word_mbchar(char_mb, allow_punct))
		break;

	    if (openfile->current_x == 0)
		begin_line = TRUE;
	    else
		openfile->current_x =
			move_mbleft(openfile->current->data,
			openfile->current_x);
	}

	/* If we've found it, stop moving backward to the ends of
	 * previous lines. */
	if (!begin_line)
	    break;

	if (openfile->current != openfile->fileage) {
	    begin_line = FALSE;
	    openfile->current_x = strlen(openfile->current->prev->data);
	}
    }

    /* If we haven't found it, move to the beginning of the file. */
    if (openfile->current == NULL)
	openfile->current = openfile->fileage;
    /* If we've found it, move backward until we find the character
     * before the first letter of the previous word. */
    else if (!begin_line) {
	if (openfile->current_x == 0)
	    begin_line = TRUE;
	else
	    openfile->current_x = move_mbleft(openfile->current->data,
		openfile->current_x);

	while (!begin_line) {
	    char_mb_len = parse_mbchar(openfile->current->data +
		openfile->current_x, char_mb, NULL);

	    /* If we've found it, stop moving backward through the
	     * current line. */
	    if (!is_word_mbchar(char_mb, allow_punct))
		break;

	    if (openfile->current_x == 0)
		begin_line = TRUE;
	    else
		openfile->current_x =
			move_mbleft(openfile->current->data,
			openfile->current_x);
	}

	/* If we've found it, move forward to the first letter of the
	 * previous word. */
	if (!begin_line)
	    openfile->current_x += char_mb_len;
    }

    free(char_mb);

    openfile->placewewant = xplustabs();

    /* If allow_update is TRUE, update the screen. */
    if (allow_update)
	edit_redraw(current_save, pww_save);

    /* Return whether we started on a word. */
    return started_on_word;
}
Пример #12
0
/* 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;
}
Пример #13
0
/* Search for a match to the bracket at the current cursor position, if
 * there is one. */
void do_find_bracket(void)
{
    linestruct *current_save;
    size_t current_x_save, pww_save;
    const char *ch;
	/* The location in matchbrackets of the bracket at the current
	 * cursor position. */
    int ch_len;
	/* The length of ch in bytes. */
    const char *wanted_ch;
	/* The location in matchbrackets of the bracket complementing
	 * the bracket at the current cursor position. */
    int wanted_ch_len;
	/* The length of wanted_ch in bytes. */
    char *bracket_set;
	/* The pair of characters in ch and wanted_ch. */
    size_t i;
	/* Generic loop variable. */
    size_t matchhalf;
	/* The number of single-byte characters in one half of
	 * matchbrackets. */
    size_t mbmatchhalf;
	/* The number of multibyte characters in one half of
	 * matchbrackets. */
    size_t count = 1;
	/* The initial bracket count. */
    bool reverse;
	/* The direction we search. */
    char *found_ch;
	/* The character we find. */

    assert(mbstrlen(matchbrackets) % 2 == 0);

    ch = openfile->current->data + openfile->current_x;

    if (ch == '\0' || (ch = mbstrchr(matchbrackets, ch)) == NULL) {
	statusbar(_("Not a bracket"));
	return;
    }

    /* Save where we are. */
    current_save = openfile->current;
    current_x_save = openfile->current_x;
    pww_save = openfile->placewewant;

    /* If we're on an opening bracket, which must be in the first half
     * of matchbrackets, we want to search forwards for a closing
     * bracket.  If we're on a closing bracket, which must be in the
     * second half of matchbrackets, we want to search backwards for an
     * opening bracket. */
    matchhalf = 0;
    mbmatchhalf = mbstrlen(matchbrackets) / 2;

    for (i = 0; i < mbmatchhalf; i++)
	matchhalf += parse_mbchar(matchbrackets + matchhalf, NULL,
		NULL);

    reverse = ((ch - matchbrackets) >= matchhalf);

    /* If we're on an opening bracket, set wanted_ch to the character
     * that's matchhalf characters after ch.  If we're on a closing
     * bracket, set wanted_ch to the character that's matchhalf
     * characters before ch. */
    wanted_ch = ch;

    while (mbmatchhalf > 0) {
	if (reverse)
	    wanted_ch = matchbrackets + move_mbleft(matchbrackets,
		wanted_ch - matchbrackets);
	else
	    wanted_ch += move_mbright(wanted_ch, 0);

	mbmatchhalf--;
    }

    ch_len = parse_mbchar(ch, NULL, NULL);
    wanted_ch_len = parse_mbchar(wanted_ch, NULL, NULL);

    /* Fill bracket_set in with the values of ch and wanted_ch. */
    bracket_set = charalloc((mb_cur_max() * 2) + 1);
    strncpy(bracket_set, ch, ch_len);
    strncpy(bracket_set + ch_len, wanted_ch, wanted_ch_len);
    null_at(&bracket_set, ch_len + wanted_ch_len);

    found_ch = charalloc(mb_cur_max() + 1);

    while (TRUE) {
	if (find_bracket_match(reverse, bracket_set)) {
	    /* If we found an identical bracket, increment count.  If we
	     * found a complementary bracket, decrement it. */
	    parse_mbchar(openfile->current->data + openfile->current_x,
		found_ch, NULL);
	    count += (strncmp(found_ch, ch, ch_len) == 0) ? 1 : -1;

	    /* If count is zero, we've found a matching bracket.  Update
	     * the screen and get out. */
	    if (count == 0) {
		edit_redraw(current_save, pww_save);
		break;
	    }
	} else {
	    /* We didn't find either an opening or closing bracket.
	     * Indicate this, restore where we were, and get out. */
	    statusbar(_("No matching bracket"));
	    openfile->current = current_save;
	    openfile->current_x = current_x_save;
	    openfile->placewewant = pww_save;
	    break;
	}
    }

    /* Clean up. */
    free(bracket_set);
    free(found_ch);
}