size_t text_customword_start_prev(Text *txt, size_t pos, int (*isboundary)(int)) { char c; Iterator it = text_iterator_get(txt, pos); while (text_iterator_char_prev(&it, &c) && space(c)); if (boundary(c)) do pos = it.pos; while (text_iterator_char_prev(&it, &c) && boundary(c) && !space(c)); else do pos = it.pos; while (text_iterator_char_prev(&it, &c) && !boundary(c)); return pos; }
size_t text_customword_end_prev(Text *txt, size_t pos, int (*isboundary)(int)) { char c; Iterator it = text_iterator_get(txt, pos); if (!text_iterator_byte_get(&it, &c)) return pos; if (boundary(c)) while (boundary(c) && !space(c) && text_iterator_char_prev(&it, &c)); else while (!boundary(c) && text_iterator_char_prev(&it, &c)); while (space(c) && text_iterator_char_prev(&it, &c)); return it.pos; }
size_t text_line_char_prev(Text *txt, size_t pos) { char c; Iterator it = text_iterator_get(txt, pos); if (!text_iterator_char_prev(&it, &c) || c == '\n') return pos; return it.pos; }
size_t text_line_lastchar(Text *txt, size_t pos) { char c; Iterator it = text_iterator_get(txt, text_line_end(txt, pos)); if (text_iterator_char_prev(&it, &c) && c == '\n') text_iterator_byte_next(&it, NULL); return it.pos; }
size_t text_line_finish(Text *txt, size_t pos) { char c; Iterator it = text_iterator_get(txt, text_line_end(txt, pos)); do text_iterator_char_prev(&it, NULL); while (text_iterator_byte_get(&it, &c) && c != '\n' && space(c)); return it.pos; }
Filerange text_object_range(Text *txt, size_t pos, int (*isboundary)(int)) { char c; size_t start; Iterator it = text_iterator_get(txt, pos), rit = it; if (!text_iterator_byte_get(&rit, &c) || boundary(c)) return text_range_empty(); char tmp = c; do start = rit.pos; while (text_iterator_char_prev(&rit, &c) && !boundary(c)); for (c = tmp; !boundary(c) && text_iterator_byte_next(&it, &c);); return text_range_new(start, it.pos); }
size_t text_char_prev(Text *txt, size_t pos) { Iterator it = text_iterator_get(txt, pos); text_iterator_char_prev(&it, NULL); return it.pos; }