static const char *update_quote_width(const char *begin, const char *end, bool utf8, size_t *width) { const char *ptr = begin; while (ptr < end && *width) { if (utf8) { size_t left = end - ptr; const char *next = ptr; wchar_t wc = next_wchar(&next, &left); if (!wc || wc == WEOF) return ptr; int w = fb_wcwidth(wc); if (w <= 0) w = next - ptr > 0 ? next - ptr : 1; if (*width < w) return ptr; *width -= w; ptr = next; } else { if (*ptr & 0x80) { if (*width < 2) return ptr; *width -= 2; ptr += 2; } else { *width -= 1; ++ptr; } } } return ptr > end ? end : ptr; }
size_t screen_display_width(const char *ptr, bool utf8) { size_t width = 0; bool ansi = false; while (*ptr) { if (ansi) { if (isalpha(*ptr)) ansi = false; } else { if (*ptr == '\033') { ansi = true; } else { if (utf8) { wchar_t wc = next_wchar(&ptr, NULL); if (wc == WEOF) break; width += fb_wcwidth(wc); --ptr; } else { ++width; } } } ++ptr; } return width; }
/** * 计算一个宽字符的显示宽度 * @param wc 一个宽字符 * @return 该宽字符在编辑器终端上的显示宽度 */ static size_t display_width_wchar(wchar_t wc) { if (wc == L'\n') return 0; if (wc == L'\033') return 1; int width = fb_wcwidth(wc); return width < 1 ? 1 : width; }
/** * Find newline in [begin, end), truncate at TRUNCATE_WIDTH. * @param begin The head pointer. * @param end The off-the-end pointer. * @param utf8 是否以UTF-8编码 * @return Off-the-end pointer to the first (truncated) line. */ static const char *get_truncated_line(const char *begin, const char *end, bool utf8) { const char *code = "[0123456789;"; bool ansi = false; int width = TRUNCATE_WIDTH; if (end - begin >= 2 && *begin == ':' && *(begin + 1) == ' ') width += 2; for (const char *s = begin; s < end; ++s) { if (*s == '\n') return s + 1; if (*s == '\033') { ansi = true; continue; } if (ansi) { if (!memchr(code, *s, sizeof(code) - 1)) ansi = false; continue; } if (*s & 0x80) { if (utf8) { const char *ptr = s; size_t size = end - s; wchar_t wc = next_wchar(&ptr, &size); if (wc == WEOF || wc == 0) { ++s; } else { width -= fb_wcwidth(wc); if (width < 0) return s; s = ptr - 1; } } else { width -= 2; if (width < 0) return s; ++s; } if (width == 0) return (s + 1 > end ? end : s + 1); } else { if (--width == 0) return s + 1; } } return end; }