summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c128
1 files changed, 57 insertions, 71 deletions
diff --git a/main.c b/main.c
index d19ed5a..7be5539 100644
--- a/main.c
+++ b/main.c
@@ -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;