SHL_EXPORT int tsm_screen_new(struct tsm_screen **out, tsm_log_t log, void *log_data) { struct tsm_screen *con; int ret; unsigned int i; if (!out) return -EINVAL; con = malloc(sizeof(*con)); if (!con) return -ENOMEM; memset(con, 0, sizeof(*con)); con->ref = 1; con->llog = log; con->llog_data = log_data; con->age_cnt = 1; con->age = con->age_cnt; con->def_attr.fr = 255; con->def_attr.fg = 255; con->def_attr.fb = 255; ret = tsm_symbol_table_new(&con->sym_table); if (ret) goto err_free; ret = tsm_screen_resize(con, 80, 24); if (ret) goto err_free; llog_debug(con, "new screen"); *out = con; return 0; err_free: for (i = 0; i < con->line_num; ++i) { line_free(con->main_lines[i]); line_free(con->alt_lines[i]); } free(con->main_lines); free(con->alt_lines); free(con->tab_ruler); tsm_symbol_table_unref(con->sym_table); free(con); return ret; }
/* * This decomposes a symbol into a ucs4 string and a size value. If \sym is a * valid UCS4 character, this returns a pointer to \sym and writes 1 into \size. * Therefore, the returned value may get destroyed if your \sym argument gets * destroyed. * If \sym is a composed ucs4 string, then the returned value points into the * hash table of the symbol table and lives as long as the symbol table does. * * This always returns a valid value. If an error happens, the default character * is returned. If \size is NULL, then the size value is omitted. */ SHL_EXPORT const uint32_t *tsm_symbol_get(struct tsm_symbol_table *tbl, tsm_symbol_t *sym, size_t *size) { uint32_t *ucs4, idx; int ret; if (*sym <= TSM_UCS4_MAX) { if (size) *size = 1; return sym; } if (!tbl) tbl = tsm_symbol_table_default; if (!tbl) { ret = tsm_symbol_table_new(&tbl); if (ret) { if (size) *size = 1; return &tsm_symbol_default; } tsm_symbol_table_default = tbl; } idx = *sym - (TSM_UCS4_MAX + 1); if (idx >= shl_array_get_length(tbl->index)) ucs4 = NULL; else ucs4 = *SHL_ARRAY_AT(tbl->index, uint32_t*, idx); if (!ucs4) { if (size) *size = 1; return &tsm_symbol_default; } if (size) { *size = 0; while (ucs4[*size] <= TSM_UCS4_MAX) ++*size; } return ucs4; }
SHL_EXPORT unsigned int tsm_symbol_get_width(struct tsm_symbol_table *tbl, tsm_symbol_t sym) { int ret; const uint32_t *ch; size_t len; if (!tbl) tbl = tsm_symbol_table_default; if (!tbl) { ret = tsm_symbol_table_new(&tbl); if (ret) return sym; tsm_symbol_table_default = tbl; } ch = tsm_symbol_get(tbl, &sym, &len); if (len == 0) return 0; return tsm_ucs4_get_width(*ch); }
SHL_EXPORT tsm_symbol_t tsm_symbol_append(struct tsm_symbol_table *tbl, tsm_symbol_t sym, uint32_t ucs4) { uint32_t buf[TSM_UCS4_MAXLEN + 1], nsym, *nval; const uint32_t *ptr; size_t s; void *tmp; bool res; int ret; if (!tbl) tbl = tsm_symbol_table_default; if (!tbl) { ret = tsm_symbol_table_new(&tbl); if (ret) return sym; tsm_symbol_table_default = tbl; } if (ucs4 > TSM_UCS4_MAX) return sym; ptr = tsm_symbol_get(tbl, &sym, &s); if (s >= TSM_UCS4_MAXLEN) return sym; memcpy(buf, ptr, s * sizeof(uint32_t)); buf[s++] = ucs4; buf[s++] = TSM_UCS4_MAX + 1; res = shl_hashtable_find(tbl->symbols, &tmp, buf); if (res) return (uint32_t)(long)tmp; nval = malloc(sizeof(uint32_t) * s); if (!nval) return sym; memcpy(nval, buf, s * sizeof(uint32_t)); nsym = tbl->next_id + 1; /* Out of IDs; we actually have 2 Billion IDs so this seems * very unlikely but lets be safe here */ if (nsym <= tbl->next_id++) goto err_id; ret = shl_hashtable_insert(tbl->symbols, nval, (void*)(long)nsym); if (ret) goto err_id; ret = shl_array_push(tbl->index, &nval); if (ret) goto err_symbol; return nsym; err_symbol: shl_hashtable_remove(tbl->symbols, nval); err_id: --tbl->next_id; free(nval); return sym; }