💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › edd983e38b1c65b43f0809c329129… captured on 2023-11-04 at 12:17:13. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-09-08)
-=-=-=-=-=-=-
0 /* See LICENSE file for copyright and license details. */
1 #include <strings.h>
2 #include <termbox.h>
3 #include "gemini.h"
4 #include "display.h"
5 #include "wcwidth.h"
6 #include "url.h"
7
8 void tb_colorline(int x, int y, uintattr_t color) {
9 for (int i=x; i < tb_width(); i++)
10 tb_set_cell(i, y, ' ', color, color);
11 }
12
13 void hide_query(char* url, char* urlbuf) {
14 int hide = 0;
15 int posx = 0;
16 for (int i=0; url[i] && i < 1024; i++) {
17 if (hide && (url[i] == '/')) {
18 hide = 0;
19 }
20 if (!hide) {
21 urlbuf[posx] = url[i];
22 posx++;
23 }
24 if (!hide && url[i] == '?') {
25 hide = 1;
26 urlbuf[posx] = '<';
27 urlbuf[posx + 1] = '*';
28 urlbuf[posx + 2] = '>';
29 posx+=3;
30 }
31 }
32 urlbuf[posx] = '\0';
33 }
34
35 void display() {
36 int bg = GREY;
37 struct gmi_tab* tab = client.tab;
38 struct gmi_page* page = &tab->page;
39 if (tab->request.ask == 2) {
40 tab->request.ask = display_ask(tab->request.info,
41 tab->request.action);
42 }
43 tb_clear();
44
45 int input_offset = 0;
46 if (client.input.mode) {
47 int cpos = utf8_width_to(client.input.field,
48 sizeof(client.input.field),
49 client.input.cursor);
50 int w = tb_width();
51 w -= w&1; // make width even so double-width
52 // characters don't cause problem
53 if (page->code == 10 || page->code == 11)
54 w -= utf8_width(client.input.label,
55 sizeof(client.input.label)) + 2;
56 if (cpos >= w) {
57 input_offset = utf8_len_to(client.input.field,
58 sizeof(client.input.field),
59 cpos - cpos%w);
60 cpos = cpos%w;
61 }
62
63 if (page->code == 11 || page->code == 10)
64 tb_set_cursor(cpos + utf8_width(client.input.label,
65 sizeof(client.input.label))+2,
66 tb_height()-1);
67 else
68 tb_set_cursor(cpos, tb_height()-1);
69 }
70
71 if (page->code == 20 || page->code == 10 || page->code == 11) {
72 tb_clear();
73 if (client.tabs_count > 1) tab->scroll--;
74 page->lines = gmi_render(tab);
75 if (client.tabs_count > 1) tab->scroll++;
76 } else if (tab->error[0] != '\0') {
77 tb_printf(2, 1+(client.tabs_count>1), RED, TB_DEFAULT,
78 "# %s", tab->error);
79 }
80
81 // current tab
82 if (client.tabs_count > 1) {
83 tb_colorline(0, 0, bg);
84 gmi_gettitle(page, tab->url);
85 int index = 1;
86 struct gmi_tab* ptr = tab;
87 while (ptr->prev) {
88 index++;
89 ptr = ptr->prev;
90 }
91 tb_printf(0, 0, BLACK, bg,
92 " %s [%d/%d]", page->title,
93 index, client.tabs_count);
94 }
95
96 // current url
97 tb_colorline(0, tb_height()-2, bg);
98 char urlbuf[MAX_URL];
99 hide_query(tab->url, urlbuf);
100 tb_printf(0, tb_height()-2, BLACK, bg, "%s (%s)",
101 urlbuf, tab->page.meta);
102
103 // Show selected link url
104 if (tab->selected != 0) {
105 int x = tb_width() -
106 utf8_width(tab->selected_url, MAX_URL) - 5;
107 x = x < 10?10:x;
108 tb_printf(x, tb_height()-2, bg, BLUE,
109 " => %s ", tab->selected_url);
110 } else if (tab->request.state != STATE_DONE) {
111 hide_query(tab->request.url, urlbuf);
112 int llen = strnlen(tab->request.url, sizeof(tab->request.url));
113 tb_printf(tb_width()-llen-5, tb_height()-2, BLACK, bg,
114 " [%s] ", urlbuf);
115 }
116
117 int count = atoi(client.vim.counter);
118 if (count) {
119 tb_printf(tb_width() - 8, tb_height() - 1,
120 TB_DEFAULT, TB_DEFAULT, "%d", count);
121 }
122
123 // input
124 if (tab->show_error) {
125 tb_hide_cursor();
126 tb_colorline(0, tb_height()-1, RED);
127 tb_print(0, tb_height()-1, WHITE, RED, tab->error);
128 client.input.field[0] = '\0';
129 } else if (tab->show_info) {
130 tb_hide_cursor();
131 tb_colorline(0, tb_height()-1, GREEN);
132 tb_print(0, tb_height()-1, WHITE, GREEN, tab->info);
133 client.input.field[0] = '\0';
134 tab->show_info = 0;
135 } else if (page->code == 10) {
136 tb_printf(0, tb_height()-1, TB_DEFAULT, TB_DEFAULT,
137 "%s: %s", client.input.label,
138 client.input.field + input_offset);
139 } else if (page->code == 11) {
140 char input_buf[1024];
141 size_t i = 0;
142 for (; client.input.field[i] &&
143 i < sizeof(client.input.field); i++)
144 input_buf[i] = '*';
145 input_buf[i] = '\0';
146 tb_printf(0, tb_height()-1, TB_DEFAULT, TB_DEFAULT,
147 "%s: %s", client.input.label, input_buf);
148 } else {
149 tb_printf(0, tb_height()-1, TB_DEFAULT, TB_DEFAULT, "%s",
150 client.input.field + input_offset);
151 }
152
153 if (client.input.mode && tb_width() & 1)
154 tb_set_cell(tb_width() - 1, tb_height() -1, ' ',
155 TB_DEFAULT, TB_DEFAULT);
156 tb_present();
157 }
158
159 void display_history() {
160 char urlbuf[1024];
161 int ret = 0;
162 struct tb_event ev;
163 bzero(&ev, sizeof(ev));
164 do {
165 struct gmi_tab* tab = client.tab;
166
167 tb_clear();
168 tb_print(2, 1, RED, TB_DEFAULT, "# History");
169
170 if (!tab->history) {
171 tb_present();
172 continue;
173 }
174 int y = 3;
175 for (struct gmi_link* link = tab->history->next; link;
176 link = link->next) {
177 hide_query(link->url, urlbuf);
178 tb_printf(4, y, TB_DEFAULT, TB_DEFAULT, "%s", urlbuf);
179 y++;
180 }
181
182 hide_query(tab->history->url, urlbuf);
183 tb_printf(4, y, TB_DEFAULT, BLUE, "-> %s", urlbuf);
184 y++;
185
186 for (struct gmi_link* link = tab->history->prev; link;
187 link = link->prev) {
188 hide_query(link->url, urlbuf);
189 tb_printf(4, y, TB_DEFAULT, TB_DEFAULT, "%s", urlbuf);
190 y++;
191 }
192
193 tb_present();
194
195 } while(((ret = tb_poll_event(&ev)) == TB_OK &&
196 ev.type == TB_EVENT_RESIZE)
197 || ret == -14);
198 }
199
200 int display_ask(char* info, char* action) {
201 int ret = 0;
202 struct tb_event ev;
203 bzero(&ev, sizeof(ev));
204 do {
205
206 tb_clear();
207 tb_printf(2, 1, RED, TB_DEFAULT, "%s", info);
208 int w = tb_width();
209 int h = tb_height();
210 const char* line1 = "Press 'y' to %s";
211 const char* line2 = "Press any other key to cancel";
212 int x1 = w/2-(strlen(line1)+strnlen(action, w/2))/2;
213 int x2 = w/2-strlen(line2)/2;
214 tb_printf(x1, h/2-1, TB_DEFAULT, TB_DEFAULT, line1, action);
215 tb_printf(x1+7, h/2-1, GREEN, TB_DEFAULT, "y");
216 tb_printf(x2, h/2, TB_DEFAULT, TB_DEFAULT, line2);
217
218 tb_present();
219
220 } while(((ret = tb_poll_event(&ev)) == TB_OK &&
221 ev.type == TB_EVENT_RESIZE) || ret == -14);
222 return ev.ch == 'y' || ev.ch == 'Y';
223 }
224