💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › 955eaa3ac2e74db85faf98df5c3e4… captured on 2023-12-28 at 15:42:19. 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 <stdlib.h>
6 #include <string.h>
7 #include <stdint.h>
8 #include <time.h>
9 #include <errno.h>
10 #include "macro.h"
11 #include "error.h"
12 #include "config.h"
13 #include "gemini.h"
14 #include "page.h"
15 #include "request.h"
16 #include "tab.h"
17 #include "client.h"
18 #include "termbox.h"
19 #include "utf8.h"
20 #include "input.h"
21 #include "strlcpy.h"
22 #include "known_hosts.h"
23 #include "storage.h"
24 #include "sandbox.h"
25 #include "parser.h"
26 #include "bookmarks.h"
27 #include "image.h"
28 #include "history.h"
29 #include "xdg.h"
30 #include "url.h"
31
32 int client_destroy(struct client *client) {
33 struct tab *tab;
34 if (!client) return ERROR_NULL_ARGUMENT;
35 for (tab = client->tab; tab && tab->prev; tab = tab->prev) ;
36 while (tab) {
37 struct tab *next = tab->next;
38 tab_free(tab);
39 tab = next;
40 }
41 known_hosts_free();
42 history_save();
43 history_free();
44 config_save();
45 free(bookmarks);
46 if (tb_shutdown()) return ERROR_TERMBOX_FAILURE;
47 return 0;
48 }
49
50 int client_closetab(struct client *client) {
51 struct tab *tab, *next, *prev;
52 if (!client->tab) return 1;
53 tab = client->tab;
54 next = tab->next;
55 prev = tab->prev;
56 if (next) next->prev = prev;
57 if (prev) prev->next = next;
58 if (next) {
59 client->tab = next;
60 } else if (prev) {
61 client->tab = prev;
62 } else client->tab = NULL;
63 tab_free(tab);
64 return 0;
65 }
66
67 int client_newtab(struct client *client, const char *url) {
68 struct tab *tab;
69 int proto;
70 if (!url) url = "about:newtab";
71 proto = protocol_from_url(url);
72 if (proto != PROTOCOL_GEMINI && proto != PROTOCOL_NONE) {
73 return tab_request(client->tab, url);
74 }
75 tab = tab_new();
76 if (!tab) return ERROR_MEMORY_FAILURE;
77 if (client->tab) {
78 tab->next = client->tab->next;
79 if (tab->next) tab->next->prev = tab;
80 tab->prev = client->tab;
81 client->tab->next = tab;
82 }
83 client->tab = tab;
84 return tab_request(client->tab, url);
85 }
86
87 int client_input(struct client *client) {
88
89 struct tb_event ev;
90 struct request *req = NULL;
91 int ret = 0;
92
93 if (!client->tab || !client->tab->request ||
94 client->tab->request->state != STATE_ONGOING) {
95 ret = tb_poll_event(&ev);
96 } else {
97 ret = tb_peek_event(&ev, 100);
98 }
99
100 if (ret == TB_ERR_NO_EVENT) return 0;
101 if (ret == TB_ERR_POLL) ret = TB_OK;
102 if (ret != TB_OK) return ERROR_TERMBOX_FAILURE;
103
104 if (client->tab)
105 req = tab_input(client->tab);
106
107 if (req && gemini_isinput(req->status) && client->mode == MODE_NORMAL) {
108 client_enter_mode_cmdline(client);
109 client->cursor = snprintf(V(client->cmd), "%s: ", req->meta);
110 }
111
112 switch (client->mode) {
113 case MODE_NORMAL:
114 return client_input_normal(client, ev);
115 case MODE_CMDLINE:
116 {
117 int ret = client_input_cmdline(client, ev);
118 if (client->mode == MODE_NORMAL)
119 tb_hide_cursor();
120 return ret;
121 }
122 }
123
124 return 0;
125 }
126
127 int client_init(struct client* client) {
128
129 int ret;
130
131 memset(client, 0, sizeof(*client));
132 if ((ret = storage_init())) return ret;
133 config_load();
134 if ((ret = parser_request_create())) return ret;
135 if ((ret = parser_page_create())) return ret;
136 #ifdef ENABLE_IMAGE
137 if ((ret = image_init())) return ret;
138 #endif
139 #ifndef DISABLE_XDG
140 if (xdg_available()) if ((ret = xdg_init())) return ret;
141 #endif
142 if ((ret = known_hosts_load())) return ret;
143 if ((ret = bookmark_load())) return ret;
144 if (tb_init()) return ERROR_TERMBOX_FAILURE;
145 #ifdef ENABLE_IMAGE
146 if (tb_set_output_mode(TB_OUTPUT_256)) return ERROR_TERMBOX_FAILURE;
147 #endif
148 if ((ret = sandbox_init())) {
149 tb_shutdown();
150 return ret;
151 }
152 history_init();
153
154 return 0;
155 }
156