Introduction
Introduction Statistics Contact Development Disclaimer Help
ui_txt.c - sacc - sacc - sacc(omys), simple console gopher client (config)
git clone git://git.codemadness.org/sacc
Log
Files
Refs
LICENSE
---
ui_txt.c (5805B)
---
1 #include <ctype.h>
2 #include <errno.h>
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <termios.h>
8 #include <sys/ioctl.h>
9 #include <sys/types.h>
10
11 #include "common.h"
12
13 static char bufout[256];
14 static Item *curentry;
15 static int lines, columns;
16 static char cmd;
17
18 static void
19 viewsize(int *ln, int *col)
20 {
21 struct winsize ws;
22
23 if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
24 die("Could not get terminal resolution: %s",
25 strerror(errno));
26 }
27
28 if (ln)
29 *ln = ws.ws_row-1; /* one off for status bar */
30 if (col)
31 *col = ws.ws_col;
32 }
33
34 void
35 uisetup(void)
36 {
37 viewsize(&lines, &columns);
38 }
39
40 void
41 uicleanup(void)
42 {
43 return;
44 }
45
46 static void
47 help(void)
48 {
49 puts("Commands:\n"
50 "#: browse item number #.\n"
51 "U: print page URI.\n"
52 "u#: print item number # URI.\n"
53 "0: browse previous item.\n"
54 "n: show next page.\n"
55 "p: show previous page.\n"
56 "t: go to the top of the page\n"
57 "b: go to the bottom of the page\n"
58 "Y: yank page URI.\n"
59 "y#: yank item number # URI.\n"
60 "/str: search for string \"str\"\n"
61 "!: refetch failed item.\n"
62 "^D, q: quit.\n"
63 "h, ?: this help.");
64 }
65
66 static int
67 ndigits(size_t n)
68 {
69 return (n < 10) ? 1 : (n < 100) ? 2 : 3;
70 }
71
72 void
73 uistatus(char *fmt, ...)
74 {
75 va_list arg;
76 int n;
77
78 va_start(arg, fmt);
79 n = vsnprintf(bufout, sizeof(bufout), fmt, arg);
80 va_end(arg);
81
82 if (n < sizeof(bufout)-1) {
83 snprintf(bufout+n, sizeof(bufout)-n,
84 " [Press Enter to continue \xe2\x98\x83]");
85 }
86
87 mbsprint(bufout, columns);
88 fflush(stdout);
89
90 getchar();
91 }
92
93 static void
94 printstatus(Item *item, char c)
95 {
96 Dir *dir = item->dat;
97 char *fmt;
98 size_t nitems = dir ? dir->nitems : 0;
99 unsigned long long printoff = dir ? dir->printoff : 0;
100
101 fmt = (strcmp(item->port, "70") && strcmp(item->port, "gopher"))…
102 "%1$3lld%%%*2$3$c %4$s:%8$s/%5$c%6$s [%7$c]: " :
103 "%3lld%% %s/%c%s [%c]: ";
104 snprintf(bufout, sizeof(bufout), fmt,
105 (printoff + lines-1 >= nitems) ? 100 :
106 (printoff + lines) * 100 / nitems,
107 item->host, item->type, item->selector, c, item->port);
108
109 mbsprint(bufout, columns);
110 }
111
112 char *
113 uiprompt(char *fmt, ...)
114 {
115 va_list ap;
116 char *input = NULL;
117 size_t n = 0;
118 ssize_t r;
119
120 va_start(ap, fmt);
121 vsnprintf(bufout, sizeof(bufout), fmt, ap);
122 va_end(ap);
123
124 mbsprint(bufout, columns);
125 fflush(stdout);
126
127 if ((r = getline(&input, &n, stdin)) == -1 || feof(stdin)) {
128 clearerr(stdin);
129 clear(&input);
130 putchar('\n');
131 } else if (input[r - 1] == '\n') {
132 input[--r] = '\0';
133 }
134
135 return input;
136 }
137
138 void
139 uidisplay(Item *entry)
140 {
141 Item *items;
142 Dir *dir;
143 size_t i, nlines, nitems;
144 int nd;
145
146 if (!entry ||
147 !(entry->type == '1' || entry->type == '+' || entry->type ==…
148 !(dir = entry->dat))
149 return;
150
151 curentry = entry;
152
153 items = dir->items;
154 nitems = dir->nitems;
155 nlines = dir->printoff + lines;
156 nd = ndigits(nitems);
157
158 for (i = dir->printoff; i < nitems && i < nlines; ++i) {
159 snprintf(bufout, sizeof(bufout), "%*zu %s %s",
160 nd, i+1,typedisplay(items[i].type),
161 items[i].username);
162
163 mbsprint(bufout, columns);
164 putchar('\n');
165 }
166
167 fflush(stdout);
168 }
169
170 static void
171 printuri(Item *item, size_t i)
172 {
173 if (!item || item->type == 0 || item->type == 'i')
174 return;
175
176 itemuri(item, bufout, sizeof(bufout));
177
178 mbsprint(bufout, columns);
179 putchar('\n');
180 }
181
182 static void
183 searchinline(const char *searchstr, Item *entry)
184 {
185 Dir *dir;
186 size_t i;
187
188 if (!searchstr || !*searchstr || !(dir = entry->dat))
189 return;
190
191 for (i = 0; i < dir->nitems; ++i)
192 if (strcasestr(dir->items[i].username, searchstr))
193 printuri(&(dir->items[i]), i + 1);
194 }
195
196 Item *
197 uiselectitem(Item *entry)
198 {
199 Dir *dir;
200 char buf[BUFSIZ], *sstr = NULL, nl;
201 int item, nitems;
202
203 if (!entry || !(dir = entry->dat))
204 return NULL;
205
206 nitems = dir ? dir->nitems : 0;
207
208 for (;;) {
209 if (!cmd)
210 cmd = 'h';
211 printstatus(entry, cmd);
212 fflush(stdout);
213
214 if (!fgets(buf, sizeof(buf), stdin)) {
215 putchar('\n');
216 return NULL;
217 }
218 if (isdigit((unsigned char)*buf)) {
219 cmd = '\0';
220 nl = '\0';
221 if (sscanf(buf, "%d%c", &item, &nl) != 2 || nl !…
222 item = -1;
223 } else if (!strcmp(buf+1, "\n")) {
224 item = -1;
225 cmd = *buf;
226 } else if (*buf == '/') {
227 for (sstr = buf+1; *sstr && *sstr != '\n'; ++sst…
228 ;
229 *sstr = '\0';
230 sstr = buf+1;
231 cmd = *buf;
232 } else if (isdigit((unsigned char)*(buf+1))) {
233 nl = '\0';
234 if (sscanf(buf+1, "%d%c", &item, &nl) != 2 || nl…
235 item = -1;
236 else
237 cmd = *buf;
238 }
239
240 switch (cmd) {
241 case '\0':
242 break;
243 case 'q':
244 return NULL;
245 case 'n':
246 if (lines < nitems - dir->printoff &&
247 lines < (size_t)-1 - dir->printoff)
248 dir->printoff += lines;
249 return entry;
250 case 'p':
251 if (lines <= dir->printoff)
252 dir->printoff -= lines;
253 else
254 dir->printoff = 0;
255 return entry;
256 case 'b':
257 if (nitems > lines)
258 dir->printoff = nitems - lines;
259 else
260 dir->printoff = 0;
261 return entry;
262 case 't':
263 dir->printoff = 0;
264 return entry;
265 case '!':
266 if (entry->raw)
267 continue;
268 return entry;
269 case 'U':
270 printuri(entry, 0);
271 continue;
272 case 'u':
273 if (item > 0 && item <= nitems)
274 printuri(&dir->items[item-1], item);
275 continue;
276 case 'Y':
277 yankitem(entry);
278 continue;
279 case 'y':
280 if (item > 0 && item <= nitems)
281 yankitem(&dir->items[item-1]);
282 continue;
283 case '/':
284 if (sstr && *sstr)
285 searchinline(sstr, entry);
286 continue;
287 case 'h':
288 case '?':
289 help();
290 continue;
291 default:
292 cmd = 'h';
293 continue;
294 }
295
296 if (item >= 0 && item <= nitems)
297 break;
298 }
299
300 if (item > 0)
301 return &dir->items[item-1];
302
303 return entry->entry;
304 }
305
306 void
307 uisigwinch(int signal)
308 {
309 uisetup();
310
311 if (!curentry)
312 return;
313
314 putchar('\n');
315 uidisplay(curentry);
316 printstatus(curentry, cmd);
317 fflush(stdout);
318 }
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.