readr

Minimal RSS reader (WIP)
Log | Files | Refs | README | LICENSE

commit 39f7911506b8e593009c0fff0d43675987354a86
parent f141b42063953c528fcaa8dd191d793583922b9b
Author: citbl <citbl@citbl.org>
Date:   Wed,  8 Oct 2025 22:43:49 +1000

UI improvements

Diffstat:
Mconfig.h | 17+++++++++++++----
Mfeeds.c | 6+++---
Mrender.c | 53++++++++++++++++++++++++++++++++++++++++-------------
Mtui.c | 9++++++++-
4 files changed, 64 insertions(+), 21 deletions(-)

diff --git a/config.h b/config.h @@ -1,15 +1,24 @@ #pragma once +#define VERSION "v1.1" + #define FEEDS "~/.config/readr/feeds" -#define FEED_CAP 20 +// the width of the left column: +#define FEED_CAP 26 + +// allocation caps #define POSTS_CAP 128 #define FEEDS_CAP 32 #define TITLE_CAP 128 #define URL_CAP 8192 -#define TEXT_COLOR TB_WHITE +// for colour details see termbox2.h + +#define LOGO_COLOR (TB_WHITE | TB_BRIGHT) +#define TEXT_COLOR (TB_WHITE | TB_DIM) #define BACK_COLOR TB_DEFAULT -#define LINE_COLOR (TB_BLACK | TB_BRIGHT) +#define LINE_COLOR (TB_WHITE | TB_DIM) #define FEED_COLOR TB_CYAN -#define POST_COLOR TB_YELLOW +#define POST_COLOR (TB_YELLOW) +#define SEEN_COLOR (TB_YELLOW | TB_DIM) diff --git a/feeds.c b/feeds.c @@ -50,9 +50,9 @@ fetch_feed(feed_t* feed, char* url) mrss_error_t rc = mrss_parse_url(url, &rss); if (rc != MRSS_OK || rss == NULL) { - char short_url[19]; - strncpy(short_url, url, 18); - short_url[18] = '\0'; + char short_url[FEEDS_CAP - 1]; + strncpy(short_url, url, FEEDS_CAP - 2); + short_url[FEEDS_CAP - 2] = '\0'; asprintf(&feed->title, "%s%s", "(bad) ", short_url); return; } diff --git a/render.c b/render.c @@ -4,28 +4,55 @@ #include "tui.h" #include "config.h" +#define HORIZ_LINE 0x2500 +#define VERT_LINE 0x2502 + static void -draw_top_bar(void) +draw_bars(void) { + int i; const int width = tb_width(); - for (int i = 0; i < width; i++) { - tb_set_cell(i, 0, ' ', LINE_COLOR, LINE_COLOR); + const int height = tb_height(); + + // verticals first + + for (i = 2; i < height - 2; i++) { + tb_set_cell(0, i, VERT_LINE, LINE_COLOR, BACK_COLOR); + tb_set_cell(FEED_CAP + 5, i, VERT_LINE, LINE_COLOR, BACK_COLOR); /* separator line */ + tb_set_cell(width - 1, i, VERT_LINE, LINE_COLOR, BACK_COLOR); + } + + for (i = 0; i < width; i++) { + tb_set_cell(i, 2, HORIZ_LINE, LINE_COLOR, BACK_COLOR); + tb_set_cell(i, height - 2, HORIZ_LINE, LINE_COLOR, BACK_COLOR); } - tb_print(1, 0, TEXT_COLOR, LINE_COLOR, "readr"); - tb_print(width - 51, 0, TEXT_COLOR, LINE_COLOR, "[enter] open link [space] open comments [q] quit"); + tb_print(1, 1, LOGO_COLOR, BACK_COLOR, "readr"); + tb_print(width - 5, 1, TEXT_COLOR, BACK_COLOR, VERSION); + tb_print(width - 66, + height - 1, + TEXT_COLOR, + BACK_COLOR, + "[arrows] move [enter] open link [space] open comments [q] quit"); + + // corners top + + tb_set_cell(0, 2, 0x250C, LINE_COLOR, BACK_COLOR); + tb_set_cell(FEED_CAP + 5, 2, 0x252C, LINE_COLOR, BACK_COLOR); + tb_set_cell(width - 1, 2, 0x2510, LINE_COLOR, BACK_COLOR); + + // corners bottom + + tb_set_cell(0, height - 2, 0x2514, LINE_COLOR, BACK_COLOR); + tb_set_cell(FEED_CAP + 5, height - 2, 0x2534, LINE_COLOR, BACK_COLOR); + tb_set_cell(width - 1, height - 2, 0x2518, LINE_COLOR, BACK_COLOR); } static void draw_background(void) { - const int height = tb_height(); tb_set_clear_attrs(TEXT_COLOR, BACK_COLOR); tb_clear(); - - for (int i = 0; i < height; i++) { - tb_set_cell(FEED_CAP + 5, i, 0x2595, LINE_COLOR, BACK_COLOR); /* vert line */ - } } void @@ -35,14 +62,14 @@ render(app_t* app) draw_background(); - draw_top_bar(); + draw_bars(); int i; for (i = 0; i < app->feeds_len; i++) { const feed_t* feed = app->feeds[i]; color = (app->selected_panel == 0 && i == app->selected_feed) ? (FEED_COLOR | TB_REVERSE) : (FEED_COLOR); - tb_print(1, 4 + i, color, TB_DEFAULT, feed->title ? feed->title : "N/A"); + tb_print(2, 4 + i, color, BACK_COLOR, feed->title ? feed->title : "N/A"); } char title[TITLE_CAP] = { 0 }; @@ -55,7 +82,7 @@ render(app_t* app) title[len] = '\0'; color = (app->selected_panel == 1 && i == app->selected_post) ? (POST_COLOR | TB_REVERSE) : (POST_COLOR); - tb_print(FEED_CAP + 10, 4 + i, color, TB_DEFAULT, title); + tb_print(FEED_CAP + 10, 4 + i, color, BACK_COLOR, title); } tb_present(); diff --git a/tui.c b/tui.c @@ -25,8 +25,15 @@ present(app_t* app) if (can_poll == TB_OK) { switch (ev.type) { case (TB_EVENT_KEY): - if (ev.key == TB_KEY_CTRL_Q || ev.key == TB_KEY_ESC || ev.ch == 'q') goto RIP; + + if (ev.key == TB_KEY_CTRL_Q // + || ev.key == TB_KEY_ESC // + || ev.key == TB_KEY_CTRL_C // + || ev.ch == 'q') + goto RIP; + handle_key(app, ev); + break; case (TB_EVENT_MOUSE): break;