💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › 06b4ffa2e60613db1e4c7b871e437… captured on 2024-02-05 at 09:55:44. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 /*
1 * ISC License
2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>
3 */
4 #include <stdio.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <time.h>
9 #include "termbox.h"
10 #include "macro.h"
11 #include "strlcpy.h"
12 #include "page.h"
13 #include "request.h"
14 #include "client.h"
15 #include "tab.h"
16 #include "utf8.h"
17 #include "url.h"
18 #include "known_hosts.h"
19
20 #define MULTIPLE_TABS(X) (X->tab->next || X->tab->prev)
21
22 struct rect client_display_rect(struct client *client) {
23 struct rect rect = {0};
24 rect.w = client->width - 2;
25 rect.y = MULTIPLE_TABS(client);
26 rect.h = client->height - 1 - rect.y;
27 return rect;
28 }
29
30 void client_display(struct client* client) {
31 if (!client) return;
32 tb_clear();
33 tab_display(client->tab, client);
34 client_draw(client);
35 tb_present();
36 }
37
38 #define TAB_WIDTH 32
39 #define TB_REV (TB_REVERSE | TB_DEFAULT), TB_DEFAULT
40
41 void client_draw_scrollbar(struct client* client, struct request *request) {
42 int y, h, i;
43 struct rect rect;
44 if (!client || !request) return;
45 rect = client_display_rect(client);
46 rect.h -= 2;
47 if ((signed)request->page.length - rect.h <= 0) return;
48 y = rect.h * request->scroll / (request->page.length - rect.h);
49 h = (rect.h - 1) / (request->page.length - rect.h);
50 h = h ? h : 1;
51 if (y + h > rect.h) y = rect.h - h + 1;
52 for (i = 0; i <= rect.h; i++) {
53 tb_set_cell(client->width - 1, rect.y + i, ' ', TB_DEFAULT,
54 (i >= y && i < y + h) ? TB_WHITE : TB_BLACK);
55 }
56 }
57
58 void client_draw(struct client* client) {
59
60 int i;
61 struct request *req, *req_input;
62
63 if (!client) return;
64
65 req = tab_completed(client->tab);
66 /* reset counter and error when a new page is loaded */
67 if (req != client->last_request) {
68 client->count = 0;
69 client->error = 0;
70 }
71 client->last_request = req;
72
73 client->width = tb_width();
74 client->height = tb_height();
75
76 if (MULTIPLE_TABS(client)) {
77 struct tab *tab, *start;
78 int x, width;
79 int count, current;
80 for (i = 0; i < client->width; i++) {
81 tb_set_cell(i, 0, ' ', TB_REV);
82 }
83 for (tab = client->tab; tab->prev; tab = tab->prev) ;
84 current = count = 0;
85 for (start = tab; start; start = start->next) {
86 if (client->tab == start) current = count;
87 count++;
88 }
89 x = 0;
90 width = (client->width - count * 2) / count;
91 if (width > TAB_WIDTH) width = TAB_WIDTH;
92 if (width < 1) width = 1;
93 for (; tab; tab = tab->next) {
94 char buf[TAB_WIDTH] = {0};
95 int fg = TB_REVERSE | TB_DEFAULT, bg = TB_DEFAULT;
96 size_t length;
97 struct request *req = tab_completed(tab);
98 if (width == 1) {
99 current--;
100 if (client->width < current * 4) continue;
101 }
102 utf8_cpy(buf, req ? req->page.title : "about:blank",
103 width);
104 length = utf8_width(V(buf));
105 if (tab == client->tab) {
106 fg = TB_DEFAULT;
107 bg = TB_DEFAULT;
108 for (i = x; i < x + width + 2; i++)
109 tb_set_cell(i, 0, ' ', fg, bg);
110 }
111 tb_set_cell(x, 0, '[', fg, bg);
112 tb_set_cell(x + width + 1, 0, ']', fg, bg);
113 tb_printf(x + (width + 2 - length) / 2, 0,
114 fg, bg, "%s", buf);
115 x += width + 2;
116 }
117 }
118
119 for (i = 0; i < client->width; i++)
120 tb_set_cell(i, client->height - 2, ' ', TB_REV);
121
122 if (client->error) {
123 int color = client->error == ERROR_INFO ? TB_GREEN : TB_RED;
124 tb_print(0, client->height - 1, TB_WHITE, color, client->cmd);
125 }
126
127 if (client->mode == MODE_CMDLINE) {
128 tb_print(0, client->height - 1, TB_DEFAULT, TB_DEFAULT,
129 client->cmd);
130 tb_set_cursor(utf8_width(client->cmd, sizeof(client->cmd)),
131 client->height - 1);
132 }
133
134 if (client->count) {
135 tb_printf(client->width - 10, client->height - 1,
136 TB_DEFAULT, TB_DEFAULT, "%d", client->count);
137 }
138
139 req_input = tab_input(client->tab);
140 if (req_input) {
141 tb_printf(0, client->height - 2, TB_REV, "%s", req_input->url);
142 } else {
143 int expired = 0, fg = TB_REVERSE | TB_DEFAULT, bg = TB_DEFAULT;
144 char url[1024];
145 if (req && known_hosts_expired(req->name) > 0) {
146 int i;
147 expired = 1;
148 fg = TB_WHITE;
149 bg = TB_RED;
150 for (i = 0; i < client->width; i++) {
151 tb_set_cell(
152 i, client->height - 2, ' ', fg, bg);
153 }
154 }
155 if (req) url_hide_query(req->url, V(url));
156 else STRLCPY(url, "about:blank");
157 tb_printf(0, client->height - 2, fg, bg, "%s%s (%s)",
158 expired ? "[Certificate expired] " : "",
159 url, req ? req->meta : "");
160 }
161
162 if (req && req->selected &&
163 (size_t)req->selected <= req->page.links_count) {
164 const char *link = req->page.links[req->selected - 1];
165 const char format[] = " => %s ";
166 int len = utf8_width(link, MAX_URL) + sizeof(format) - 3;
167 int x = client->width - len;
168 if (x < 10) x = 10;
169 tb_printf(x, client->height - 2, TB_WHITE, TB_BLUE,
170 format, link);
171 }
172 client_draw_scrollbar(client, req);
173 }
174