๐ŸŽ€ Toy Gemini Client Written in C99
cli retro gemini gemtext terminal tls lightweight minimal c99 gemini-protocol
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: implement a working, alright ui

Fuwn a63a2d5a 4ba10025

+63 -68
+2 -2
include/viv/ui.h
··· 8 8 9 9 #include <curses.h> 10 10 11 - void UI_initialise(void); 11 + void UI_initialise(char *[], int); 12 12 /* void UI_free(void); */ 13 - void UI_print_in_middle(WINDOW *, int, int, int, char *, chtype); 13 + /* void UI_print_in_middle(WINDOW *, int, int, int, char *, chtype); */ 14 14 15 15 #endif /* VIV_UI_H */
+1
include/viv/viv.h
··· 13 13 int VIV_exit(int, const char *, ...); 14 14 /* http://www.martinbroadhurst.com/split-a-string-in-c.html */ 15 15 void VIV_split(const char *, char, split_fn, void *); 16 + void VIV_add_to_dynamic_array(const char *, int, void *); 16 17 17 18 char *strsep(char **__restrict, const char *__restrict); 18 19
+26 -63
viv/ui.c
··· 5 5 6 6 #include "viv/ui.h" 7 7 8 - #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 9 - 10 8 #include <menu.h> 11 9 #include <stdlib.h> 12 10 #include <string.h> 13 11 14 - char *choices[] = { 15 - "mix", 16 - "pop", 17 - "mix", 18 - "pop", 19 - "mix", 20 - "pop", 21 - "mix", 22 - "pop", 23 - "mix", 24 - "pop", 25 - "mix", 26 - "pop", 27 - "mix", 28 - "pop", 29 - "mix", 30 - "pop", 31 - "mix", 32 - "pop", 33 - "mix", 34 - "pop", 35 - "mix", 36 - "pop", 37 - "mix", 38 - "pop", 39 - "mix", 40 - "pop", 41 - "mix", 42 - "pop", 43 - "mix", 44 - "pop", 45 - "mix", 46 - "pop", 47 - (char *)NULL 48 - }; 49 - 50 - void UI_initialise(void) { 51 - // int height, width, i; 12 + void UI_initialise(char *content[], int content_length) { 52 13 WINDOW *window; 53 14 ITEM **window_items; 54 15 MENU *menu; 55 16 int character; 56 - int choices_size; 17 + int max_y; 57 18 58 19 initscr(); 59 20 start_color(); ··· 63 24 init_pair(1, COLOR_RED, COLOR_BLACK); 64 25 init_pair(2, COLOR_CYAN, COLOR_BLACK); 65 26 66 - choices_size = ARRAY_SIZE(choices); 67 - window_items = (ITEM **)calloc(choices_size, sizeof(ITEM *)); 27 + window_items = (ITEM **)calloc(content_length, sizeof(ITEM *)); 28 + max_y = getmaxy(stdscr); 68 29 69 - for (int i = 0; i < choices_size; ++i) { 70 - window_items[i] = new_item(choices[i], choices[i]); 30 + for (int i = 0; i < content_length; ++i) { 31 + window_items[i] = new_item(content[i], content[i]); 71 32 } 72 33 73 34 menu = new_menu((ITEM **)window_items); 74 35 75 - window = newwin(10, 40, 4, 4); 36 + window = newwin(max_y, 60, 0, 0); 76 37 keypad(window, TRUE); 77 38 78 39 set_menu_win(menu, window); 79 - set_menu_sub(menu, derwin(window, 6, 38, 3, 1)); 80 - set_menu_format(menu, 5, 1); 81 - 82 - set_menu_mark(menu, " * "); 40 + set_menu_sub(menu, derwin(window, max_y - 2, 60, 0, 0)); 41 + set_menu_format(menu, max_y - 2, 1); 42 + set_menu_mark(menu, ""); 83 43 84 - box(window, 0, 0); 44 + /* box(window, 0, 0); 85 45 UI_print_in_middle(window, 1, 0, 40, "viv", COLOR_PAIR(1)); 86 46 mvwaddch(window, 2, 0, ACS_LTEE); 87 47 mvwhline(window, 2, 1, ACS_HLINE, 38); 88 - mvwaddch(window, 2, 39, ACS_RTEE); 48 + mvwaddch(window, 2, 39, ACS_RTEE); */ 89 49 90 50 post_menu(menu); 91 51 wrefresh(window); 92 52 93 53 attron(COLOR_PAIR(2)); 94 - mvprintw(LINES - 2, 0, "Use PageUp and PageDown to scroll down or up a page of items"); 95 - mvprintw(LINES - 1, 0, "Arrow Keys to navigate (F1 to Exit)"); 54 + mvprintw(LINES - 2, 0, "exit: q"); 55 + mvprintw(LINES - 1, 0, "movement: hjkl"); 96 56 attroff(COLOR_PAIR(2)); 97 57 refresh(); 98 58 99 - while ((character = wgetch(window)) != KEY_F(1)) { 59 + while ((character = wgetch(window)) != 'q') { 100 60 switch (character) { 101 - case KEY_UP: { 61 + case 'k': { 102 62 menu_driver(menu, REQ_UP_ITEM); 103 63 } break; 104 - case KEY_DOWN: { 64 + case 'j': { 105 65 menu_driver(menu, REQ_DOWN_ITEM); 106 66 } break; 107 - case KEY_RIGHT: { 67 + case 'l': { 108 68 menu_driver(menu, REQ_SCR_DPAGE); 109 69 } break; 110 - case KEY_LEFT: { 70 + case 'h': { 111 71 menu_driver(menu, REQ_SCR_UPAGE); 112 72 } break; 73 + /* case KEY_RESIZE | 'r': { 74 + 75 + } break; */ 113 76 default: { 114 77 /* ignore */ 115 78 } break; ··· 118 81 119 82 unpost_menu(menu); 120 83 free_menu(menu); 121 - for (int i = 0; i < choices_size; ++i) { 84 + for (int i = 0; i < content_length; ++i) { 122 85 free_item(window_items[i]); 123 86 } 124 87 delwin(window); ··· 126 89 refresh(); 127 90 } 128 91 129 - void UI_print_in_middle( 92 + /* void UI_print_in_middle( 130 93 WINDOW *window, 131 94 int start_y, 132 95 int start_x, ··· 141 104 142 105 getyx(window, y, x); 143 106 144 - /* if (start_x != 0) { x = start_x; } */ 107 + */ /* if (start_x != 0) { x = start_x; } */ /* 145 108 if (start_y != 0) { y = start_y; } 146 109 if (width != 0) { width = 80; } 147 110 ··· 152 115 mvwprintw(window, y, x, "%s", string); 153 116 wattroff(window, colour); 154 117 refresh(); 155 - } 118 + } */
+34 -3
viv/viv.c
··· 10 10 #include <string.h> 11 11 #include <unistd.h> 12 12 13 + #include "viv/dynamic_array.h" 13 14 #include "viv/cli.h" 14 15 #include "viv/gemini.h" 15 16 #include "viv/log.h" ··· 141 142 gemini_ctx.content 142 143 ) 143 144 145 + VIV_DYNAMIC_ARRAY_dynamic_array *array = VIV_DYNAMIC_ARRAY_create(0); 146 + 147 + VIV_split(gemini_ctx.content, '\n', VIV_add_to_dynamic_array, array); 148 + 149 + char *lines[VIV_DYNAMIC_ARRAY_get_count(array)]; 150 + 151 + for (int i = 0; i < (int)VIV_DYNAMIC_ARRAY_get_count(array); ++i) { 152 + lines[i] = VIV_DYNAMIC_ARRAY_get(array, i); 153 + 154 + if (strlen(lines[i]) > 1) { 155 + lines[i][strlen(lines[i]) - 1] = 0; 156 + if (lines[i][strlen(lines[i]) - 1] == '\r') { 157 + lines[i][strlen(lines[i]) - 1] = ' '; 158 + } 159 + } else if (strlen(lines[i]) == 1) { 160 + lines[i] = " "; 161 + } 162 + } 163 + 164 + UI_initialise(lines, (int)(sizeof(lines) / sizeof(*lines))); 165 + 166 + VIV_DYNAMIC_ARRAY_for_each(array, free); 167 + VIV_DYNAMIC_ARRAY_delete(array); 168 + 144 169 close(connection_context.socket); 145 170 SSL_CTX_free(ssl_context); 146 171 ERR_free_strings(); 147 172 EVP_cleanup(); 148 173 149 174 free(gemini_ctx.header.header); 150 - 151 - /* ui.c testing */ 152 - /* UI_initialise(); */ 153 175 154 176 return EXIT_SUCCESS; 155 177 } ··· 200 222 201 223 return rv; 202 224 } 225 + 226 + void VIV_add_to_dynamic_array(const char *string, int length, void *data) { 227 + VIV_DYNAMIC_ARRAY_dynamic_array *array = data; 228 + char *token = calloc(length + 1, 1); 229 + 230 + memcpy(token, string, length); 231 + 232 + VIV_DYNAMIC_ARRAY_add_tail(array, token); 233 + }