#include "visualizer/grid.h" #include #include #include static size_t glyph_bytes(unsigned char lead) { if (lead < 0x80) return 1; if ((lead >> 5) == 0x6) return 2; if ((lead >> 4) == 0xE) return 3; if ((lead >> 3) == 0x1E) return 4; return 1; } size_t psi_utf8_count(const char* s) { size_t count = 0; while (*s) { s += glyph_bytes((unsigned char)*s); count++; } return count; } struct PsiStringBuilder psi_new_string_builder(void) { return (struct PsiStringBuilder){ NULL, 0, 0, }; } void psi_string_builder_append(struct PsiStringBuilder* sb, const char* s) { size_t n = strlen(s); if (sb->len + n + 1 > sb->cap) { size_t new_cap = sb->cap == 0 ? 256 : sb->cap * 2; while (new_cap < sb->len + n + 1) new_cap *= 2; sb->data = realloc(sb->data, new_cap); assert(sb->data != NULL); sb->cap = new_cap; } memcpy(sb->data + sb->len, s, n + 1); sb->len += n; } char* psi_string_builder_finish(struct PsiStringBuilder* sb) { if (sb->data == NULL) psi_string_builder_append(sb, ""); return sb->data; } struct PsiGlyphRow psi_new_glyph_row(size_t width) { char (*cells)[5] = malloc(width * sizeof(*cells)); assert(cells != NULL || width == 0); for (size_t i = 0; i < width; i++) memcpy(cells[i], " ", 2); return (struct PsiGlyphRow){ cells, width, }; } void psi_free_glyph_row(struct PsiGlyphRow* row) { free(row->cells); row->cells = NULL; row->width = 0; } void psi_glyph_row_set(struct PsiGlyphRow* row, size_t index, const char* glyph) { if (index >= row->width) return; size_t n = glyph_bytes((unsigned char)glyph[0]); memcpy(row->cells[index], glyph, n); row->cells[index][n] = '\0'; } size_t psi_glyph_row_place(struct PsiGlyphRow* row, size_t start, const char* utf8) { size_t count = 0; const char* p = utf8; while (*p) { size_t n = glyph_bytes((unsigned char)*p); size_t index = start + count; if (index < row->width) { memcpy(row->cells[index], p, n); row->cells[index][n] = '\0'; } p += n; count++; } return count; } void psi_glyph_row_fill_space(struct PsiGlyphRow* row, size_t from, size_t to, const char* glyph) { for (size_t i = from; i < to && i < row->width; i++) if (strcmp(row->cells[i], " ") == 0) psi_glyph_row_set(row, i, glyph); } void psi_glyph_row_render(struct PsiGlyphRow row, struct PsiStringBuilder* sb) { for (size_t i = 0; i < row.width; i++) psi_string_builder_append(sb, row.cells[i]); psi_string_builder_append(sb, "\n"); }