1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 
5 #ifndef __TICKIT_H__
6 #define __TICKIT_H__
7 
8 /* We'd quite like the timer*() functions */
9 #ifndef _DEFAULT_SOURCE
10 # define _DEFAULT_SOURCE
11 #endif
12 
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdbool.h>
18 
19 #include <sys/time.h>
20 
21 #ifdef __GNUC__
22 # define DEPRECATED __attribute__((deprecated))
23 #else
24 # define DEPRECATED
25 #endif
26 
27 #define TICKIT_VERSION_MAJOR 0
28 #define TICKIT_VERSION_MINOR 4
29 #define TICKIT_VERSION_PATCH 2
30 
31 int tickit_version_major(void);
32 int tickit_version_minor(void);
33 int tickit_version_patch(void);
34 
35 /*
36  * Top-level object / structure types
37  */
38 
39 typedef struct TickitPen TickitPen;
40 typedef struct TickitRectSet TickitRectSet;
41 typedef struct TickitRenderBuffer TickitRenderBuffer;
42 typedef struct TickitString TickitString;
43 typedef struct TickitTerm TickitTerm;
44 typedef struct TickitWindow TickitWindow;
45 
46 typedef struct Tickit Tickit;
47 
48 /* Opaque struct pointers required but not part of official API */
49 typedef struct TickitTermDriver TickitTermDriver;
50 
51 /* Forward declaration to pointer defined by <tickit-evloop.h> */
52 typedef struct TickitEventHooks TickitEventHooks;
53 
54 typedef struct {
55   int top;
56   int left;
57   int lines;
58   int cols;
59 } TickitRect;
60 
61 /*
62  * Enumerations
63  */
64 
65 typedef enum {
66   TICKIT_BIND_FIRST   = 1<<0,
67   TICKIT_BIND_UNBIND  = 1<<1,
68   TICKIT_BIND_DESTROY = 1<<2,
69   TICKIT_BIND_ONESHOT = 1<<3,
70 } TickitBindFlags;
71 
72 typedef enum {
73   TICKIT_CTL_USE_ALTSCREEN = 1,
74 
75   TICKIT_N_CTLS
76 } TickitCtl;
77 
78 typedef enum {
79   TICKIT_CURSORSHAPE_BLOCK = 1,
80   TICKIT_CURSORSHAPE_UNDER,
81   TICKIT_CURSORSHAPE_LEFT_BAR,
82 } TickitCursorShape;
83 
84 typedef enum {
85   TICKIT_IO_IN    = 1<<0,
86   TICKIT_IO_OUT   = 1<<1,
87   TICKIT_IO_HUP   = 1<<2,
88   TICKIT_IO_ERR   = 1<<3,
89   TICKIT_IO_INVAL = 1<<4,
90 } TickitIOCondition;
91 
92 typedef struct {
93   int fd;
94   TickitIOCondition cond;
95 } TickitIOWatchInfo;
96 
97 typedef enum {
98   TICKIT_LINECAP_START = 0x01,
99   TICKIT_LINECAP_END   = 0x02,
100   TICKIT_LINECAP_BOTH  = 0x03,
101 } TickitLineCaps;
102 
103 typedef enum {
104   TICKIT_LINE_SINGLE = 1,
105   TICKIT_LINE_DOUBLE = 2,
106   TICKIT_LINE_THICK  = 3,
107 } TickitLineStyle;
108 
109 typedef enum {
110   TICKIT_NO    =  0,
111   TICKIT_YES   =  1,
112   TICKIT_MAYBE = -1,
113 } TickitMaybeBool;
114 
115 typedef enum {
116   TICKIT_PEN_FG = 1,     /* colour */
117   TICKIT_PEN_BG,         /* colour */
118   TICKIT_PEN_BOLD,       /* bool */
119   TICKIT_PEN_UNDER,      /* number */
120   TICKIT_PEN_ITALIC,     /* bool */
121   TICKIT_PEN_REVERSE,    /* bool */
122   TICKIT_PEN_STRIKE,     /* bool */
123   TICKIT_PEN_ALTFONT,    /* number */
124   TICKIT_PEN_BLINK,      /* bool */
125 
126   TICKIT_N_PEN_ATTRS
127 } TickitPenAttr;
128 
129 typedef struct {
130   pid_t pid;
131   int wstatus;
132 } TickitProcessWatchInfo;
133 
134 /* additional attribute types recognised by tickit_pen_new_attrs */
135 enum {
136   /* We're unlikely to ever have 256 attributes, so adding 0x100 should be safe */
137   TICKIT_PEN_FG_DESC = 0x100 + TICKIT_PEN_FG,
138   TICKIT_PEN_BG_DESC = 0x100 + TICKIT_PEN_BG,
139 };
140 
141 typedef enum {
142   TICKIT_PEN_UNDER_NONE,
143   TICKIT_PEN_UNDER_SINGLE,
144   TICKIT_PEN_UNDER_DOUBLE,
145   TICKIT_PEN_UNDER_WAVY,
146 
147   TICKIT_N_PEN_UNDERS
148 } TickitPenUnderline;
149 
150 typedef enum {
151   TICKIT_RUN_DEFAULT = 0,
152   TICKIT_RUN_ONCE    = 1<<0,
153   TICKIT_RUN_NOHANG  = 1<<1,
154   TICKIT_RUN_NOSETUP = 1<<2,
155 } TickitRunFlags;
156 
157 typedef enum {
158   /* This is part of the API so additions must go at the end only */
159   TICKIT_TERMCTL_ALTSCREEN = 1,
160   TICKIT_TERMCTL_CURSORVIS,
161   TICKIT_TERMCTL_MOUSE,
162   TICKIT_TERMCTL_CURSORBLINK,
163   TICKIT_TERMCTL_CURSORSHAPE,
164   TICKIT_TERMCTL_ICON_TEXT,
165   TICKIT_TERMCTL_TITLE_TEXT,
166   TICKIT_TERMCTL_ICONTITLE_TEXT,
167   TICKIT_TERMCTL_KEYPAD_APP,
168   TICKIT_TERMCTL_COLORS, // read-only
169 
170   TICKIT_N_TERMCTLS
171 } TickitTermCtl;
172 
173 typedef enum {
174   TICKIT_TERM_MOUSEMODE_OFF,
175   TICKIT_TERM_MOUSEMODE_CLICK,
176   TICKIT_TERM_MOUSEMODE_DRAG,
177   TICKIT_TERM_MOUSEMODE_MOVE,
178 } TickitTermMouseMode;
179 
180 typedef enum {
181   TICKIT_TYPE_NONE,
182   TICKIT_TYPE_BOOL,
183   TICKIT_TYPE_INT,
184   TICKIT_TYPE_STR,
185   TICKIT_TYPE_COLOUR, // currently unused except by pen
186 } TickitType;
187 
188 typedef enum {
189   TICKIT_WINCTL_STEAL_INPUT = 1,
190   TICKIT_WINCTL_FOCUS_CHILD_NOTIFY,
191   TICKIT_WINCTL_CURSORVIS,
192   TICKIT_WINCTL_CURSORBLINK,
193   TICKIT_WINCTL_CURSORSHAPE,
194 
195   TICKIT_N_WINCTLS
196 } TickitWindowCtl;
197 
198 typedef enum {
199   TICKIT_WINDOW_HIDDEN      = 1<<0,
200   TICKIT_WINDOW_LOWEST      = 1<<1,
201   TICKIT_WINDOW_ROOT_PARENT = 1<<2,
202   TICKIT_WINDOW_STEAL_INPUT = 1<<3,
203 
204   // Composite flag
205   TICKIT_WINDOW_POPUP = TICKIT_WINDOW_ROOT_PARENT|TICKIT_WINDOW_STEAL_INPUT,
206 } TickitWindowFlags;
207 
208 // TODO: this wants a name surely?
209 enum {
210   TICKIT_MOD_SHIFT = 0x01,
211   TICKIT_MOD_ALT   = 0x02,
212   TICKIT_MOD_CTRL  = 0x04,
213 };
214 
215 /* back-compat name */
216 typedef enum {
217   TICKIT_PENTYPE_BOOL   = TICKIT_TYPE_BOOL,
218   TICKIT_PENTYPE_INT    = TICKIT_TYPE_INT,
219   TICKIT_PENTYPE_COLOUR = TICKIT_TYPE_COLOUR,
220 } TickitPenAttrType;
221 
222 /*
223  * Secondary structures
224  */
225 
226 typedef struct {
227   size_t bytes;
228   int    codepoints;
229   int    graphemes;
230   int    columns;
231 } TickitStringPos;
232 
233 /*
234  * Event types
235  */
236 
237 typedef enum {
238   TICKIT_EV_FIRE = (1 << 0),
239   TICKIT_EV_UNBIND = (1 << 1),
240   TICKIT_EV_DESTROY = (1 << 2),
241 } TickitEventFlags;
242 
243 typedef struct {
244   int lines, cols;
245 } TickitResizeEventInfo;
246 
247 typedef enum {
248   TICKIT_KEYEV_KEY = 1,
249   TICKIT_KEYEV_TEXT,
250 } TickitKeyEventType;
251 
252 typedef struct {
253   TickitKeyEventType type;
254   int mod;
255   const char *str;
256 } TickitKeyEventInfo;
257 
258 typedef enum {
259   TICKIT_MOUSEEV_PRESS = 1,
260   TICKIT_MOUSEEV_DRAG,
261   TICKIT_MOUSEEV_RELEASE,
262   TICKIT_MOUSEEV_WHEEL,
263 
264   TICKIT_MOUSEEV_DRAG_START = 0x101,
265   TICKIT_MOUSEEV_DRAG_OUTSIDE,
266   TICKIT_MOUSEEV_DRAG_DROP,
267   TICKIT_MOUSEEV_DRAG_STOP,
268 } TickitMouseEventType;
269 
270 enum {
271   TICKIT_MOUSEWHEEL_UP = 1,
272   TICKIT_MOUSEWHEEL_DOWN,
273 };
274 
275 typedef struct {
276   TickitMouseEventType type;
277   int button;
278   int mod;
279   int line, col;
280 } TickitMouseEventInfo;
281 
282 typedef struct {
283   TickitRect rect;
284   TickitRect oldrect;
285 } TickitGeomchangeEventInfo;
286 
287 typedef struct {
288   TickitRect rect;
289   TickitRenderBuffer *rb;
290 } TickitExposeEventInfo;
291 
292 typedef enum {
293   TICKIT_FOCUSEV_IN = 1,
294   TICKIT_FOCUSEV_OUT,
295 } TickitFocusEventType;
296 
297 typedef struct {
298   TickitFocusEventType type;
299   TickitWindow *win;
300 } TickitFocusEventInfo;
301 
302 /*
303  * Functions
304  */
305 
306 /* TickitPen */
307 
308 TickitPen *tickit_pen_new(void);
309 TickitPen *tickit_pen_new_attrs(TickitPenAttr attr, ...);
310 TickitPen *tickit_pen_clone(const TickitPen *orig);
311 
312 TickitPen *tickit_pen_ref(TickitPen *pen);
313 void       tickit_pen_unref(TickitPen *pen);
314 
315 bool tickit_pen_has_attr(const TickitPen *pen, TickitPenAttr attr);
316 bool tickit_pen_is_nonempty(const TickitPen *pen);
317 bool tickit_pen_nondefault_attr(const TickitPen *pen, TickitPenAttr attr);
318 bool tickit_pen_is_nondefault(const TickitPen *pen);
319 
320 bool tickit_pen_get_bool_attr(const TickitPen *pen, TickitPenAttr attr);
321 void tickit_pen_set_bool_attr(TickitPen *pen, TickitPenAttr attr, bool val);
322 
323 int  tickit_pen_get_int_attr(const TickitPen *pen, TickitPenAttr attr);
324 void tickit_pen_set_int_attr(TickitPen *pen, TickitPenAttr attr, int val);
325 
326 int  tickit_pen_get_colour_attr(const TickitPen *pen, TickitPenAttr attr);
327 void tickit_pen_set_colour_attr(TickitPen *pen, TickitPenAttr attr, int value);
328 
329 typedef struct {
330   uint8_t r, g, b;
331 } TickitPenRGB8;
332 
333 bool tickit_pen_has_colour_attr_rgb8(const TickitPen *pen, TickitPenAttr attr);
334 TickitPenRGB8 tickit_pen_get_colour_attr_rgb8(const TickitPen *pen, TickitPenAttr attr);
335 void tickit_pen_set_colour_attr_rgb8(TickitPen *pen, TickitPenAttr attr, TickitPenRGB8 value);
336 
337 bool tickit_pen_set_colour_attr_desc(TickitPen *pen, TickitPenAttr attr, const char *value);
338 
339 void tickit_pen_clear_attr(TickitPen *pen, TickitPenAttr attr);
340 void tickit_pen_clear(TickitPen *pen);
341 
342 bool tickit_pen_equiv_attr(const TickitPen *a, const TickitPen *b, TickitPenAttr attr);
343 bool tickit_pen_equiv(const TickitPen *a, const TickitPen *b);
344 
345 void tickit_pen_copy_attr(TickitPen *dst, const TickitPen *src, TickitPenAttr attr);
346 void tickit_pen_copy(TickitPen *dst, const TickitPen *src, bool overwrite);
347 
348 typedef int TickitPenEventFn(TickitPen *tt, TickitEventFlags flags, void *info, void *user);
349 
350 typedef enum {
351   TICKIT_PEN_ON_DESTROY,
352   TICKIT_PEN_ON_CHANGE,
353 } TickitPenEvent;
354 
355 int  tickit_pen_bind_event(TickitPen *tt, TickitPenEvent ev, TickitBindFlags flags,
356     TickitPenEventFn *fn, void *user);
357 void tickit_pen_unbind_event_id(TickitPen *tt, int id);
358 
359 TickitPenAttrType tickit_pen_attrtype(TickitPenAttr attr);
360 const char *tickit_pen_attrname(TickitPenAttr attr);
361 TickitPenAttr tickit_pen_lookup_attr(const char *name);
362 
363 /* TickitRect */
364 
365 void tickit_rect_init_sized(TickitRect *rect, int top, int left, int lines, int cols);
366 void tickit_rect_init_bounded(TickitRect *rect, int top, int left, int bottom, int right);
367 
tickit_rect_bottom(const TickitRect * rect)368 static inline int tickit_rect_bottom(const TickitRect *rect)
369 { return rect->top + rect->lines; }
370 
tickit_rect_right(const TickitRect * rect)371 static inline int tickit_rect_right (const TickitRect *rect)
372 { return rect->left + rect->cols; }
373 
374 void tickit_rect_translate(TickitRect *rect, int downward, int rightward);
375 
376 bool tickit_rect_intersect(TickitRect *dst, const TickitRect *a, const TickitRect *b);
377 
378 bool tickit_rect_intersects(const TickitRect *a, const TickitRect *b);
379 bool tickit_rect_contains(const TickitRect *large, const TickitRect *small);
380 
381 int tickit_rect_add(TickitRect ret[3], const TickitRect *a, const TickitRect *b);
382 int tickit_rect_subtract(TickitRect ret[4], const TickitRect *orig, const TickitRect *hole);
383 
384 /* TickitRectSet */
385 
386 TickitRectSet *tickit_rectset_new(void);
387 void tickit_rectset_destroy(TickitRectSet *trs);
388 
389 void tickit_rectset_clear(TickitRectSet *trs);
390 
391 size_t tickit_rectset_rects(const TickitRectSet *trs);
392 size_t tickit_rectset_get_rect(const TickitRectSet *trs, size_t i, TickitRect *rects);
393 size_t tickit_rectset_get_rects(const TickitRectSet *trs, TickitRect rects[], size_t n);
394 
395 void tickit_rectset_add(TickitRectSet *trs, const TickitRect *rect);
396 void tickit_rectset_subtract(TickitRectSet *trs, const TickitRect *rect);
397 
398 void tickit_rectset_translate(TickitRectSet *trs, int downward, int rightward);
399 
400 bool tickit_rectset_intersects(const TickitRectSet *trs, const TickitRect *rect);
401 bool tickit_rectset_contains(const TickitRectSet *trs, const TickitRect *rect);
402 
403 /* TickitString */
404 
405 TickitString *tickit_string_new(const char *str, size_t len);
406 TickitString *tickit_string_ref(TickitString *s);
407 void tickit_string_unref(TickitString *s);
408 const char *tickit_string_get(const TickitString *s);
409 size_t tickit_string_len(const TickitString *s);
410 
411 /* TickitTerm */
412 
413 TickitTerm *tickit_term_new(void);
414 TickitTerm *tickit_term_new_for_termtype(const char *termtype);
415 void tickit_term_destroy(TickitTerm *tt);
416 
417 typedef void TickitTermOutputFunc(TickitTerm *tt, const char *bytes, size_t len, void *user);
418 
419 struct TickitTermBuilder {
420   const char *termtype;
421 
422   enum {
423     TICKIT_NO_OPEN,
424     TICKIT_OPEN_FDS,    /* use input_fd, output_fd */
425     TICKIT_OPEN_STDIO,  /* input=0, output=1 */
426     TICKIT_OPEN_STDTTY, /* input = output = first of 0/1/2 for which isatty() is true */
427     /* TODO: Consider
428      *   TICKIT_OPEN_DEVTTY to open /dev/tty
429      */
430   } open;
431   int input_fd, output_fd; /* only valid if open==TICKIT_OPEN_FDS */
432 
433   TickitTermOutputFunc *output_func;
434   void                 *output_func_user;
435 
436   size_t output_buffersize;
437 
438   /* Fields below here are undocumented and for vaguely internal or
439    * special-case purposes
440    */
441   TickitTermDriver *driver;
442 
443   const struct TickitTerminfoHook {
444     const char *(*getstr)(const char *name, const char *value, void *data);
445     void         *data;
446   } *ti_hook;
447 };
448 TickitTerm *tickit_term_build(const struct TickitTermBuilder *builder);
449 
450 void tickit_term_teardown(TickitTerm *tt);
451 
452 TickitTerm *tickit_term_ref(TickitTerm *tt);
453 void        tickit_term_unref(TickitTerm *tt);
454 
455 TickitTerm *tickit_term_open_stdio(void);
456 
457 const char *tickit_term_get_termtype(TickitTerm *tt);
458 
459 void tickit_term_set_output_fd(TickitTerm *tt, int fd);
460 int  tickit_term_get_output_fd(const TickitTerm *tt);
461 void tickit_term_set_output_func(TickitTerm *tt, TickitTermOutputFunc *fn, void *user);
462 void tickit_term_set_output_buffer(TickitTerm *tt, size_t len);
463 
464 void tickit_term_await_started_msec(TickitTerm *tt, long msec);
465 void tickit_term_await_started_tv(TickitTerm *tt, const struct timeval *timeout);
466 void tickit_term_flush(TickitTerm *tt);
467 
468 void tickit_term_pause(TickitTerm *tt);
469 void tickit_term_resume(TickitTerm *tt);
470 
471 /* fd is allowed to be unset (-1); works abstractly */
472 void tickit_term_set_input_fd(TickitTerm *tt, int fd);
473 int  tickit_term_get_input_fd(const TickitTerm *tt);
474 
475 TickitMaybeBool tickit_term_get_utf8(const TickitTerm *tt);
476 void tickit_term_set_utf8(TickitTerm *tt, bool utf8);
477 
478 void tickit_term_input_push_bytes(TickitTerm *tt, const char *bytes, size_t len);
479 void tickit_term_input_readable(TickitTerm *tt);
480 int  tickit_term_input_check_timeout_msec(TickitTerm *tt);
481 void tickit_term_input_wait_msec(TickitTerm *tt, long msec);
482 void tickit_term_input_wait_tv(TickitTerm *tt, const struct timeval *timeout);
483 
484 void tickit_term_get_size(const TickitTerm *tt, int *lines, int *cols);
485 void tickit_term_set_size(TickitTerm *tt, int lines, int cols);
486 void tickit_term_refresh_size(TickitTerm *tt);
487 
488 void tickit_term_observe_sigwinch(TickitTerm *tt, bool observe);
489 
490 typedef int TickitTermEventFn(TickitTerm *tt, TickitEventFlags flags, void *info, void *user);
491 
492 typedef enum {
493   TICKIT_TERM_ON_DESTROY,
494   TICKIT_TERM_ON_RESIZE,
495   TICKIT_TERM_ON_KEY,
496   TICKIT_TERM_ON_MOUSE,
497 } TickitTermEvent;
498 
499 int  tickit_term_bind_event(TickitTerm *tt, TickitTermEvent ev, TickitBindFlags flags,
500     TickitTermEventFn *fn, void *user);
501 void tickit_term_unbind_event_id(TickitTerm *tt, int id);
502 
503 void tickit_term_print(TickitTerm *tt, const char *str);
504 void tickit_term_printn(TickitTerm *tt, const char *str, size_t len);
505 void tickit_term_printf(TickitTerm *tt, const char *fmt, ...);
506 void tickit_term_vprintf(TickitTerm *tt, const char *fmt, va_list args);
507 bool tickit_term_goto(TickitTerm *tt, int line, int col);
508 void tickit_term_move(TickitTerm *tt, int downward, int rightward);
509 bool tickit_term_scrollrect(TickitTerm *tt, TickitRect rect, int downward, int rightward);
510 
511 void tickit_term_chpen(TickitTerm *tt, const TickitPen *pen);
512 void tickit_term_setpen(TickitTerm *tt, const TickitPen *pen);
513 
514 void tickit_term_clear(TickitTerm *tt);
515 void tickit_term_erasech(TickitTerm *tt, int count, TickitMaybeBool moveend);
516 
517 bool tickit_term_getctl_int(TickitTerm *tt, TickitTermCtl ctl, int *value);
518 bool tickit_term_setctl_int(TickitTerm *tt, TickitTermCtl ctl, int value);
519 bool tickit_term_setctl_str(TickitTerm *tt, TickitTermCtl ctl, const char *value);
520 
521 void tickit_term_emit_key(TickitTerm *tt, TickitKeyEventInfo *info);
522 void tickit_term_emit_mouse(TickitTerm *tt, TickitMouseEventInfo *info);
523 
524 const char *tickit_term_ctlname(TickitTermCtl ctl);
525 TickitTermCtl tickit_term_lookup_ctl(const char *name);
526 
527 TickitType tickit_term_ctltype(TickitTermCtl ctl);
528 
529 /* String handling utilities */
530 
531 int tickit_utf8_seqlen(long codepoint);
532 
533 /* Does NOT NUL-terminate the buffer */
534 size_t tickit_utf8_put(char *str, size_t len, long codepoint);
535 
536 size_t tickit_utf8_count(const char *str, TickitStringPos *pos, const TickitStringPos *limit);
537 size_t tickit_utf8_countmore(const char *str, TickitStringPos *pos, const TickitStringPos *limit);
538 size_t tickit_utf8_ncount(const char *str, size_t len, TickitStringPos *pos, const TickitStringPos *limit);
539 size_t tickit_utf8_ncountmore(const char *str, size_t len, TickitStringPos *pos, const TickitStringPos *limit);
540 
541 // Some convenient mutators for TickitStringPos structs
542 
tickit_stringpos_zero(TickitStringPos * pos)543 static inline void tickit_stringpos_zero(TickitStringPos *pos) {
544   pos->bytes = pos->codepoints = pos->graphemes = pos->columns = 0;
545 }
546 
547 #define INIT_TICKIT_STRINGPOS_LIMIT_NONE { .bytes = -1, .codepoints = -1, .graphemes = -1, .columns = -1 }
tickit_stringpos_limit_none(TickitStringPos * pos)548 static inline void tickit_stringpos_limit_none(TickitStringPos *pos)
549 {
550   pos->bytes = pos->codepoints = pos->graphemes = pos->columns = -1;
551 }
552 
553 #define INIT_TICKIT_STRINGPOS_LIMIT_BYTES(v) { .bytes = (v), .codepoints = -1, .graphemes = -1, .columns = -1 }
tickit_stringpos_limit_bytes(TickitStringPos * pos,size_t bytes)554 static inline void tickit_stringpos_limit_bytes(TickitStringPos *pos, size_t bytes) {
555   pos->codepoints = pos->graphemes = pos->columns = -1;
556   pos->bytes = bytes;
557 }
558 
559 #define INIT_TICKIT_STRINGPOS_LIMIT_CODEPOINTS(v) { .bytes = -1, .codepoints = (v), .graphemes = -1, .columns = -1 }
tickit_stringpos_limit_codepoints(TickitStringPos * pos,int codepoints)560 static inline void tickit_stringpos_limit_codepoints(TickitStringPos *pos, int codepoints) {
561   pos->bytes = pos->graphemes = pos->columns = -1;
562   pos->codepoints = codepoints;
563 }
564 
565 #define INIT_TICKIT_STRINGPOS_LIMIT_GRAPHEMES(v) { .bytes = -1, .codepoints = -1, .graphemes = (v), .columns = -1 }
tickit_stringpos_limit_graphemes(TickitStringPos * pos,int graphemes)566 static inline void tickit_stringpos_limit_graphemes(TickitStringPos *pos, int graphemes) {
567   pos->bytes = pos->codepoints = pos->columns = -1;
568   pos->graphemes = graphemes;
569 }
570 
571 #define INIT_TICKIT_STRINGPOS_LIMIT_COLUMNS(v) { .bytes = -1, .codepoints = -1, .graphemes = -1, .columns = (v) }
tickit_stringpos_limit_columns(TickitStringPos * pos,int columns)572 static inline void tickit_stringpos_limit_columns(TickitStringPos *pos, int columns) {
573   pos->bytes = pos->codepoints = pos->graphemes = -1;
574   pos->columns = columns;
575 }
576 
577 int    tickit_utf8_mbswidth(const char *str);
578 int    tickit_utf8_byte2col(const char *str, size_t byte);
579 size_t tickit_utf8_col2byte(const char *str, int col);
580 
581 /* TickitRenderBuffer */
582 
583 TickitRenderBuffer *tickit_renderbuffer_new(int lines, int cols);
584 void tickit_renderbuffer_destroy(TickitRenderBuffer *rb);
585 
586 TickitRenderBuffer *tickit_renderbuffer_ref(TickitRenderBuffer *rb);
587 void                tickit_renderbuffer_unref(TickitRenderBuffer *rb);
588 
589 void tickit_renderbuffer_get_size(const TickitRenderBuffer *rb, int *lines, int *cols);
590 
591 void tickit_renderbuffer_translate(TickitRenderBuffer *rb, int downward, int rightward);
592 void tickit_renderbuffer_clip(TickitRenderBuffer *rb, TickitRect *rect);
593 void tickit_renderbuffer_mask(TickitRenderBuffer *rb, TickitRect *mask);
594 
595 bool tickit_renderbuffer_has_cursorpos(const TickitRenderBuffer *rb);
596 void tickit_renderbuffer_get_cursorpos(const TickitRenderBuffer *rb, int *line, int *col);
597 void tickit_renderbuffer_goto(TickitRenderBuffer *rb, int line, int col);
598 void tickit_renderbuffer_ungoto(TickitRenderBuffer *rb);
599 
600 void tickit_renderbuffer_setpen(TickitRenderBuffer *rb, const TickitPen *pen);
601 
602 void tickit_renderbuffer_reset(TickitRenderBuffer *rb);
603 
604 void tickit_renderbuffer_save(TickitRenderBuffer *rb);
605 void tickit_renderbuffer_savepen(TickitRenderBuffer *rb);
606 void tickit_renderbuffer_restore(TickitRenderBuffer *rb);
607 
608 void tickit_renderbuffer_skip_at(TickitRenderBuffer *rb, int line, int col, int cols);
609 void tickit_renderbuffer_skip(TickitRenderBuffer *rb, int cols);
610 void tickit_renderbuffer_skip_to(TickitRenderBuffer *rb, int col);
611 void tickit_renderbuffer_skiprect(TickitRenderBuffer *rb, TickitRect *rect);
612 int tickit_renderbuffer_text_at(TickitRenderBuffer *rb, int line, int col, const char *text);
613 int tickit_renderbuffer_textn_at(TickitRenderBuffer *rb, int line, int col, const char *text, size_t len);
614 int tickit_renderbuffer_text(TickitRenderBuffer *rb, const char *text);
615 int tickit_renderbuffer_textn(TickitRenderBuffer *rb, const char *text, size_t len);
616 int tickit_renderbuffer_textf_at(TickitRenderBuffer *rb, int line, int col, const char *fmt, ...);
617 int tickit_renderbuffer_vtextf_at(TickitRenderBuffer *rb, int line, int col, const char *fmt, va_list args);
618 int tickit_renderbuffer_textf(TickitRenderBuffer *rb, const char *fmt, ...);
619 int tickit_renderbuffer_vtextf(TickitRenderBuffer *rb, const char *fmt, va_list args);
620 void tickit_renderbuffer_erase_at(TickitRenderBuffer *rb, int line, int col, int cols);
621 void tickit_renderbuffer_erase(TickitRenderBuffer *rb, int cols);
622 void tickit_renderbuffer_erase_to(TickitRenderBuffer *rb, int col);
623 void tickit_renderbuffer_eraserect(TickitRenderBuffer *rb, TickitRect *rect);
624 void tickit_renderbuffer_clear(TickitRenderBuffer *rb);
625 void tickit_renderbuffer_char_at(TickitRenderBuffer *rb, int line, int col, long codepoint);
626 void tickit_renderbuffer_char(TickitRenderBuffer *rb, long codepoint);
627 
628 void tickit_renderbuffer_hline_at(TickitRenderBuffer *rb, int line, int startcol, int endcol,
629     TickitLineStyle style, TickitLineCaps caps);
630 void tickit_renderbuffer_vline_at(TickitRenderBuffer *rb, int startline, int endline, int col,
631     TickitLineStyle style, TickitLineCaps caps);
632 
633 void tickit_renderbuffer_copyrect(TickitRenderBuffer *rb, const TickitRect *dest, const TickitRect *src);
634 void tickit_renderbuffer_moverect(TickitRenderBuffer *rb, const TickitRect *dest, const TickitRect *src);
635 
636 void tickit_renderbuffer_flush_to_term(TickitRenderBuffer *rb, TickitTerm *tt);
637 
638 void tickit_renderbuffer_blit(TickitRenderBuffer *dst, const TickitRenderBuffer *src);
639 
640 // This API is still somewhat experimental
641 
642 typedef struct {
643   char north;
644   char south;
645   char east;
646   char west;
647 } TickitRenderBufferLineMask;
648 
649 int tickit_renderbuffer_get_cell_active(TickitRenderBuffer *rb, int line, int col);
650 size_t tickit_renderbuffer_get_cell_text(TickitRenderBuffer *rb, int line, int col, char *buffer, size_t len);
651 TickitRenderBufferLineMask tickit_renderbuffer_get_cell_linemask(TickitRenderBuffer *rb, int line, int col);
652 
653 // returns a direct pointer - do not free or modify
654 TickitPen *tickit_renderbuffer_get_cell_pen(TickitRenderBuffer *rb, int line, int col);
655 
656 struct TickitRenderBufferSpanInfo {
657   bool is_active;
658   int n_columns;
659   char *text;
660   size_t len;
661   TickitPen *pen;
662 };
663 
664 // returns the text length or -1 on error
665 size_t tickit_renderbuffer_get_span(TickitRenderBuffer *rb, int line, int startcol, struct TickitRenderBufferSpanInfo *info, char *buffer, size_t len);
666 
667 /* Window */
668 
669 TickitWindow *tickit_window_new_root(TickitTerm *term);
670 TickitWindow *tickit_window_new(TickitWindow *parent, TickitRect rect, TickitWindowFlags flags);
671 
672 TickitWindow *tickit_window_parent(const TickitWindow *win);
673 TickitWindow *tickit_window_root(const TickitWindow *win);
674 
675 size_t tickit_window_children(const TickitWindow *win);
676 size_t tickit_window_get_children(const TickitWindow *win, TickitWindow *children[], size_t n);
677 
678 TickitTerm *tickit_window_get_term(const TickitWindow *win);
679 
680 void tickit_window_close(TickitWindow *win);
681 
682 void tickit_window_destroy(TickitWindow *win);
683 
684 TickitWindow *tickit_window_ref(TickitWindow *win);
685 void          tickit_window_unref(TickitWindow *win);
686 
687 typedef int TickitWindowEventFn(TickitWindow *win, TickitEventFlags flags, void *info, void *user);
688 
689 typedef enum {
690   TICKIT_WINDOW_ON_DESTROY,
691   TICKIT_WINDOW_ON_GEOMCHANGE,
692   TICKIT_WINDOW_ON_EXPOSE,
693   TICKIT_WINDOW_ON_FOCUS,
694   TICKIT_WINDOW_ON_KEY,
695   TICKIT_WINDOW_ON_MOUSE,
696 } TickitWindowEvent;
697 
698 int  tickit_window_bind_event(TickitWindow *win, TickitWindowEvent ev, TickitBindFlags flags,
699     TickitWindowEventFn *fn, void *user);
700 void tickit_window_unbind_event_id(TickitWindow *win, int id);
701 
702 void tickit_window_raise(TickitWindow *win);
703 void tickit_window_raise_to_front(TickitWindow *win);
704 void tickit_window_lower(TickitWindow *win);
705 void tickit_window_lower_to_back(TickitWindow *win);
706 
707 void tickit_window_show(TickitWindow *win);
708 void tickit_window_hide(TickitWindow *win);
709 bool tickit_window_is_visible(TickitWindow *win);
710 
711 TickitRect tickit_window_get_geometry(const TickitWindow *win);
712 TickitRect tickit_window_get_abs_geometry(const TickitWindow *win);
713 
714 #define tickit_window_top(win)   (tickit_window_get_geometry(win)).top
715 #define tickit_window_left(win)  (tickit_window_get_geometry(win)).left
716 #define tickit_window_lines(win) (tickit_window_get_geometry(win)).lines
717 #define tickit_window_cols(win)  (tickit_window_get_geometry(win)).cols
718 
719 int tickit_window_bottom(const TickitWindow *win);
720 int tickit_window_right(const TickitWindow *win);
721 
722 void tickit_window_resize(TickitWindow *win, int lines, int cols);
723 void tickit_window_reposition(TickitWindow *win, int top, int left);
724 void tickit_window_set_geometry(TickitWindow *win, TickitRect rect);
725 
726 TickitPen *tickit_window_get_pen(const TickitWindow *win);
727 void tickit_window_set_pen(TickitWindow *win, TickitPen *pen);
728 void tickit_window_expose(TickitWindow *win, const TickitRect *exposed);
729 void tickit_window_flush(TickitWindow *win);
730 
731 bool tickit_window_scrollrect(TickitWindow *win, const TickitRect *rect, int downward, int rightward, TickitPen *pen);
732 bool tickit_window_scroll(TickitWindow *win, int downward, int rightward);
733 bool tickit_window_scroll_with_children(TickitWindow *win, int downward, int rightward);
734 
735 void tickit_window_set_cursor_position(TickitWindow *win, int line, int col);
736 void tickit_window_set_cursor_visible(TickitWindow *win, bool visible);
737 void tickit_window_set_cursor_shape(TickitWindow *win, TickitCursorShape shape);
738 
739 void tickit_window_take_focus(TickitWindow *win);
740 bool tickit_window_is_focused(const TickitWindow *win);
741 void tickit_window_set_focus_child_notify(TickitWindow *win, bool notify);
742 
743 bool tickit_window_getctl_int(TickitWindow *win, TickitWindowCtl ctl, int *value);
744 bool tickit_window_setctl_int(TickitWindow *win, TickitWindowCtl ctl, int value);
745 
746 bool tickit_window_is_steal_input(const TickitWindow *win);
747 void tickit_window_set_steal_input(TickitWindow *win, bool steal);
748 
749 const char *tickit_window_ctlname(TickitWindowCtl ctl);
750 TickitWindowCtl tickit_window_lookup_ctl(const char *name);
751 
752 TickitType tickit_window_ctltype(TickitWindowCtl ctl);
753 
754 /* Main object */
755 
756 typedef int TickitCallbackFn(Tickit *t, TickitEventFlags flags, void *info, void *user);
757 
758 Tickit *tickit_new_for_term(TickitTerm *tt);
759 Tickit *tickit_new_stdio(void);
760 Tickit *tickit_new_stdtty(void);
761 
762 Tickit *tickit_ref(Tickit *t);
763 void    tickit_unref(Tickit *t);
764 
765 struct TickitBuilder {
766   TickitTerm *tt;
767   struct TickitTermBuilder term_builder; /* used if tt == NULL */
768 
769   /* Fields below here are undocumented and for vaguely internal or
770    * special-case purposes
771    */
772   const TickitEventHooks *evhooks;
773   void *evinitdata;
774 };
775 Tickit *tickit_build(const struct TickitBuilder *builder);
776 
777 TickitTerm *tickit_get_term(Tickit *t);
778 
779 TickitWindow *tickit_get_rootwin(Tickit *t);
780 
781 void tickit_run(Tickit *t);
782 void tickit_stop(Tickit *t);
783 
784 void tickit_tick(Tickit *t, TickitRunFlags flags);
785 
786 bool tickit_getctl_int(Tickit *tt, TickitCtl ctl, int *value);
787 bool tickit_setctl_int(Tickit *tt, TickitCtl ctl, int value);
788 
789 const char *tickit_ctlname(TickitCtl ctl);
790 TickitCtl tickit_lookup_ctl(const char *name);
791 
792 TickitType tickit_ctltype(TickitCtl ctl);
793 
794 void *tickit_watch_io(Tickit *t, int fd, TickitIOCondition cond, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
795 
796 /* Discouraged synonyn for tickit_watch_io cond=TICKIT_IO_IN|TICKIT_IO_HUP */
797 void *tickit_watch_io_read(Tickit *t, int fd, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
798 
799 void *tickit_watch_timer_after_msec(Tickit *t, int msec, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
800 void *tickit_watch_timer_after_tv(Tickit *t, const struct timeval *after, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
801 
802 void *tickit_watch_timer_at_epoch(Tickit *t, time_t at, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
803 void *tickit_watch_timer_at_tv(Tickit *t, const struct timeval *at, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
804 
805 void *tickit_watch_later(Tickit *t, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
806 
807 void *tickit_watch_signal(Tickit *t, int signum, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
808 
809 void *tickit_watch_process(Tickit *t, pid_t pid, TickitBindFlags flags, TickitCallbackFn *fn, void *user);
810 
811 void tickit_watch_cancel(Tickit *t, void *watch);
812 
813 /* Debug support */
814 
815 void tickit_debug_init(void);
816 
817 extern bool tickit_debug_enabled;
818 
819 void tickit_debug_logf(const char *flag, const char *fmt, ...);
820 void tickit_debug_vlogf(const char *flag, const char *fmt, va_list args);
821 
822 void tickit_debug_set_func(void (*func)(const char *str, void *data), void *data);
823 void tickit_debug_set_fh(FILE *fh);
824 bool tickit_debug_open(const char *path);
825 
826 #endif
827 
828 #ifdef __cplusplus
829 }
830 #endif
831