1 #include <errno.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <notcurses/notcurses.h>
5 #include "lib/internal.h" // internal headers
6
7 static inline wchar_t
capboolbool(unsigned utf8,bool cap)8 capboolbool(unsigned utf8, bool cap){
9 // FIXME these fancy glyphs aren't reliable enough yet (they're not
10 // usually present on the linux console, for instance) for such an
11 // essential, must-work-everywhere tool.
12 /*if(utf8){
13 return cap ? L'✓' : L'✖';
14 }else{
15 return cap ? '+' : '-';
16 }*/
17 (void)utf8;
18 return cap ? '+' : '-';
19 }
20
21 static void
tinfo_debug_cap(struct ncplane * n,const char * name,bool yn)22 tinfo_debug_cap(struct ncplane* n, const char* name, bool yn){
23 if(!yn){
24 ncplane_set_styles(n, NCSTYLE_ITALIC);
25 }
26 ncplane_putstr(n, name);
27 ncplane_set_styles(n, NCSTYLE_BOLD);
28 ncplane_putwc(n, capboolbool(notcurses_canutf8(ncplane_notcurses(n)), yn));
29 ncplane_set_styles(n, NCSTYLE_NONE);
30 ncplane_putchar(n, ' ');
31 }
32
33 static void
tinfo_debug_style(struct ncplane * n,const char * name,int style,char ch)34 tinfo_debug_style(struct ncplane* n, const char* name, int style, char ch){
35 unsigned support = notcurses_supported_styles(ncplane_notcurses(n)) & style;
36 if(!support){
37 ncplane_set_styles(n, NCSTYLE_ITALIC);
38 }
39 ncplane_set_styles(n, style);
40 ncplane_putstr(n, name);
41 ncplane_set_styles(n, NCSTYLE_BOLD);
42 ncplane_putwc(n, capboolbool(notcurses_canutf8(ncplane_notcurses(n)), support));
43 ncplane_set_styles(n, NCSTYLE_NONE);
44 ncplane_putchar(n, ch);
45 }
46
47 static void
wviz(struct ncplane * n,const wchar_t * wp)48 wviz(struct ncplane* n, const wchar_t* wp){
49 unsigned wchars;
50 for(const wchar_t* w = wp ; *w ; w += wchars){
51 if(ncplane_putwc_utf32(n, w, &wchars) <= 0){
52 ncplane_putchar(n, ' ');
53 }
54 }
55 }
56
57 static void
wvizn(struct ncplane * n,const wchar_t * wp,int nnn)58 wvizn(struct ncplane* n, const wchar_t* wp, int nnn){
59 for(int nn = 0 ; nn < nnn ; ++nn){
60 if(ncplane_putwc(n, wp[nn]) <= 0){
61 ncplane_putchar(n, ' ');
62 }
63 }
64 }
65
66 static int
braille_viz(struct ncplane * n,wchar_t l,const wchar_t * egcs,wchar_t r,const char * indent,const wchar_t * bounds,wchar_t r8,wchar_t l8,const wchar_t * trailer)67 braille_viz(struct ncplane* n, wchar_t l, const wchar_t* egcs, wchar_t r,
68 const char* indent, const wchar_t* bounds, wchar_t r8, wchar_t l8,
69 const wchar_t* trailer){
70 ncplane_printf(n, "%s%lc", indent, l);
71 for(int i = 0 ; i < 64 ; ++i){
72 if(ncplane_putwc(n, egcs[i]) <= 0){
73 ncplane_putchar(n, ' ');
74 }
75 }
76 ncplane_putwc(n, r);
77 ncplane_putwc(n, bounds[0]);
78 if(ncplane_putwc(n, r8) <= 0){
79 ncplane_putchar(n, ' ');
80 }
81 if(ncplane_putwc(n, l8) <= 0){
82 ncplane_putchar(n, ' ');
83 }
84 ncplane_putwc(n, bounds[1]);
85 if(trailer){
86 wviz(n, trailer);
87 }
88 if(ncplane_dim_x(n) > 80){
89 ncplane_putchar(n, '\n');
90 }
91 return 0;
92 }
93
94 static void
finish_line(struct ncplane * n)95 finish_line(struct ncplane* n){
96 unsigned x;
97 ncplane_cursor_yx(n, NULL, &x);
98 while(x++ < 80){
99 ncplane_putchar(n, ' ');
100 }
101 if(ncplane_dim_x(n) > 80){
102 ncplane_putchar(n, '\n');
103 }
104 }
105
106 static int
emoji_viz(struct ncplane * n)107 emoji_viz(struct ncplane* n){
108 static const char emoji[] = "\U0001f47e" // alien monster
109 "\U0001f3f4" // waving black flag
110 "\U0001f918" // sign of the horns
111 "\U0001f6ac" // cigarette, delicious
112 "\U0001f30d" // globe europe/africa
113 "\U0001f30e" // globe americas
114 "\U0001f30f" // globe asia/australia
115 "\U0001F946" // rifle
116 "\U0001f4a3" // bomb
117 "\U0001f5e1" // dagger
118 "\U0001F52B" // pistol
119 "\u2697\ufe0f" // alembic
120 "\u269b\ufe0f" // atom
121 "\u2622\ufe0f" // radiation sign
122 "\u2623\ufe0f" // biohazard
123 "\U0001F33F" // herb
124 "\U0001F3B1" // billiards
125 "\U0001F3E7" // automated teller machine
126 "\U0001F489" // syringe
127 "\U0001F48A" // pill
128 "\U0001f574\ufe0f" // man in suit levitating
129 "\U0001F4E1" // satellite antenna
130 "\U0001F93B" // modern pentathlon
131 "\U0001F991" // squid
132 "\U0001f1e6\U0001f1f6" // regional indicators AQ (antarctica)
133 "\U0001f469\u200d\U0001f52c" // woman scientist
134 "\U0001faa4" // mouse trap
135 "\U0001f6b1" // non-potable water
136 "\u270a\U0001f3ff" // type-6 raised fist
137 "\U0001f52c" // microscope
138 "\U0001f9ec" // dna double helix
139 "\U0001f3f4\u200d\u2620\ufe0f" // pirate flag
140 "\U0001f93d\U0001f3fc\u200d\u2640\ufe0f" // type-3 woman playing water polo
141 ;
142 ncplane_set_bg_rgb(n, 0);
143 size_t bytes;
144 for(const char* e = emoji ; *e ; e += bytes){
145 if(ncplane_putegc(n, e, &bytes) < 0){
146 if(ncplane_putchar(n, ' ') < 0){
147 break;
148 }
149 }
150 }
151 unsigned x;
152 ncplane_cursor_yx(n, NULL, &x);
153 while(x++ < 80){
154 ncplane_putchar(n, ' ');
155 }
156 if(ncplane_dim_x(n) > 80){
157 ncplane_putchar(n, '\n');
158 }
159 return 0;
160 }
161
162 // symbols for legacy computing
163 static int
legacy_viz(struct ncplane * n,const char * indent,const wchar_t * eighths,const wchar_t * anglesr,const wchar_t * anglesl)164 legacy_viz(struct ncplane* n, const char* indent, const wchar_t* eighths,
165 const wchar_t* anglesr, const wchar_t* anglesl){
166 ncplane_printf(n, "%s ", indent);
167 unsigned wchars;
168 for(const wchar_t* e = eighths ; *e ; e += wchars){
169 if(ncplane_putwc_utf32(n, e, &wchars) <= 0){
170 ncplane_putchar(n, ' ');
171 }
172 }
173 ncplane_putchar(n, ' ');
174 const wchar_t* r = anglesr;
175 const wchar_t* l = anglesl;
176 while(*r){
177 if(ncplane_putwc_utf32(n, r, &wchars) <= 0){
178 ncplane_putchar(n, ' ');
179 }
180 r += wchars;
181 if(ncplane_putwc_utf32(n, l, &wchars) <= 0){
182 ncplane_putchar(n, ' ');
183 }
184 l += wchars;
185 ncplane_putchar(n, ' ');
186 }
187 return 0;
188 }
189
190 static int
sex_viz(struct ncplane * n,const wchar_t * sex,wchar_t r,const wchar_t * post)191 sex_viz(struct ncplane* n, const wchar_t* sex, wchar_t r, const wchar_t* post){
192 for(int i = 0 ; i < 31 ; ++i){
193 if(ncplane_putwc(n, sex[i]) <= 0){
194 ncplane_putchar(n, ' ');
195 }
196 }
197 if(ncplane_putwc(n, r) <= 0){
198 ncplane_putchar(n, ' ');
199 }
200 unsigned wchars = 0;
201 for(const wchar_t* p = post ; *p ; p += wchars){
202 if(ncplane_putwc_utf32(n, p, &wchars) <= 0){
203 ncplane_putchar(n, ' ');
204 }
205 }
206 return 0;
207 }
208
209 static void
triviz(struct ncplane * n,const wchar_t * w1,const wchar_t * w2,const wchar_t * w3,const wchar_t * w4,const wchar_t * w5,const wchar_t * w6,const wchar_t * w7,const wchar_t * w8,const wchar_t * w9,const wchar_t * wa,const wchar_t * wb,const wchar_t * wc,const wchar_t * wd,const wchar_t * we,const wchar_t * wf,const wchar_t * w10,const wchar_t * w11,const wchar_t * w12,const wchar_t * w13,const wchar_t * w14,const wchar_t * w15)210 triviz(struct ncplane* n, const wchar_t* w1, const wchar_t* w2, const wchar_t* w3,
211 const wchar_t* w4, const wchar_t* w5, const wchar_t* w6,
212 const wchar_t* w7, const wchar_t* w8, const wchar_t* w9,
213 const wchar_t* wa, const wchar_t* wb, const wchar_t* wc,
214 const wchar_t* wd, const wchar_t* we, const wchar_t* wf,
215 const wchar_t* w10, const wchar_t* w11, const wchar_t* w12,
216 const wchar_t* w13, const wchar_t* w14, const wchar_t* w15){
217 wvizn(n, w1, 2);
218 ncplane_putchar(n, ' ');
219 wvizn(n, w2, 2);
220 ncplane_putchar(n, ' ');
221 wvizn(n, w3, 2);
222 ncplane_putchar(n, ' ');
223 wvizn(n, w4, 2);
224 wvizn(n, w5, 2);
225 ncplane_putchar(n, ' ');
226 wvizn(n, w6, 2);
227 ncplane_putchar(n, ' ');
228 wvizn(n, w7, 2);
229 ncplane_putchar(n, ' ');
230 wvizn(n, w8, 2);
231 ncplane_putchar(n, ' ');
232 wvizn(n, w9, 2);
233 wvizn(n, wa, 1);
234 ncplane_putchar(n, ' ');
235 wvizn(n, wb, 2);
236 wvizn(n, wc, 1);
237 ncplane_putchar(n, ' ');
238 wvizn(n, wd, 2);
239 wvizn(n, we, 1);
240 ncplane_putchar(n, ' ');
241 wvizn(n, wf, 2);
242 wvizn(n, w10, 1);
243 ncplane_putchar(n, ' ');
244 wvizn(n, w11, 2);
245 wvizn(n, w12, 1);
246 wvizn(n, w13, 3); // chess
247 wviz(n, w14);
248 wviz(n, w15);
249 }
250
251 static void
vertviz(struct ncplane * n,wchar_t l,wchar_t li,wchar_t ri,wchar_t r,const wchar_t * trail)252 vertviz(struct ncplane* n, wchar_t l, wchar_t li, wchar_t ri, wchar_t r,
253 const wchar_t* trail){
254 if(ncplane_putwc(n, l) <= 0){
255 ncplane_putchar(n, ' ');
256 }
257 if(ncplane_putwc(n, li) <= 0){
258 ncplane_putchar(n, ' ');
259 }
260 if(ncplane_putwc(n, ri) <= 0){
261 ncplane_putchar(n, ' ');
262 }
263 if(ncplane_putwc(n, r) <= 0){
264 ncplane_putchar(n, ' ');
265 }
266 wviz(n, trail);
267 if(ncplane_dim_x(n) > 80){
268 ncplane_putchar(n, '\n');
269 }
270 }
271
272 static int
unicodedumper(struct ncplane * n,const char * indent)273 unicodedumper(struct ncplane* n, const char* indent){
274 if(notcurses_canutf8(ncplane_notcurses_const(n))){
275 // all NCHALFBLOCKS are contained within NCQUADBLOCKS
276 ncplane_printf(n, "%s%ls⎧", indent, NCQUADBLOCKS);
277 // (on Windows, these will be encoded as UTF-16 surrogate
278 // pairs due to a 16-bit wchar_t.
279 sex_viz(n, NCSEXBLOCKS, L'⎫', L"♠♥" NCSEGDIGITS L"\u2157\u2158\u2159\u215a\u215b");
280 vertviz(n, L'⎧', NCEIGHTHSR[0], NCEIGHTHSL[0], L'⎫', L"┌╥─╥─╥┐⎛⎞");
281 ncplane_printf(n, "%s╲╿╱ ◨◧ ◪◩ ◖◗ ⫷⫸ ⎩", indent);
282 sex_viz(n, &NCSEXBLOCKS[32], L'⎭', L"♦♣\u00bc\u00bd\u00be\u2150\u2151\u2152\u2153\u2154\u2155\u2156\u215c\u215d\u215e\u215f\u2189");
283 vertviz(n, L'⎪', NCEIGHTHSR[1], NCEIGHTHSL[1], L'⎪', L"├╜╓╫╖╙┤⎜⎟");
284 ncplane_printf(n, "%s╾╳╼ ", indent);
285 triviz(n, NCWHITESQUARESW, NCWHITECIRCLESW, NCDIAGONALSW, &NCDIAGONALSW[4],
286 NCCIRCULARARCSW, NCWHITETRIANGLESW, NCSHADETRIANGLESW, NCBLACKTRIANGLESW,
287 NCBOXLIGHTW, &NCBOXLIGHTW[4], NCBOXHEAVYW, &NCBOXHEAVYW[4], NCBOXROUNDW,
288 &NCBOXROUNDW[4], NCBOXDOUBLEW, &NCBOXDOUBLEW[4], NCBOXOUTERW, &NCBOXOUTERW[4],
289 NCCHESSBLACK, L"⩘▵△▹▷▿▽◃◁", NCARROWW);
290 vertviz(n, L'⎪', NCEIGHTHSR[2], NCEIGHTHSL[2], L'⎪', L"├─╨╫╨─┤┇⎜⎟");
291 ncplane_printf(n, "%s╱╽╲ ", indent);
292 triviz(n, &NCWHITESQUARESW[2], &NCWHITECIRCLESW[2], &NCDIAGONALSW[2], &NCDIAGONALSW[6],
293 &NCCIRCULARARCSW[2], &NCWHITETRIANGLESW[2], &NCSHADETRIANGLESW[2], &NCBLACKTRIANGLESW[2],
294 &NCBOXLIGHTW[2], &NCBOXLIGHTW[5], &NCBOXHEAVYW[2], &NCBOXHEAVYW[5], &NCBOXROUNDW[2],
295 &NCBOXROUNDW[5], &NCBOXDOUBLEW[2], &NCBOXDOUBLEW[5], &NCBOXOUTERW[2], &NCBOXOUTERW[5],
296 &NCCHESSBLACK[3], L"⩗▴⏶⯅▲▸⏵⯈▶", L"▾⏷⯆▼◂⏴⯇◀");
297 vertviz(n, L'⎪', NCEIGHTHSR[3], NCEIGHTHSL[3], L'⎪', L"╞═╤╬╤═╡┋⎜⎟");
298 braille_viz(n, L'⎡', NCBRAILLEEGCS, L'⎤', indent, L"⎨⎬", NCEIGHTHSR[4], NCEIGHTHSL[4],
299 L"╞╕╘╬╛╒╡┊⎜⎟");
300 braille_viz(n, L'⎢', &NCBRAILLEEGCS[64], L'⎥', indent, L"⎪⎪", NCEIGHTHSR[5], NCEIGHTHSL[5],
301 L"└┴─╨─┴┘╏⎝⎠");
302 braille_viz(n, L'⎢', &NCBRAILLEEGCS[128], L'⎥', indent, L"⎪⎪", NCEIGHTHSR[6], NCEIGHTHSL[6],
303 L"╭──╮⟬⟭╔╗≶≷");
304 braille_viz(n, L'⎣', &NCBRAILLEEGCS[192], L'⎦', indent, L"⎪⎪", NCEIGHTHSR[7], NCEIGHTHSL[7],
305 L"│╭╮│╔═╝║⊆⊇");
306 legacy_viz(n, indent, L"▔▁", NCANGLESBR, NCANGLESBL);
307 wviz(n, NCDIGITSSUBW);
308 wviz(n, L" ⎛");
309 wviz(n, NCEIGHTHSB);
310 // ⎞⎪⎪╰╯││║╔═╝⊴⊵
311 wviz(n, L"\U0001FB6B\u239e⎪⎪╰╯││║╔═╝⊴⊵");
312 if(ncplane_dim_x(n) > 80){
313 ncplane_putchar(n, '\n');
314 }
315 legacy_viz(n, indent, L"▏▕", NCANGLESTR, NCANGLESTL);
316 wviz(n, NCDIGITSSUPERW);
317 wviz(n, L" ⎝");
318 wviz(n, NCEIGHTHST);
319 // ⎠⎩⎭⧒⧑╰╯╚╝❨❩⟃⟄
320 wviz(n, L"\U0001FB69\u23a0⎩⎭⧒⧑╰╯╚╝❨❩⟃⟄");
321 if(ncplane_dim_x(n) > 80){
322 ncplane_putchar(n, '\n');
323 }
324 emoji_viz(n);
325 unsigned y, x;
326 ncplane_cursor_yx(n, &y, &x);
327 uint64_t ur = NCCHANNELS_INITIALIZER(0xff, 0xff, 0xff, 0x1B, 0xd8, 0x8E);
328 uint64_t lr = NCCHANNELS_INITIALIZER(0xff, 0xff, 0xff, 0xdB, 0x18, 0x8E);
329 uint64_t ul = NCCHANNELS_INITIALIZER(0xff, 0xff, 0xff, 0x19, 0x19, 0x70);
330 uint64_t ll = NCCHANNELS_INITIALIZER(0xff, 0xff, 0xff, 0x19, 0x19, 0x70);
331 ncplane_stain(n, y - 16, 0, 16, 80, ul, ur, ll, lr);
332 ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_ITALIC);
333 ncplane_cursor_move_yx(n, y - 12, 54);
334 wviz(n, L"https://notcurses.com");
335 ncplane_set_styles(n, NCSTYLE_NONE);
336 }
337 return 0;
338 }
339
340 static int
display_logo(struct ncplane * n,const char * path)341 display_logo(struct ncplane* n, const char* path){
342 unsigned cpixy, cpixx;
343 ncplane_pixel_geom(n, NULL, NULL, &cpixy, &cpixx, NULL, NULL);
344 struct ncvisual* ncv = ncvisual_from_file(path);
345 if(ncv == NULL){
346 return -1;
347 }
348 if(ncvisual_resize(ncv, 3 * cpixy, 24 * cpixx)){
349 ncvisual_destroy(ncv);
350 return -1;
351 }
352 unsigned y;
353 ncplane_cursor_yx(n, &y, NULL);
354 struct ncvisual_options vopts = {
355 .n = n,
356 .y = y - 3,
357 .x = 54,
358 .blitter = NCBLIT_PIXEL,
359 .flags = NCVISUAL_OPTION_CHILDPLANE | NCVISUAL_OPTION_NODEGRADE,
360 };
361 struct ncplane* bitm = ncvisual_blit(ncplane_notcurses(n), ncv, &vopts);
362 if(bitm == NULL){
363 ncvisual_destroy(ncv);
364 return -1;
365 }
366 ncvisual_destroy(ncv);
367 return 0;
368 }
369
370 static void
tinfo_debug_bitmaps(struct ncplane * n,const tinfo * ti,const char * indent)371 tinfo_debug_bitmaps(struct ncplane* n, const tinfo* ti, const char* indent){
372 uint32_t fg = 0;
373 int r = notcurses_default_foreground(ncplane_notcurses(n), &fg);
374 if(r){
375 ncplane_printf(n, "%sno known default fg ", indent);
376 }else{
377 ncplane_printf(n, "%sdefault fg 0x%06x ", indent, fg);
378 }
379 uint32_t bg = 0;
380 r = notcurses_default_background(ncplane_notcurses(n), &bg);
381 if(r){
382 ncplane_printf(n, "no known default bg");
383 }else{
384 ncplane_printf(n, "default bg 0x%06x", bg);
385 }
386 finish_line(n);
387 ncpixelimpl_e blit = notcurses_check_pixel_support(ncplane_notcurses(n));
388 switch(blit){
389 case NCPIXEL_NONE:
390 ncplane_printf(n, "%sno bitmap graphics detected", indent);
391 break;
392 case NCPIXEL_SIXEL:
393 if(ti->sixel_maxy){
394 ncplane_printf(n, "%smax sixel size: %dx%d colorregs: %u",
395 indent, ti->sixel_maxy, ti->sixel_maxx, ti->color_registers);
396 }else{
397 ncplane_printf(n, "%ssixel colorregs: %u", indent, ti->color_registers);
398 }
399 break;
400 case NCPIXEL_LINUXFB:
401 ncplane_printf(n, "%sframebuffer graphics supported", indent);
402 break;
403 case NCPIXEL_ITERM2:
404 ncplane_printf(n, "%siTerm2 graphics supported", indent);
405 break;
406 case NCPIXEL_KITTY_STATIC:
407 ncplane_printf(n, "%srgba pixel graphics support", indent);
408 break;
409 case NCPIXEL_KITTY_ANIMATED:
410 ncplane_printf(n, "%s1st gen rgba pixel animation support", indent);
411 break;
412 case NCPIXEL_KITTY_SELFREF:
413 ncplane_printf(n, "%s2nd gen rgba pixel animation support", indent);
414 break;
415 }
416 finish_line(n);
417 }
418
419 static void
tinfo_debug_caps(struct ncplane * n,const tinfo * ti,const char * indent)420 tinfo_debug_caps(struct ncplane* n, const tinfo* ti, const char* indent){
421 ncplane_printf(n, "%s", indent);
422 tinfo_debug_cap(n, "af", get_escape(ti, ESCAPE_SETAF));
423 tinfo_debug_cap(n, "ab", get_escape(ti, ESCAPE_SETAB));
424 tinfo_debug_cap(n, "sum", get_escape(ti, ESCAPE_BSUM));
425 tinfo_debug_cap(n, "cup", get_escape(ti, ESCAPE_CUP));
426 tinfo_debug_cap(n, "vpa", get_escape(ti, ESCAPE_VPA));
427 tinfo_debug_cap(n, "hpa", get_escape(ti, ESCAPE_HPA));
428 tinfo_debug_cap(n, "sgr0", get_escape(ti, ESCAPE_SGR0));
429 tinfo_debug_cap(n, "op", get_escape(ti, ESCAPE_OP));
430 tinfo_debug_cap(n, "fgop", get_escape(ti, ESCAPE_FGOP));
431 tinfo_debug_cap(n, "bgop", get_escape(ti, ESCAPE_BGOP));
432 tinfo_debug_cap(n, "bce", ti->bce);
433 finish_line(n);
434 }
435
436 static void
tinfo_debug_styles(const notcurses * nc,struct ncplane * n,const char * indent)437 tinfo_debug_styles(const notcurses* nc, struct ncplane* n, const char* indent){
438 const tinfo* ti = &nc->tcache;
439 ncplane_putstr(n, indent);
440 tinfo_debug_style(n, "bold", NCSTYLE_BOLD, ' ');
441 tinfo_debug_style(n, "ital", NCSTYLE_ITALIC, ' ');
442 tinfo_debug_style(n, "struck", NCSTYLE_STRUCK, ' ');
443 tinfo_debug_style(n, "ucurl", NCSTYLE_UNDERCURL, ' ');
444 tinfo_debug_style(n, "uline", NCSTYLE_UNDERLINE, ' ');
445 tinfo_debug_cap(n, "u7", get_escape(ti, ESCAPE_U7));
446 tinfo_debug_cap(n, "ccc", ti->caps.can_change_colors);
447 tinfo_debug_cap(n, "rgb", ti->caps.rgb);
448 tinfo_debug_cap(n, "el", get_escape(ti, ESCAPE_EL));
449 finish_line(n);
450 ncplane_putstr(n, indent);
451 tinfo_debug_cap(n, "utf8", notcurses_canutf8(nc));
452 tinfo_debug_cap(n, "2x1", notcurses_canhalfblock(nc));
453 tinfo_debug_cap(n, "2x2", notcurses_canquadrant(nc));
454 tinfo_debug_cap(n, "3x2", notcurses_cansextant(nc));
455 tinfo_debug_cap(n, "4x2", notcurses_canbraille(nc));
456 tinfo_debug_cap(n, "img", notcurses_canopen_images(nc));
457 tinfo_debug_cap(n, "vid", notcurses_canopen_videos(nc));
458 tinfo_debug_cap(n, "indn", get_escape(ti, ESCAPE_INDN));
459 tinfo_debug_cap(n, "gpm", ti->gpmfd >= 0);
460 tinfo_debug_cap(n, "kbd", ti->kittykbdsupport);
461 finish_line(n);
462 }
463
464 static int
usage(const char * base,FILE * fp,int ret)465 usage(const char* base, FILE* fp, int ret){
466 fprintf(fp, "usage: %s [ -v ]\n", base);
467 exit(ret);
468 }
469
470 // we should probably change this up to use regular good ol'
471 // notcurses_render() without the alternate screen, no?
main(int argc,const char ** argv)472 int main(int argc, const char** argv){
473 notcurses_options nopts = {
474 .flags = NCOPTION_NO_ALTERNATE_SCREEN
475 | NCOPTION_PRESERVE_CURSOR
476 | NCOPTION_NO_CLEAR_BITMAPS
477 | NCOPTION_DRAIN_INPUT,
478 };
479 if(argc > 2){
480 usage(*argv, stderr, EXIT_FAILURE);
481 }
482 if(argc == 2){
483 if(strcmp(argv[1], "-v")){
484 usage(*argv, stderr, EXIT_FAILURE);
485 }
486 nopts.loglevel = NCLOGLEVEL_TRACE;
487 }
488 struct notcurses* nc = notcurses_init(&nopts, NULL);
489 if(nc == NULL){
490 return EXIT_FAILURE;
491 }
492 // so that we know whether we're talking to gpm
493 notcurses_mice_enable(nc, NCMICE_ALL_EVENTS);
494 const char indent[] = "";
495 unsigned dimx;
496 struct ncplane* stdn = notcurses_stddim_yx(nc, NULL, &dimx);
497 if(dimx < 80){
498 ncplane_set_fg_rgb(stdn, 0xff5349);
499 ncplane_set_styles(stdn, NCSTYLE_BOLD);
500 ncplane_putstr(stdn, "This program requires at least 80 columns.\n");
501 notcurses_render(nc);
502 notcurses_stop(nc);
503 return EXIT_FAILURE;
504 }
505 ncplane_set_scrolling(stdn, true);
506 tinfo_debug_caps(stdn, &nc->tcache, indent);
507 tinfo_debug_styles(nc, stdn, indent);
508 tinfo_debug_bitmaps(stdn, &nc->tcache, indent);
509 unicodedumper(stdn, indent);
510 char* path = prefix_data("notcurses.png");
511 if(path){
512 display_logo(stdn, path); // let it fail
513 free(path);
514 }
515 if(notcurses_render(nc)){
516 notcurses_stop(nc);
517 return EXIT_FAILURE;
518 }
519 return notcurses_stop(nc) ? EXIT_FAILURE : EXIT_SUCCESS;
520 }
521