/* 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); }
/* 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); }
/* This function is equivalent to strpbrk() for multibyte strings. */ char *mbstrpbrk(const char *s, const char *accept) { #ifdef ENABLE_UTF8 if (use_utf8) { for (; *s != '\0'; s += move_mbright(s, 0)) { if (mbstrchr(accept, s) != NULL) return (char *)s; } return NULL; } else #endif return (char *) strpbrk(s, accept); }
/* 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); }