aboutsummaryrefslogtreecommitdiff
path: root/termbox2/termbox2.ha
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--termbox2/termbox2.ha605
1 files changed, 605 insertions, 0 deletions
diff --git a/termbox2/termbox2.ha b/termbox2/termbox2.ha
new file mode 100644
index 0000000..f8476ee
--- /dev/null
+++ b/termbox2/termbox2.ha
@@ -0,0 +1,605 @@
1use encoding::utf8;
2use fmt;
3use types::c;
4
5// Type for key values, see [[termbox2::KEY]].
6export type key = u16;
7
8// ASCII constants, see [[termbox2::key_event]].key.
9export def KEY = struct {
10 CTRL_TILDE: key = 0x00,
11 CTRL_2: key = 0x00, // clash with CTRL_TILDE
12 CTRL_A: key = 0x01,
13 CTRL_B: key = 0x02,
14 CTRL_C: key = 0x03,
15 CTRL_D: key = 0x04,
16 CTRL_E: key = 0x05,
17 CTRL_F: key = 0x06,
18 CTRL_G: key = 0x07,
19 BACKSPACE: key = 0x08,
20 CTRL_H: key = 0x08, // clash with CTRL_BACKSPACE
21 TAB: key = 0x09,
22 CTRL_I: key = 0x09, // clash with TAB
23 CTRL_J: key = 0x0a,
24 CTRL_K: key = 0x0b,
25 CTRL_L: key = 0x0c,
26 ENTER: key = 0x0d,
27 CTRL_M: key = 0x0d, // clash with ENTER
28 CTRL_N: key = 0x0e,
29 CTRL_O: key = 0x0f,
30 CTRL_P: key = 0x10,
31 CTRL_Q: key = 0x11,
32 CTRL_R: key = 0x12,
33 CTRL_S: key = 0x13,
34 CTRL_T: key = 0x14,
35 CTRL_U: key = 0x15,
36 CTRL_V: key = 0x16,
37 CTRL_W: key = 0x17,
38 CTRL_X: key = 0x18,
39 CTRL_Y: key = 0x19,
40 CTRL_Z: key = 0x1a,
41 ESC: key = 0x1b,
42 CTRL_LSQ_BRACKET: key = 0x1b, // clash with 'ESC'
43 CTRL_3: key = 0x1b, // clash with 'ESC'
44 CTRL_4: key = 0x1c,
45 CTRL_BACKSLASH: key = 0x1c, // clash with 'CTRL_4'
46 CTRL_5: key = 0x1d,
47 CTRL_RSQ_BRACKET: key = 0x1d, // clash with 'CTRL_5'
48 CTRL_6: key = 0x1e,
49 CTRL_7: key = 0x1f,
50 CTRL_SLASH: key = 0x1f, // clash with 'CTRL_7'
51 CTRL_UNDERSCORE: key = 0x1f, // clash with 'CTRL_7'
52 SPACE: key = 0x20,
53 BACKSPACE2: key = 0x7f,
54 CTRL_8: key = 0x7f, // clash with 'BACKSPACE2'
55 F1: key = (0xffff - 0),
56 F2: key = (0xffff - 1),
57 F3: key = (0xffff - 2),
58 F4: key = (0xffff - 3),
59 F5: key = (0xffff - 4),
60 F6: key = (0xffff - 5),
61 F7: key = (0xffff - 6),
62 F8: key = (0xffff - 7),
63 F9: key = (0xffff - 8),
64 F10: key = (0xffff - 9),
65 F11: key = (0xffff - 10),
66 F12: key = (0xffff - 11),
67 INSERT: key = (0xffff - 12),
68 DELETE: key = (0xffff - 13),
69 HOME: key = (0xffff - 14),
70 END: key = (0xffff - 15),
71 PGUP: key = (0xffff - 16),
72 PGDN: key = (0xffff - 17),
73 ARROW_UP: key = (0xffff - 18),
74 ARROW_DOWN: key = (0xffff - 19),
75 ARROW_LEFT: key = (0xffff - 20),
76 ARROW_RIGHT: key = (0xffff - 21),
77 BACK_TAB: key = (0xffff - 22),
78 MOUSE_LEFT: key = (0xffff - 23),
79 MOUSE_RIGHT: key = (0xffff - 24),
80 MOUSE_MIDDLE: key = (0xffff - 25),
81 MOUSE_RELEASE: key = (0xffff - 26),
82 MOUSE_WHEEL_UP: key = (0xffff - 27),
83 MOUSE_WHEEL_DOWN: key = (0xffff - 28),
84};
85
86// Type for key modifiers, see [[termbox2::MOD]].
87export type mod = u8;
88
89// Key modifiers (bitwise), see [[termbox2::event]].mod.
90export def MOD = struct {
91 ALT: mod = 1,
92 CTRL: mod = 2,
93 SHIFT: mod = 4,
94 MOTION: mod = 8,
95};
96
97// Type for input modes, see [[termbox2::INPUT]].
98export type input_mode = int;
99
100// Input modes (bitwise), see [[termbox2::set_input_mode]].
101export def INPUT = struct {
102 CURRENT: input_mode = 0,
103 ESC: input_mode = 1,
104 ALT: input_mode = 2,
105 MOUSE: input_mode = 4,
106};
107
108// Type for output modes, see [[termbox2::OUTPUT]].
109export type output_mode = int;
110
111// Output modes, see [[termbox2::set_output_mode]].
112export def OUTPUT = struct {
113 CURRENT: output_mode = 0,
114 NORMAL: output_mode = 1,
115 _256: output_mode = 2,
116 _216: output_mode = 3,
117 GRAYSCALE: output_mode = 4,
118 TRUECOLOR: output_mode = 5, // only available if OPT_ATTR_W >= 32
119};
120
121// Type for error return values, see [[termbox2::ERR]].
122export type err = !int;
123
124// Common error return values.
125//
126// Library behavior is undefined after receiving ERR.MEM.
127// Callers may attempt reinitializing by freeing memory, invoking
128// [[termbox2::shutdown]], then [[termbox2::init]].
129export def ERR = struct {
130 ERR: err = -1,
131 NEED_MORE: err = -2,
132 INIT_ALREADY: err = -3,
133 INIT_OPEN: err = -4,
134 MEM: err = -5,
135 NO_EVENT: err = -6,
136 NO_TERM: err = -7,
137 NOT_INIT: err = -8,
138 OUT_OF_BOUNDS: err = -9,
139 READ: err = -10,
140 RESIZE_IOCTL: err = -11,
141 RESIZE_PIPE: err = -12,
142 RESIZE_SIGACTION: err = -13,
143 POLL: err = -14,
144 SELECT: err = -14,
145 TCGETATTR: err = -15,
146 TCSETATTR: err = -16,
147 UNSUPPORTED_TERM: err = -17,
148 RESIZE_WRITE: err = -18,
149 RESIZE_POLL: err = -19,
150 RESIZE_SELECT: err = -19,
151 RESIZE_READ: err = -20,
152 RESIZE_SSCANF: err = -21,
153 CAP_COLLISION: err = -22,
154 HARE_BUILD: err = -9990, // Additional error type
155 HARE_INVALID_UTF8: err = -9991, // Additional error type
156 HARE_OTHER: err = -9992, // Additional error type
157};
158
159// An incoming key press event. Note that there is overlap between
160// MOD.CTRL and KEY.CTRL_* keys. MOD.CTRL and MOD.SHIFT are only set
161// as modifiers to KEY.ARROW_*.
162export type key_event = struct {
163 mod: mod, // Modifier
164 key_or_ch: (key | rune), // A [[termbox2::KEY]] or a Unicode code point
165};
166
167// An incoming resize event.
168export type resize_event = struct {
169 w: i32, // resize width
170 h: i32, // resize height
171};
172
173// An incoming mouse event.
174export type mouse_event = struct {
175 key: key, // Mouse button, e.g. termbox2::KEY.MOUSE_LEFT
176 x: i32,
177 y: i32,
178};
179
180// The C data structure for an event, for compatibility.
181type tb_event = struct {
182 t: u8,
183 mod: u8,
184 key: u16,
185 ch: u32,
186 w: i32,
187 h: i32,
188 x: i32,
189 y: i32,
190};
191
192def TB_EVENT_KEY: u8 = 1;
193def TB_EVENT_RESIZE: u8 = 2;
194def TB_EVENT_MOUSE: u8 = 3;
195fn tb_event_to_event(e: tb_event) (event | err) = switch (e.t) {
196 case TB_EVENT_KEY => yield key_event {
197 mod = e.mod,
198 key_or_ch = if (e.key != 0) e.key: key else e.ch: rune,
199 };
200 case TB_EVENT_RESIZE => yield resize_event {
201 w = e.w,
202 h = e.h,
203 };
204 case TB_EVENT_MOUSE => yield mouse_event {
205 key = e.key,
206 x = e.x,
207 y = e.y,
208 };
209 case => yield ERR.HARE_OTHER;
210 };
211
212// Any incoming event from the tty.
213export type event = (key_event | resize_event | mouse_event);
214
215fn build_opts_match() bool =
216 (has_egc() == OPT_EGC) &&
217 (attr_width() == OPT_ATTR_W) &&
218 (has_truecolor() == (OPT_ATTR_W == 32 || OPT_ATTR_W == 64));
219
220fn void_or_err(r: int) (void | err) = if (r < 0) r: err;
221fn int_or_err(r: int) (int | err) = if (r < 0) r: err else r;
222fn size_or_err(r: int) (size | err) = if (r < 0) r: err else r: size;
223fn str_or_err(cstr: *c::char) (str | err) = match(c::tostr(cstr)) {
224 case utf8::invalid => yield ERR.HARE_INVALID_UTF8;
225 case let s: str => yield s;
226};
227
228// Initialize the termbox library. This function should be called before
229// any other functions. After successful initialization, the library must
230// be finalized using [[termbox2::shutdown]].
231export fn init() (void | err) =
232 if (!build_opts_match())
233 ERR.HARE_BUILD
234 else
235 void_or_err(tb_init());
236@symbol("tb_init") fn tb_init() int;
237
238// Same as [[termbox2::init]], but allows to specify a file path in place
239// of the default /dev/tty.
240export fn init_file(path: str) (void | err) = {
241 let c_path = c::fromstr(path)!;
242 defer free(c_path);
243 return if (!build_opts_match())
244 ERR.HARE_BUILD
245 else
246 void_or_err(tb_init_file(c_path));
247};
248@symbol("tb_init_file") fn tb_init_file(cstr: *c::char) int;
249
250// Same as [[termbox2::init]], but allows to specify an output
251// file descriptor.
252export fn init_fd(ttyfd: int) (void | err) =
253 if (!build_opts_match())
254 ERR.HARE_BUILD
255 else
256 void_or_err(tb_init_fd(ttyfd));
257@symbol("tb_init_fd") fn tb_init_fd(fd: int) int;
258
259// Same as [[termbox2::init]], but allows to specify input and output
260// file descriptors.
261export fn init_rwfd(rfd: int, wfd: int) (void | err) =
262 if (!build_opts_match())
263 ERR.HARE_BUILD
264 else
265 void_or_err(tb_init_rwfd(rfd, wfd));
266@symbol("tb_init_rwfd") fn tb_init_rwfd(rfd: int, wfd: int) int;
267
268// Finalizes the library.
269export fn shutdown() (void | err) = void_or_err(tb_shutdown());
270@symbol("tb_shutdown") fn tb_shutdown() int;
271
272// Return the width of the internal back buffer (which is the same as the
273// terminal's window width in columns). The internal buffer can be resized
274// after [[termbox2::clear]] or [[termbox2::present]] calls. Returns ERR.ERR
275// when called before [[termbox2::init]] or after [[termbox2::shutdown]].
276export fn width() (size | err) = size_or_err(tb_width());
277@symbol("tb_width") fn tb_width() int;
278
279// Return the height of the internal back buffer (which is the same as the
280// terminal's window width in rows). The internal buffer can be resized
281// after [[termbox2::clear]] or [[termbox2::present]] calls. Returns ERR.ERR
282// when called before [[termbox2::init]] or after [[termbox2::shutdown]].
283export fn height() (size | err) = size_or_err(tb_height());
284@symbol("tb_height") fn tb_height() int;
285
286// Clear the internal back buffer using [[termbox2::ATTRIBUTE]].DEFAULT.
287export fn clear() (void | err) = void_or_err(tb_clear());
288@symbol("tb_clear") fn tb_clear() int;
289
290// Clear the internal back buffer using the specified attributes.
291export fn set_clear_attrs(fg: uattr, bg: uattr) (void | err) =
292 void_or_err(tb_set_clear_attrs(fg, bg));
293@symbol("tb_set_clear_attrs") fn tb_set_clear_attrs(fg: uattr, bg: uattr) int;
294
295// Synchronize the internal back buffer with the terminal by
296// writing to tty.
297export fn present() (void | err) = void_or_err(tb_present());
298@symbol("tb_present") fn tb_present() int;
299
300// Clear the internal front buffer effectively forcing a complete re-render
301// of the back buffer to the tty. It is not necessary to call this under
302// normal circumstances.
303export fn invalidate() (void | err) = void_or_err(tb_invalidate());
304@symbol("tb_invalidate") fn tb_invalidate() int;
305
306// Set the position of the cursor. Upper-left cell is (0, 0).
307export fn set_cursor(cx: int, cy: int) (void | err) =
308 void_or_err(tb_set_cursor(cx, cy));
309@symbol("tb_set_cursor") fn tb_set_cursor(x: int, y: int) int;
310
311// Hide the cursor.
312export fn hide_cursor() (void | err) = void_or_err(tb_hide_cursor());
313@symbol("tb_hide_cursor") fn tb_hide_cursor() int;
314
315// Set cell contents in the internal back buffer at the specified position.
316// Non-printable runes are replaced with U+FFFD at render time.
317export fn set_cell(
318 x: int,
319 y: int,
320 ch: rune,
321 fg: uattr,
322 bg: uattr,
323) (void | err) = void_or_err(tb_set_cell(x, y, ch: u32, fg, bg));
324@symbol("tb_set_cell") fn tb_set_cell(
325 x: int,
326 y: int,
327 ch: u32,
328 fg: uattr,
329 bg: uattr,
330) int;
331
332// Set extended cell contents. Only available when OPT_ATTR_W >= 32.
333// See also [[termbox2::set_cell]] and [[termbox2::cell]].
334export fn set_cell_ex(
335 x: int,
336 y: int,
337 ch: []rune,
338 fg: uattr,
339 bg: uattr,
340) (void | err) =
341 void_or_err(tb_set_cell_ex(x, y, &ch[0]: *u32, len(ch), fg, bg));
342@symbol("tb_set_cell_ex") fn tb_set_cell_ex(
343 x: int,
344 y: int,
345 ch: *u32,
346 n: size,
347 fg: uattr,
348 bg: uattr,
349) int;
350
351// Add one character to the cell's ech. Only available when OPT_ATTR_W >= 32.
352// See also [[termbox2::set_cell_ex]] and [[termbox2::cell]].
353export fn extend_cell(x: int, y: int, ch: rune) (void | err) =
354 void_or_err(tb_extend_cell(x, y, ch: u32));
355@symbol("tb_extend_cell") fn tb_extend_cell(x: int, y: int, ch: u32) int;
356
357// Set the input mode, see [[termbox2::INPUT]].
358//
359// Termbox has two input modes:
360// - INPUT.ESC When escape (\x1b) is in the buffer and there's no match
361// for an escape sequence, a key event for [[termbox2::KEY]].ESC is returned.
362// - INPUT.ALT When escape (\x1b) is in the buffer and there's no match
363// for an an escape sequence, the next keyboard event is returned with a
364// [[termbox2::MOD]].ALT modifier.
365//
366// You can also apply termbox2::INPUT.MOUSE via bitwise OR operation to either
367// of the modes (e.g., INPUT.ALT | INPUT.MOUSE) to receive
368// [[termbox2::mouse_event]] events. If none of the main two modes were
369// set, but the mouse mode was, INPUT.ESC is used. If for some reason you've
370// decided to use INPUT.ESC | INPUT.ALT, it will behave as if only INPUT.ESC
371// was selected.
372//
373// If mode is INPUT.CURRENT, return the current input mode.
374//
375// The default input mode is INPUT.ESC.
376export fn set_input_mode(mode: input_mode) (int | err) =
377 int_or_err(tb_set_input_mode(mode: int));
378@symbol("tb_set_input_mode") fn tb_set_input_mode(mode: int) int;
379
380// Set the output mode, see [[termbox2::OUTPUT]].
381//
382// Termbox has multiple output modes:
383//
384// 1. OUTPUT.NORMAL => [0..8]
385//
386// This mode provides 8 different colors (see [[termbox2::COLOR]]), plus
387// COLOR.DEFAULT which skips sending a color code (i.e., uses the terminal's
388// default color). Colors may be bitwise OR'd with style attributes, see
389// [[termbox2::ATTRIBUTE]]. Extra attributes are available if OPT_ATTR_W == 64.
390//
391// Some notes: ATTRIBUTE.REVERSE and ATTRIBUTE.BRIGHT can be applied as either
392// fg or bg attributes for the same effect. The rest of the attributes apply to
393// fg only and are ignored as bg attributes.
394//
395// Example usage:
396//
397// let fg = termbox2::COLOR.BLACK | termbox2::ATTRIBUTE.BOLD;
398// let bg = termbox2::COLOR.RED;
399// termbox2::set_cell(x, y, '@', fg, bg);
400//
401// 2. OUTPUT._256 => [0..255] + ATTRIBUTE.HI_BLACK
402//
403// In this mode you get 256 distinct colors (plus default):
404// - 0x00 (1): ATTRIBUTE.DEFAULT
405// - ATTRIBUTE.HI_BLACK (1): COLOR.BLACK in OUTPUT.NORMAL
406// - 0x01..0x07 (7): the next 7 colors as in OUTPUT.NORMAL
407// - 0x08..0x0f (8): bright versions of the above
408// - 0x10..0xe7 (216): 216 different colors
409// - 0xe8..0xff (24): 24 different shades of gray
410//
411// All style attributes except ATTRIBUTE.BRIGHT may be bitwise OR'd as in
412// OUTPUT.NORMAL.
413//
414// Note COLOR.BLACK must be used for black, as 0x00 represents default.
415//
416// 3. OUTPUT._216 => [0..216]
417//
418// This mode supports the 216-color range of OUTPUT._256 only, but you
419// don't need to provide an offset:
420// - 0x00 (1): COLOR.DEFAULT
421// - 0x01..0xd8 (216): 216 different colors
422//
423// 4. OUTPUT.GRAYSCALE => [0..24]
424//
425// This mode supports the 24-color range of OUTPUT._256 only, but you
426// don't need to provide an offset:
427// - 0x00 (1): COLOR.DEFAULT
428// - 0x01..0x18 (24): 24 different shades of gray
429//
430// 5. OUTPUT.TRUECOLOR => [0x000000..0xffffff] + ATTRIBUTE.HI_BLACK
431//
432// This mode provides 24-bit color on supported terminals.
433// The format is 0xRRGGBB.
434//
435// All style attributes except ATTRIBUTE.BRIGHT may be bitwise OR'd as in
436// OUTPUT.NORMAL.
437//
438// Note ATTRIBUTE.HI_BLACK must be used for black, as 0x000000 represents
439// default.
440//
441// To use the terminal default color (i.e., to not send an escape code), pass
442// COLOR.DEFAULT. For convenience, the value 0 is interpreted as COLOR.DEFAULT
443// in all modes.
444//
445// Note, cell attributes persist after switching output modes. Any translation
446// between, for example, OUTPUT.NORMAL's COLOR.RED and OUTPUT.TRUECOLOR's
447// 0xff0000 must be performed by the caller. Also note that cells previously
448// rendered in one mode may persist unchanged until the front buffer is cleared
449// (such as after a resize event) at which point it will be re-interpreted and
450// flushed according to the current mode. Callers may invoke
451// [[termbox2::invalidate]] if it is desirable to immediately re-interpret
452// and flush the entire screen according to the current mode.
453//
454// Note, not all terminals support all output modes, especially beyond
455// OUTPUT.NORMAL. There is also no very reliable way to determine color
456// support dynamically. If portability is desired, callers are recommended to
457// use OUTPUT.NORMAL or make output mode end-user configurable. The same
458// advice applies to style attributes.
459//
460// If mode is OUTPUT.CURRENT, return the current output mode.
461//
462// The default output mode is OUTPUT.NORMAL.
463export fn set_output_mode(mode: output_mode) (int | err) =
464 int_or_err(tb_set_output_mode(mode: int));
465@symbol("tb_set_output_mode") fn tb_set_output_mode(mode: int) int;
466
467// Wait for an event up to timeout_ms milliseconds and return it. If no event
468// is available within the timeout period, ERR.NO_EVENT is returned. On a resize
469// event, the underlying select(2) call may be interrupted, yielding a return
470// code of ERR.POLL.
471export fn peek_event(timeout_ms: size) (event | err) = {
472 let e = tb_event {
473 t = 0,
474 mod = 0,
475 key = 0,
476 ch = 0,
477 w = 0,
478 h = 0,
479 x = 0,
480 y = 0,
481 };
482 let r = tb_peek_event(&e, timeout_ms: int);
483 return if (r < 0) r: err else tb_event_to_event(e);
484};
485@symbol("tb_peek_event") fn tb_peek_event(ev: *tb_event, t: int) int;
486
487// Same as [[termbox2::peek_event]] except no timeout.
488export fn poll_event() (event | err) = {
489 let e = tb_event {
490 t = 0,
491 mod = 0,
492 key = 0,
493 ch = 0,
494 w = 0,
495 h = 0,
496 x = 0,
497 y = 0,
498 };
499 let r = tb_poll_event(&e);
500 return if (r < 0) r: err else tb_event_to_event(e);
501};
502@symbol("tb_poll_event") fn tb_poll_event(ev: *tb_event) int;
503
504// Internal termbox fds that can be used with poll(2), select(2), etc.
505// externally. Callers must invoke [[termbox2::poll_event]] or
506// [[termbox2::peek_event]] if fds become readable.
507export fn get_fds() ((int, int) | err) = {
508 let ttyfd: int = 0;
509 let resizefd: int = 0;
510 let r = tb_get_fds(&ttyfd, &resizefd);
511 return if (r < 0) r: err else (ttyfd, resizefd);
512};
513@symbol("tb_get_fds") fn tb_get_fds(ttyfd: *int, resizefd: *int) int;
514
515// Print function. On success, it returns the width of the printed string.
516// Strings are interpreted as UTF-8.
517//
518// No attempt is made to do proper grapheme cluster parsing. With
519// [[termbox2::OPT_EGC]] enabled, as a very coarse approximation, codepoints
520// of width 0 are tacked on to the previous codepoint via
521// [[termbox2::extend_cell]].
522//
523// Non-printable characters (iswprint(3)) and truncated UTF-8 byte sequences
524// are replaced with U+FFFD.
525//
526// Newlines (\n) are supported with the caveat that the return value will be
527// the width of the string as if it were on a single line.
528//
529// If the starting coordinate is out of bounds, ERR.OUT_OF_BOUNDS is returned.
530// If the starting coordinates is in bounds, but goes out of bounds, then the
531// out-of-bounds portions of the string are ignored.
532//
533// For finer control, use [[termbox2::set_cell]].
534export fn print(
535 x: int,
536 y: int,
537 fg: uattr,
538 bg: uattr,
539 fmt_str: str,
540 args: fmt::field...
541) (size | err) = {
542 let s = fmt::asprintf(fmt_str, args...)!;
543 defer free(s);
544 let cstr = c::fromstr(s)!;
545 defer free(cstr);
546 let outw: size = 0;
547 let e = tb_print_ex(x, y, fg, bg, &outw, cstr);
548 return if (e < 0) e: err else outw;
549};
550@symbol("tb_print_ex") fn tb_print_ex(
551 x: int,
552 y: int,
553 fg: uattr,
554 bg: uattr,
555 out_w: *size,
556 cstr: const *c::char,
557) int;
558
559// Send raw bytes to the terminal.
560export fn send(buf: []u8) (void | err) =
561 void_or_err(tb_send(&buf[0]: *c::char, len(buf)));
562@symbol("tb_send") fn tb_send(buf: const *c::char, nbuf: size) int;
563
564// Returns a string explaining the given error code. The caller must free
565// the return value.
566export fn strerror(e: err) str = switch (e) {
567 case ERR.HARE_BUILD =>
568 yield fmt::asprintf(
569 "Cannot initialize Termbox because of a mismatch "
570 "between the C and Hare build options.\n"
571 "Hare OPT_EGC is {} and C TB_OPT_EGC is {}\n"
572 "Hare OPT_ATTR_W {} and C TB_OPT_ATTR_W is {}",
573 OPT_EGC, has_egc(), OPT_ATTR_W, attr_width()
574 )!;
575 case ERR.HARE_INVALID_UTF8 =>
576 yield fmt::asprintf("Invalid UTF8 sequence recieved from tb")!;
577 case ERR.HARE_OTHER =>
578 yield fmt::asprintf("Unknown error in the Hare bindings")!;
579 case => yield match (str_or_err(tb_strerror(e: int))) {
580 case err => yield fmt::asprintf(
581 "Unexpected error while interpreting previous error"
582 )!;
583 case let estr: str => yield estr;
584 };
585};
586@symbol("tb_strerror") fn tb_strerror(e: int) const *c::char;
587
588// Returns true if the the C termbox2 library was compiled with truecolor
589// support (i.e., if [[termbox2::OPT_ATTR_W]] is 32 or 64).
590export fn has_truecolor() bool = tb_has_truecolor() != 0;
591@symbol("tb_has_truecolor") fn tb_has_truecolor() int;
592
593// Returns true if the the C termbox2 library was compiled with EGC
594// support (i.e., if [[termbox2::OPT_EGC]] is true).
595export fn has_egc() bool = tb_has_egc() != 0;
596@symbol("tb_has_egc") fn tb_has_egc() int;
597
598// Returns the value of the TB_OPT_ATTR_W compile time option of the
599// C termbox2 library.
600export fn attr_width() size = tb_attr_width(): size;
601@symbol("tb_attr_width") fn tb_attr_width() int;
602
603// Returns the string version of the C termbox2 library.
604export fn version() (str | err) = str_or_err(tb_version());
605@symbol("tb_version") fn tb_version() const *c::char;

Generated with cgit - Back to sebastiano.tronto.net