diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 128 |
1 files changed, 57 insertions, 71 deletions
@@ -174,47 +174,51 @@ int timestamp_invalid(struct timespec *ts) { return 0; } -/* user cache */ +/* users */ + +typedef struct { + int lines, cols; + Str *txt; +} Pfp; typedef struct { Str name; - Str pfp; + Pfp pfp; } User; -typedef struct UserCache UserCache; -struct UserCache { - Str key; - UserCache *child[4]; - User value; -}; - -typedef uint64_t Hash; -Hash str_hash(Str s) { - Hash h = 14695981039346656037LU; - for (int i = 0; i < s.n; i++) - h = (h ^ (s.s[i] & 255)) * 1099511628211LU; - return h; -} - -User *user_get_or_new(UserCache **ht, Str key, Arena *a) { - Hash hash = str_hash(key); - for (Hash h = hash; *ht; h >>= 2) { - if (str_eql(key, (*ht)->key)) return &(*ht)->value; - ht = &(*ht)->child[h & 3]; - } - if (!a) return NULL; - *ht = new(a, UserCache); - (*ht)->key = key; - return &(*ht)->value; +/* TODO: utf8 support */ +void pfp_load(Pfp *pfp, Str src, Arena *a) { + int lines = 0, cols = 0; + for (Str s = src, l = {0}; next_line(&s, &l);) { + if (l.n > cols) cols = l.n; + lines++; + } + pfp->lines = lines; + pfp->cols = cols; + pfp->txt = new_arr(a, Str, lines); + lines = 0; + for (Str s = src, l = {0}; next_line(&s, &l);) { + pfp->txt[lines++] = l; + } } -User *user_get(UserCache *ht, Str key) { - Hash hash = str_hash(key); - for (Hash h = hash; ht; h >>= 2) { - if (str_eql(key, ht->key)) return &ht->value; - ht = ht->child[h & 3]; - } - return NULL; +User *user_load(Str name, Str binkdir, Arena *a) { + User *u = new(a, User); + u->name = str_dup(name, a); + FILE *f = fopen(cstr_fmt(a, "%S/pfp.txt", binkdir), "r/o"); + Str pfp_src = {0}; + if (f) { + read_all(f, &pfp_src, a); + fclose(f); + } else { + pfp_src = S( + "bi __ \n" + "nk_(''<\n" + " (____)\n" + ); + } + pfp_load(&u->pfp, pfp_src, a); + return u; } /* posts */ @@ -222,13 +226,13 @@ User *user_get(UserCache *ht, Str key) { typedef struct Post { struct timespec timestamp; const char *path; - Str user, text; + User *user; + Str text; } Post; typedef struct { ArenaMark mark; Post *data; - UserCache *users; ptrdiff_t len, cap; } PostList; @@ -238,24 +242,6 @@ typedef struct { int err; } PostStats; -/* load users */ - -void user_load(PostList *pl, Str name, Str binkdir, Arena *a) { - User *u = user_get_or_new(&pl->users, name, a); - u->name = name; - FILE *f = fopen(cstr_fmt(a, "%S/pfp.txt", binkdir), "r/o"); - if (f) { - read_all(f, &u->pfp, a); - fclose(f); - } else { - u->pfp = S( - "bi __ \n" - "nk_(''<\n" - " (____)\n" - ); - } -} - /* sorting */ int ts_cmp(const struct timespec *a, const struct timespec *b) { @@ -300,8 +286,7 @@ void posts_gather_from(PostList *posts, Str username, const char *path, Arena *a DIR *d = opendir(path); if (!d) return; post_stats.user_count++; - Str user = str_dup(username, a); - user_load(posts, user, str_from_cstr(path), a); + User *user = user_load(username, str_from_cstr(path), a); for (struct dirent *de; (de = readdir(d)); ) { if (*de->d_name == '.') continue; Post p = { 0 }; @@ -354,6 +339,12 @@ void posts_refresh(PostList *posts, Arena *a) { post_stats_fini(&post_stats); } +/* post utility functions */ + +int is_post_mine(Post *post) { + return str_eql(post->user->name, str_from_cstr(getlogin())); +} + /* word wrapping */ static inline int ch_space(char c) { @@ -443,7 +434,7 @@ int gfx_post_height(GfxPost *post) { return post->lines + 2 + GFX_TEXT_MARGIN_Y * 2; } -void gfx_draw_post(GfxPost *post, PostList *pl, int y, int x, int width) { +void gfx_draw_post(GfxPost *post, int y, int x, int width) { int height = gfx_post_height(post); if (!post->drawn) { @@ -453,7 +444,7 @@ void gfx_draw_post(GfxPost *post, PostList *pl, int y, int x, int width) { int left = x + opt.margin.left, top = y + opt.margin.top; int right = left + width - 1, bottom = top + height - 1; - int self = str_eql(post->src->user, str_from_cstr(getlogin())); + int self = is_post_mine(post->src); color_set(CPAIR_BORDER, 0); gfx_hline(top, left, right - left, ACS_HLINE); @@ -472,18 +463,17 @@ void gfx_draw_post(GfxPost *post, PostList *pl, int y, int x, int width) { if (opt.pfp_vis) { color_set(self ? CPAIR_PFP_SELF : CPAIR_PFP, 0); - User *u = user_get(pl->users, post->src->user); + User *u = post->src->user; if (u) { - Str line = { 0 }; - Str pfp = u->pfp; - for (int i = 0; next_line(&pfp, &line); i++) { - mvaddnstr(top + i + GFX_TEXT_MARGIN_Y, left - line.n - GFX_TEXT_MARGIN_X, line.s, line.n); + Pfp *pfp = &u->pfp; + for (int i = 0; i < pfp->lines; i++) { + mvaddnstr(top + i + GFX_TEXT_MARGIN_Y, left - pfp->cols - GFX_TEXT_MARGIN_X, pfp->txt[i].s, pfp->txt[i].n); } } } color_set(CPAIR_USER, 0); - mvaddnstr(y, left + 2, post->src->user.s, post->src->user.n); + mvaddnstr(y, left + 2, post->src->user->name.s, post->src->user->name.n); color_set(post->has_mention ? CPAIR_MENTION : CPAIR_TEXT, 0); @@ -495,11 +485,11 @@ void gfx_draw_post(GfxPost *post, PostList *pl, int y, int x, int width) { } } -void gfx_draw(Gfx *gfx, PostList *pl, int cur) { +void gfx_draw(Gfx *gfx, int cur) { int width = gfx_post_width(); erase(); for (int i = cur, y = GFX_MARGIN_Y; i < gfx->len && y < getmaxy(stdscr) - GFX_MARGIN_Y; i++) { - gfx_draw_post(&gfx->posts[i], pl, y, GFX_MARGIN_X, width); + gfx_draw_post(&gfx->posts[i], y, GFX_MARGIN_X, width); y += gfx_post_height(&gfx->posts[i]) + GFX_POST_SPACING; } } @@ -528,10 +518,6 @@ char *get_editor(void) { return editor; } -int is_post_mine(Post *post) { - return str_eql(post->user, str_from_cstr(getlogin())); -} - void edit_post(Post *post, Arena *temp) { system(cstr_fmt(temp, "%s %s", get_editor(), post->path)); } @@ -645,7 +631,7 @@ int main(void) { if (cur < 0) cur = 0; arena_reset(&temp_arena); - gfx_draw(&gfx, &posts, cur); + gfx_draw(&gfx, cur); switch (tagline_status) { case TAGLINE_OK: color_set(CPAIR_TAGLINE_OK, 0); break; case TAGLINE_WARN: color_set(CPAIR_TAGLINE_WARN, 0); break; |