1 /*
2  Arcan Text-Oriented User Interface Library
3 
4  Copyright (c) 2014-2019, Bjorn Stahl
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms,
8  with or without modification, are permitted provided that the
9  following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice,
12  this list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright notice,
15  this list of conditions and the following disclaimer in the documentation
16  and/or other materials provided with the distribution.
17 
18  3. Neither the name of the copyright holder nor the names of its contributors
19  may be used to endorse or promote products derived from this software without
20  specific prior written permission.
21 
22  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #ifndef HAVE_ARCAN_TUI
36 #define HAVE_ARCAN_TUI
37 
38 /*
39  * [ABOUT]
40  *  This is a library intended to allow the development of rich text-oriented
41  *  user interfaces that are free from the legacy- cruft of terminal emulation
42  *  protocols, offering better system integration, lower latency, faster drawing
43  *  and access to more features, and to take advantage of existing display
44  *  servers and window managers. It is not intended to provide normal toolkit
45  *  like components as such, only access to subsystems like input, drawing
46  *  and storage- with a bias towards text output and keyboard input.
47  *
48  * [PORTABILITY]
49  *  In order to allow custom backends that use other IPC and drawing systems to
50  *  avoid a lock-in or dependency on Arcan, there is a separate arcan_tuidefs.h
51  *  as an intermediate step in order to be able to move away from the shmif-
52  *  dependency entirely. It contains the type mapping of all opaque- structures
53  *  provided herein and should help when writing another backend. The biggest
54  *  caveat is likely custom drawing into cells as it binds the color-space to
55  *  sRGB and the packing format to a macro.
56  *
57  * [STABILITY]
58  *  The majority of the interface exposed here in terms of enumerations and
59  *  types is mostly safe against breaking changes. To be extra careful, wait
60  *  until a mirror- repo @github.com/letoram/arcan-tui.git has been set up
61  *  and all the fields updated.
62  *
63  * [THREAD SAFETY]
64  *  The main allocation, initial setup routines are currently not safe for
65  *  multithreaded use and there might be some state bleed between text
66  *  rendering. Each individual context, however, should ultimately work both in
67  *  multithreaded- and multiprocess- (though other systems such as libc memory
68  *  allocation may not be) use.
69  *
70  * [LICENSING / ACKNOWLEDGEMENTS]
71  *  The default implementation is built on a forked version of libTSM
72  *  (c) David Herrmann, which pulls in dependencies that make the final
73  *  output LGPL2.1+. The intent of the library and API itself is to be BSD
74  *  licensed.
75  *
76  * [ONTOLOGY]
77  *  Cell   - Smallest drawable unit, contains a UNCODE codepoint and
78  *           formatting attributes.
79  *
80  *  Glyph  - Character from a font which is mapped to the codepoint
81  *           of a cell in order to transform it to something visible
82  *           (drawing or 'blitting')
83  *
84  *  Screen - Buffer of cols*rows of cells.
85  *
86  *  Line   - Refers to a single sequence of columns.
87  *
88  *  Main Screen - A screen tied to the livespan of the TUI conncetion
89  *
90  *  [Sub] - Window - Additional screens with a dependency/relationship to
91  *                   the main screen. Allocated asynchronously and can be
92  *                   rejected. Use sparringly and with the assumption that
93  *                   an allocation is likely to fail.
94  *
95  *  Drawing command that operate on a screen also works for a window.
96  *
97  * [USE]
98  *  Display-server/backend specific connection setup/wrapper that
99  *  provides the opaque arcan_tui_conn structure. All symbols and flag
100  *  values are kept separately in arcan_tuisym.h
101  *
102  *  struct tui_cbcfg cb {
103  *     SET EVENT-HANDLERS HERE (e.g. input_key, tick, geohint, ...)
104  *  };
105  *
106  *  arcan_tui_conn* conn = arcan_tui_open_display("mytitle", "myident");
107  *  struct tui_context* ctx = arcan_tui_setup(conn, NULL, cb, sizeof(cb));
108  *
109  *  normal processing loop:
110  *   (use fdset/fdset_sz and timeout for poll-like behavior)
111  *
112  *  while (running){
113  *  	struct tui_process_res res =
114  *  		arcan_tui_process(&ctx, 1, NULL, 0, -1);
115  *  	if (res.errc == 0){
116  *
117  *  	}
118  *
119  *  UPDATED/TIME TO DRAW?
120  *  	if (-1 == arcan_tui_refresh(ctx) && errno == EINVAL)
121  *  		break;
122  * }
123  *
124  * [ADVANCED EXAMPLES]
125  *  See the builtin widgets (arcan_tui_bufferwnd, arcan_tui_listwnd)
126  *
127  * subwindows:
128  * (in subwnd handler from cbs)
129  *  struct tui_context* con = arcan_tui_setup(conn, parent, cb, sizeof(cb));
130  *  arcan_tui_wndhint(con, ...);
131  *
132  * Normal use/drawing functions (all prefixed with arcan_tui_):
133  *  erase_screen(ctx, prot)
134  *  erase_region(ctx, x1, y1, x2, y2, prot)
135  *  eraseattr_region(ctx, x1, y1, x2, y2, prot, attr)
136  *  eraseattr_screen(ctx, prot, attr)
137  *  erase_cursor_to_screen(ctx, prot)
138  *  erase_home_to_cursor(ctx, prot)
139  *  erase_current_line(ctgx)
140  *  erase_chars(ctx, n)
141  *  write(ucs4, attr)
142  *  writeu8(uint8_t* u8, size_t n, attr)
143  *  insert_lines(ctx, n)
144  *  newline(ctx)
145  *  delete_lines(ctx, n)
146  *  insert_chars(ctx, n)
147  *  delete_chars(ctx, n)
148  *  set_tabstop(ctx)
149  *  reset_tabstop(ctx)
150  *  reset_all_tabstops(ctx)
151  *
152  * Virtual Screen management:
153  *  scroll_up(ctx, n)
154  *  scroll_down(ctx, n)
155  *  set_margins(ctx, top, bottom)
156  *  dimensions(ctx, size_t* rows, size_t* cols)
157  *  request_subwnd(ctx, id, type)
158  *
159  * Cursor Management:
160  *  cursorpos(ctx, size_t* x, size_t* y)
161  *  tab_right(ctx, n)
162  *  tab_left(ctx, n)
163  *  move_to(ctx, x, y)
164  *  move_up(ctx, num, scroll)
165  *  move_down(ctx, num, scroll)
166  *  move_left(ctx, num)
167  *  move_right(ctx, num)
168  *  move_line_end(ctx)
169  *  move_line_home(ctx)
170  *
171  * Metadata:
172  *  copy(ctx, msg)
173  *  ident(ctx, ident)
174  *
175  * Context Management:
176  *  reset(ctx)
177  *  set_flags(ctx, flags)
178  *  reset_flags(ctx, flags)
179  *  defattr(ctx, attr)
180  *
181  * Dynamic Loading:
182  *
183  * For the cases where you want dynamic loading of the TUI functions,
184  * define ARCAN_TUI_DYNAMIC before including the header file and the
185  * normal external function entry points will be replaced with same-
186  * name static scoped function pointers. In order to initialize them,
187  * run the arcan_tui_dynload in the same compilation unit with a
188  * loader function provided as a function pointer argument.
189  *
190  * [DEPRECATION/REFACTORING]
191  *  [ ] Remove TSM
192  *  [ ] Implement line- mode as a widget and remove all scrollback/
193  *      wrapping control functions from the arcan_tui_xxx namespace
194  */
195 
196 #include "arcan_tuidefs.h"
197 #include "arcan_tuisym.h"
198 
199 struct tui_context;
200 
201 struct tui_constraints {
202 	int anch_row, anch_col;
203 	int max_rows, max_cols;
204 	int min_rows, min_cols;
205 };
206 
207 struct tui_screen_attr {
208 	union {
209 		uint8_t fc[3];
210 		struct {
211 			uint8_t fr;
212 			uint8_t fg;
213 			uint8_t fb;
214 		};
215 	};
216 	union {
217 		uint8_t bc[3];
218 		struct {
219 			uint8_t br; /* background red */
220 			uint8_t bg; /* background green */
221 			uint8_t bb; /* background blue */
222 		};
223 	};
224 
225 /* bitmask from TUI_ATTR_ */
226 	uint16_t aflags;
227 	uint8_t custom_id;
228 };
229 
230 /* _Static_assert(sizeof(tui_screen_attr) == 8) */
231 
tui_attr_equal(struct tui_screen_attr a,struct tui_screen_attr b)232 static inline bool tui_attr_equal(
233 	struct tui_screen_attr a, struct tui_screen_attr b)
234 {
235 	return (
236 		a.fr == b.fr &&
237 		a.fg == b.fg &&
238 		a.fb == b.fb &&
239 		a.br == b.br &&
240 		a.bg == b.bg &&
241 		a.bb == b.bb &&
242 		a.aflags == b.aflags &&
243 		a.custom_id == b.custom_id
244 	);
245 }
246 
247 struct tui_cell {
248 /* drawing properties */
249 	struct tui_screen_attr attr;
250 
251 /* used for substitutions */
252 	uint32_t ch, draw_ch;
253 
254 /* resolved after shaping has been applied */
255 	uint32_t real_x;
256 	uint8_t cell_w;
257 
258 /* cycling counter for when the cell was last updated */
259 	uint8_t fstamp;
260 };
261 
262 /*
263  * used with the 'query_label' callback.
264  */
265 struct tui_labelent {
266 /* 7-bit ascii reference string */
267 	char label[16];
268 
269 /* user-readable short description */
270 	char descr[58];
271 
272 /* utf8 icon or short identifier */
273 	uint8_t vsym[5];
274 
275 /* button : 0
276  * axis-motion : 1
277  * touch : 2 */
278 	uint8_t idatatype;
279 
280 /* match enum tuik_syms in _tuisyms.h */
281 	uint16_t initial;
282 /*optional alias- for label */
283 	uint16_t subv;
284 /* modifier-mask, from _tuisyms.h */
285 	uint16_t modifiers;
286 };
287 
288 /*
289  * fill in the events you want to handle, will be dispatched during process
290  */
291 struct tui_cbcfg {
292 /*
293  * appended last to any invoked callback
294  */
295 	void* tag;
296 
297 /*
298  * Called when the label-list has been invalidated and during setup.  [ind]
299  * indicates the requested label index. This will be sweeped from low (0) and
300  * incremented until query_label() returns false.
301  *
302  * A new sweep may be initiated on a new GEOHINT or a state reset.
303  *
304  * [lang] and [country] are either set to the last known GEOHINT
305  * or [NULL] to indicate some default unspecified english.
306  *
307  * [dstlbl] should be filled out according to the labelent structure and the
308  * function should return TRUE if there is a label at the requested index - or
309  * FALSE if there are no more labels to register.
310  */
311 	bool (*query_label)(struct tui_context*,
312 		size_t ind, const char* country, const char* lang,
313 		struct tui_labelent* dstlbl, void*);
314 
315 /*
316  * An explicit label- input has been sent,
317  *
318  * [label] is a string identifier that may correspond to an
319  *         exposed label from previous calls to query_label().
320  * [active] indicates that the unspecified source input device
321  *          has transitioned from an inactive to an active state
322  *          (rasing) or from a previously active to an inactive
323  *          state (falling).
324  *
325  * return TRUE if the label was consumed, FALSE if the label
326  * should be treated by a (possible) internal/masked implementation.
327  */
328 	bool (*input_label)(struct tui_context*,
329 		const char* label, bool active, void*);
330 
331 /*
332  * an explicit analog- label input has been sent,
333  * [n] number of samples in [smpls]
334  * [rel] set if relative some previous or device/datatype specific pos
335  * [datatype] see shmif_event.h, to get type
336  */
337 	bool (*input_alabel)(struct tui_context*,
338 		const char* label, const int16_t* smpls,
339 		size_t n, bool rel, uint8_t datatype, void*
340 	);
341 
342 /*
343  * Mouse motion has occured within the context. [x] and [y] indicate
344  * the current CELL (x -> col, y -> row). Will only happen if mouse
345  * events are set to be forwarded by some TUI implementation specific
346  * means.
347  */
348 	void (*input_mouse_motion)(struct tui_context*,
349 		bool relative, int x, int y, int modifiers, void*);
350 
351 /*
352  * Mouse button state has changed for some button index.
353  */
354 	void (*input_mouse_button)(struct tui_context*,
355 		int last_x, int last_y, int button, bool active, int modifiers, void*);
356 
357 /*
358  * single UTF8- character
359  */
360 	bool (*input_utf8)(struct tui_context*, const char* u8, size_t len, void*);
361 
362 /*
363  * Other KEY where we are uncertain about origin, filled on a best-effort
364  * (should be last-line of defence after label->utf8|sym->mouse->[key].
365  *
366  * [keysym] matches a value from the table in arcan_tuisym.h (TUIK prefix)
367  * :Ex
368  */
369 	void (*input_key)(struct tui_context*, uint32_t symest,
370 		uint8_t scancode, uint8_t mods, uint16_t subid, void* tag);
371 
372 /*
373  * other input- that wasn't handled in the other callbacks
374  */
375 	void (*input_misc)(struct tui_context*, const arcan_ioevent*, void*);
376 
377 /*
378  * state transfer, [input=true] if we should receive a state-block that was
379  * previously saved or [input=false] if we should store. dup+thread+write or
380  * write to use or ignore (closed after call)
381  */
382 	void (*state)(struct tui_context*, bool input, int fd, void*);
383 
384 /*
385  * request to send [input=false] or receive a binary chunk, [input=true,size=0] for streams
386  * of unknown size, [input=false] then size is 'recommended' upper limit, if set.
387  * handler takes ownership of [fd] and should close() it when done. [fd] will
388  * be opened in non-blocking mode.
389  */
390 	void (*bchunk)(
391 		struct tui_context*, bool input, uint64_t size, int fd, const char* type, void*);
392 
393 /*
394  * one video frame has been pasted, accessible during call lifespan
395  */
396 	void (*vpaste)(struct tui_context*,
397 		shmif_pixel*, size_t w, size_t h, size_t stride, void*);
398 
399 /*
400  * paste-action, audio stream block [channels interleaved]
401  */
402 	void (*apaste)(struct tui_context*,
403 		shmif_asample*, size_t n_samples, size_t frequency, size_t nch, void*);
404 
405 /*
406  * periodic parent-driven clock
407  */
408 	void (*tick)(struct tui_context*, void*);
409 
410 /*
411  * pasted a block of text, continuous flag notes if there are more to come
412  */
413 	void (*utf8)(struct tui_context*,
414 		const uint8_t* str, size_t len, bool cont, void*);
415 
416 /*
417  * The underlying size has changed. Note that this also sends the height in
418  * pixels via [neww, newh]. This should have very few practical usecases as all
419  * other positioning operations etc. are on a cell- level. If the pixel
420  * resolution is not known, [neww, newh] can be set to zero.
421  *
422  * WARNING:
423  *  Be careful not to process, refresh or other similar actions from the
424  *  context of this or the 'resize' callback.
425  */
426 	void (*resized)(struct tui_context*,
427 		size_t neww, size_t newh, size_t cols, size_t rows, void*);
428 
429 /*
430  * only reset levels that should require action on behalf of the caller are
431  * being forwarded, this covers levels >= 1.
432  */
433 	void (*reset)(struct tui_context*, int level, void*);
434 
435 /*
436  * comparable to a locale switch (which the backend obviously cannot perform
437  * without introducing subtle bugs like . -> , without the caller knowing,
438  * but with more detail.
439  *
440  * check ISO-3166-1 for a3_country, ISO-639-2 for a3_language
441  */
442 	void (*geohint)(struct tui_context*, float lat, float longitude, float elev,
443 		const char* a3_country, const char* a3_language, void*);
444 
445 /*
446  * this may be invoked for two reasons, one is that the contents for some
447  * reason are invalid (widgets that draw cooperatively being one example).
448  *
449  * The other is that the color-mapping for the window has changed. Both
450  * scenarios warrant that the client fully redraws the contents of the window
451  * (the underlying window implementation will make sure that only cells that
452  * have legitimately changed will actually be redrawn.
453  */
454 	void (*recolor)(struct tui_context*, void*);
455 
456 /*
457  * A new subwindow has arrived or the request has failed (=NULL). This should
458  * either be bound to a new tui context via the arcan_tui_setup() call using
459  * the provided connection argument here and return true, OR don't touch it
460  * and return false.
461  *
462  * To map the special type 'TUI_WND_HANDOVER', the tui_handover_setup call
463  * should be used on the connection argument within the scope of the callback
464  * after which the client has no direct control over how the window behaves.
465  *
466  * WARNING: mapping the connection via arcan_tui_setup and returning FALSE
467  * may cause use-after-free or other memory corruption issues.
468  */
469 	bool (*subwindow)(struct tui_context*,
470 		arcan_tui_conn* connection, uint32_t id, uint8_t type, void*);
471 
472 /*
473  * Dynamic glyph substitution callback per updated row. This allows you to
474  * change cell attributes pre-rendering, particularly for the purpose of
475  * indicating/updating shaping-breaks so that, if the renderer is operating
476  * in a shaped mode, can realign appropriately - but also to perform custom/
477  * manual glyph substitutions or disable the default- shaper/substituter.
478  *
479  * return true if the contents of the cells were modified, false otherwise.
480  *
481  * For more advanced shaping that depend on the font and font properties
482  * used, leave the callback to its default callback table state or forward-
483  * chain to the default callback state from here (though check if it is set).
484  */
485 	bool (*substitute)(struct tui_context*,
486 		struct tui_cell* cells, size_t n_cells, size_t row, void* t);
487 
488 /*
489  * The underlying size is about to change, expressed in both pixels and
490  * rows/columns. If the pixel dimensions aren't known, [neww, newh] will
491  * be set to 0.
492  */
493 	void (*resize)(struct tui_context*,
494 		size_t neww, size_t newh, size_t cols, size_t rows, void*);
495 
496 /*
497  * Window visibility and input focus state has changed
498  */
499 	void (*visibility)(struct tui_context*, bool visible, bool focus, void*);
500 
501 /*
502  * Context has changed liveness state
503  * 0 : normal operation
504  * 1 : suspend state, execution should be suspended, next event will
505  *     exec_state into normal or terminal state
506  * 2 : terminal state, context is dead
507  */
508 	void (*exec_state)(struct tui_context*, int state, void*);
509 
510 /*
511  * This is intended for completion style command-line integration, mainly as a
512  * building block for a 'libreadline' replacement widget but hopefully also for
513  * cooperative 'int main(argv..)' style command line evaluation as part of
514  * building new shells with runtime feedback.
515  *
516  * [argv] is a NULL terminated array of the on-going / current set of arguments.
517  *
518  * Command MUST be one out of:
519  * TUI_CLI_BEGIN,
520  * TUI_CLI_EVAL,
521  * TUI_CLI_COMMIT,
522  * TUI_CLI_CANCEL
523  *
524  * The return value MUST be one out of:
525  * TUI_CLI_ACCEPT,
526  * TUI_CLI_SUGGEST,
527  * TUI_CLI_REPLACE,
528  * TUI_CLI_INVALID
529  *
530  * The callee retains ownership of feedback results, but the results should
531  * remain valid until the next EVAL, COMMIT or CANCEL.
532  *
533  * A response to EVAL may be ACCEPT if the command is acceptible as is, or
534  * SUGGEST if there is a set of possible completion options that expand on
535  * the current stack or REPLACE if there is a single commit chain that can
536  * replace the stack.
537  *
538  * If the response is to SUGGEST, the FIRST feedback item refers to the
539  * last item in argv, set that to an empty string. The remaining feedback
540  * items refer to possible additional items to [argv].
541  */
542 	int (*cli_command)(struct tui_context*,
543 		const char** const argv, size_t n_elem, int command,
544 		const char** feedback, size_t* n_results
545 	);
546 
547 /*
548  * This is normally mapped to 'scrolling' - changing content starting offset
549  * in order to slide the visible subset when there is more content than can
550  * be presented than there is space in the window.
551  *
552  * The absolute form only covers the upper left corner 'start' and is in the
553  * 0..1 range where 0 indicates the start of all contents and 1 means the 'end
554  * of contents'.
555  *
556  * The relative form allows stepping both vertically and horizontally (where
557  * applicable) and is relative to the current window base. Horizontal scrolling
558  * should be avoided in favor of reflowing wherever possible.
559  *
560  * In order to indicate support, use arcan_tui_content_size to provide rough
561  * estimates on the current size. This needs to be updated in response to
562  * certain events and actions, such as after the window has changed size or
563  * updated its set of handlers.
564  */
565 	void (*seek_absolute)(struct tui_context*, float pct, void*);
566 	void (*seek_relative)(struct tui_context*, ssize_t rows, ssize_t cols, void*);
567 
568 /*
569  * Add new callbacks here as needed, since the setup requires a sizeof of
570  * this struct as an argument, we get some light indirect versioning
571  */
572 };
573 
574 enum tui_process_errc {
575 	TUI_ERRC_OK = 0,
576 	TUI_ERRC_BAD_ARG = -1,
577 	TUI_ERRC_BAD_FD = -2,
578 	TUI_ERRC_BAD_CTX = -3,
579 };
580 
581 struct tui_region {
582 	int dx, dy;
583 	size_t x, y;
584 	size_t w, h;
585 };
586 
587 struct tui_process_res {
588 	uint32_t ok;
589 	uint32_t bad;
590 	int errc;
591 };
592 
593 enum tui_subwnd_hint {
594 	TUIWND_SPLIT_NONE = 0,
595 	TUIWND_SPLIT_LEFT = 1,
596 	TUIWND_SPLIT_RIGHT = 2,
597 	TUIWND_SPLIT_TOP = 3,
598 	TUIWND_SPLIT_BOTTOM = 4,
599 	TUIWND_JOIN_LEFT = 5,
600 	TUIWND_JOIN_RIGHT = 6,
601 	TUIWND_JOIN_TOP = 7,
602 	TUIWND_JOIN_DOWN = 8,
603 	TUIWND_TAB = 9
604 };
605 
606 struct tui_subwnd_req {
607 	int dir;
608 	size_t rows;
609 	size_t columns;
610 	enum tui_subwnd_hint hint;
611 };
612 
613 #ifndef ARCAN_TUI_DYNAMIC
614 
615 /*
616  * Build a tui context based on the properties from the optional connection
617  * [con] or a reference parent [parent], and bind it with the handler table
618  * defined in [cfg], passing the sizeof(struct tui_cbcfg) along with it.
619  *
620  * If [con] is not provided, the context will be used as a displayless-
621  * store, no input events are provided or processed, refresh calls and so
622  * on will not trigger, but it can be used to draw into.
623  *
624  * In such cases, a [con] from either a subwindow event handler or a new
625  * _open_display can adopt a context by calling [arcan_tui_bind].
626  */
627 struct tui_context* arcan_tui_setup(
628 	arcan_tui_conn* con, struct tui_context* parent,
629 	const struct tui_cbcfg* cfg,
630 	size_t cfg_sz, ...
631 );
632 
633 /*
634  * Take a previously created context and bind it to a tui connection.
635  *
636  * This is an edge case for advanced use when writing frontends to applications
637  * where data for the intended subwindow is already present, and a lock/block
638  * to wait for the response of the subwindow would create complex buffering
639  * scenarios.
640  *
641  * In those cases, setup the new context already when making the subwindow
642  * request, then in the event handler, should the request be approved - issue a
643  * bind on the context.
644  *
645  * This can also be used to unbind a connection (set it to null) from an
646  * existing tui context. This will cause _destroy to leave the connection
647  * intact.
648  *
649  * ONLY _bind and _destroy are defined for a context without a connection bound
650  * to it.
651  */
652 bool arcan_tui_bind(
653 	arcan_tui_conn* con, struct tui_context* orphan);
654 
655 /*
656  * Destroy the tui context and the managed connection. If the exit state
657  * is successful (EXIT_SUCCESS equivalent), leave [message] as NULL.
658  * Otherwise provide a short user-readable error description.
659  */
660 void arcan_tui_destroy(struct tui_context*, const char* message);
661 
662 /*
663  * callback driven approach with custom I/O multiplexation
664  *
665  * poll the main loop with a specified timeout (typically -1 in its
666  * separate process or thread is fine)
667  * [fdset_sz and n_contexts] are limited to 32 each.
668  *
669  * returns a bitmask with the active descriptors, always provide and
670  * check [errc], if:
671  *  TUI_ERRC_BAD_ARG - missing contexts/fdset or too many contexts/sets
672  *  TUI_ERRC_BAD_FD - then the .bad field will show bad descriptors
673  *  TUI_ERRC_BAD_CTX - then the .ok field will show bad contexts
674  */
675 struct tui_process_res arcan_tui_process(
676 	struct tui_context** contexts, size_t n_contexts,
677 	int* fdset, size_t fdset_sz, int timeout);
678 
679 /*
680  * Extract the current set of pollable descriptors (for custom
681  * multiplexing) and store at most [fddst_lim] into [fdset].
682  *
683  * This set can change between _tui_process calls, and thus need
684  * to be repopulated. Returns the number of descriptors that have
685  * been stored.
686  */
687 size_t arcan_tui_get_handles(
688 	struct tui_context** contexts, size_t n_contexts,
689 	int fddst[], size_t fddst_lim);
690 
691 /*
692  * Update and synch the specified context.
693  * Returns:
694  *  1 on success
695  *  0 on state-ok but no need to sync
696  * -1 and errno (:EAGAIN) if the connection is already busy synching
697  * -1 and errno (:EINVAL) if the connection is broken
698  */
699 int arcan_tui_refresh(struct tui_context*);
700 
701 /*
702  * Explicitly invalidate the context, next refresh will likely
703  * redraw fully. Should only be needed in exceptional cases
704  */
705 void arcan_tui_invalidate(struct tui_context*);
706 
707 /*
708  * get temporary access to the current state of the TUI/context,
709  * returned pointer is undefined between calls to process/refresh
710  */
711 arcan_tui_conn* arcan_tui_acon(struct tui_context*);
712 
713 /*
714  * Open a new connection to a TUI- capable display and return an opaque
715  * connection reference or NULL if no connection could be established. If a
716  * handle is provided, forward it to arcan_tui_setup which will take over
717  * lifecycle management for the connection.
718  */
719 arcan_tui_conn* arcan_tui_open_display(const char* title, const char* ident);
720 
721 /*
722  * try to send the contents of utf8_msg, careful with length of this
723  * string as it will be split into ~64b chunks that each consume an
724  * event-queue slot, and may therefore stall for long periods of time.
725  *
726  * if mouse_fwd mode has been enabled (by user or in the _tui_setup),
727  * this is the only way to send data to the pasteboard.
728  *
729  * will fail if the pasteboard has been disabled (by user).
730  */
731 bool arcan_tui_copy(struct tui_context*, const char* utf8_msg);
732 
733 /*
734  * update title or identity
735  */
736 void arcan_tui_ident(struct tui_context*, const char* ident);
737 
738 /*
739  * get a copy of the contents of the front(f = true) or last(f = false)
740  * cell-level buffer at the x, y coordinates. If x,y is out of bounds,
741  * an empty cell will be returned.
742  */
743 struct tui_cell arcan_tui_getxy(struct tui_context*, size_t x, size_t y,bool f);
744 
745 /*
746  * Send a new request for a subwindow with life-span that depends on the main
747  * connection. The subwindows don't survive migration and will thus be lost on
748  * a ->reset.
749  *
750  * A request is asynchronous, and [id] is only used for the caller to be able
751  * to pair the event delivery with a request. See the (subwindow) tui_cbcfg
752  * entry for more details. Note that subwindows can be delivered as an explicit
753  * "I want you to deal with this" kind of scenario, typically for the TUI_DEBUG
754  * type as a means of dynamically enabling implementation-defined debug output
755  * on demand.
756  *
757  * The possible types are defined as part of arcan_tuisym.h
758  */
759 void arcan_tui_request_subwnd(struct tui_context*, unsigned type, uint16_t id);
760 
761 /*
762  * Extended version of request_subwnd that allows you to also specify hints
763  * to the window manager.
764  *
765  * The argument interpretation is the same as for arcan_tui_request_subwnd,
766  * along with the common 'struct + sizeof(struct)' pattern for additional
767  * arguments.
768  *
769  * These additional arguments server as positioning and sizing hints to
770  * allow the window manager to make better decisions on where to place new
771  * windows and what its respectable sizes are.
772  */
773 void arcan_tui_request_subwnd_ext(struct tui_context*,
774 	unsigned type, uint16_t id, struct tui_subwnd_req req, size_t req_sz);
775 
776 /*
777  * Replace (copy over) the active handler table with a new one.
778  * if the provided cbcfg is NULL, no change to the active set will be
779  * performed, to drop all callbacks, instead, use:
780  *
781  * arcan_tui_update_handlers(tui,
782  *     &(struct tui_cbcfg){}, NULL, sizeof(struct tui_cbcfg));
783  *
784  * If [old] is provided, the old set of handlers will be stored there.
785  *
786  * Returns false if an invalid context was provided, or if the cb_sz was
787  * larger than the .so assumed size of the handler table (application linked
788  * to newer/wrong headers).
789  */
790 bool arcan_tui_update_handlers(struct tui_context*,
791 	const struct tui_cbcfg* new_handlers, struct tui_cbcfg* old, size_t cb_sz);
792 
793 /*
794  * Signal visibility, position and dimension intent for a window or subwindow
795  * [wnd] relative to a possible parent [par].
796  *
797  * [par] must be NULL or refer to the same tui_contextas the subwnd call
798  * initiated from.
799  *
800  * The dimensions inside the constraints structure are a hint, not a guarantee.
801  * The rendering handler need to always be able to draw / layout to any size,
802  * even if that means cropping. Handover windows are special in the sense that
803  * after forwarded, they can't be controlled other than having its requested
804  * anchor being 'scrolled' with the scrollhint.
805  *
806  * Negative values in the constraints means retaining the current values.
807  */
808 void arcan_tui_wndhint(struct tui_context* wnd,
809 	struct tui_context* par, struct tui_constraints cons);
810 
811 /*
812  * Announce capability for reading (input_descr != NULL) and/or writing
813  * (output_descr != NULL) some kind of user- provided file data.
814  *
815  * [immediately=true] - attempt to query the user 'as soon as possible'
816  *                      with an open/save kind of a user dialog, this set
817  *                      of extensions will not override a previously
818  *                      defined one (immediately=false).
819  *
820  * [immediately=false] - remember, as a persistent hint, that the program
821  *                       can load and/or store files that match the
822  *                       description at any time.
823  *
824  * Both sides may result in the (bchunk) callback being triggered at
825  * some point in the future but it is not guaranteed.
826  *
827  * The 'input_descr' and 'output_descr' are a ; separated list of file name
828  * extensions in preferred order, and may include a possible wildcard entry
829  * (*). Each extension should be short (3-5 characters recommended) and must
830  * be shorter than 64 characters.
831  */
832 void arcan_tui_announce_io(struct tui_context* c,
833 	bool immediately, const char* input_descr, const char* output_descr);
834 
835 /*
836  * Indicate the relationship between how much available contents that can be
837  * presented versus how much is actually being shown. This is window size
838  * dependent and will influence seek_absolute/seek_relative requests.
839  *
840  * Offset and total are in lines, and invalid values or underflows will
841  * indicate that the window does not support scrolling/seeking in that
842  * direction (vertical, horizontal).
843  *
844  * The constraints for invalid/underflow are:
845  *
846  * (row_ofs, col_ofs) == 0 || offset > total - (wnd_rows, wnd_cols)
847  * [row/col_tot] < wnd_(rows, cols)
848  *
849  * Content size is assumed to be unknown by default and is reset/ignored
850  * on_resized and on handler updates. Proper event handlers should thus
851  * re-issue content_size hints when that happens.
852  * This includes switching a window to using one of the helper windows.
853  */
854 void arcan_tui_content_size(struct tui_context* wnd,
855 	size_t row_ofs, size_t row_tot, size_t col_ofs, size_t col_tot);
856 
857 /*
858  * Asynchronously transfer the contents of [fdin] to [fdout]. This is
859  * mainly to encourage non-blocking implementation of the bchunk handler.
860  * The descriptors will be closed when the transfer is completed or if
861  * it fails.
862  *
863  * If [sigfd] is provided (> 0),
864  * the result of the operation will be written on finish as:
865  *   -1 (read error)
866  *   -2 (write error)
867  *   -3 (alloc/arg error)
868  *    0 (ok)
869  *
870  * [flags] is reserved for future use.
871  */
872 void arcan_tui_bgcopy(
873 	struct tui_context*, int fdin, int fdout, int sigfd, int flags);
874 
875 /*
876  * Announce/ update an estimate of how much storage is needed to be able
877  * to provide a serialized state-blob that could be used to snapshot the
878  * state of the program in a restorable fashion.
879  *
880  * 0  : not supported (default)
881  * >0 : state size in bytes
882  */
883 void arcan_tui_statesize(struct tui_context* c, size_t sz);
884 
885 /*
886  * Clear all cells (or cells not marked protected) to the default attribute.
887  * This MAY invalidate the entire screen for redraw. Prefer to only erase
888  * regions that should actually be cleared and updated.
889  */
890 void arcan_tui_erase_screen(struct tui_context*, bool protect);
891 void arcan_tui_eraseattr_screen(
892 	struct tui_context*, bool protect, struct tui_screen_attr);
893 
894 void arcan_tui_erase_region(struct tui_context*,
895 	size_t x1, size_t y1, size_t x2, size_t y2, bool protect);
896 void arcan_tui_erase_sb(struct tui_context*);
897 
898 void arcan_tui_eraseattr_region(struct tui_context*, size_t x1,
899 	size_t y1, size_t x2, size_t y2, bool protect, struct tui_screen_attr);
900 
901 /*
902  * helpers that match erase_region + invalidate + cursporpos
903  */
904 void arcan_tui_erase_cursor_to_screen(struct tui_context*, bool protect);
905 void arcan_tui_erase_screen_to_cursor(struct tui_context*, bool protect);
906 void arcan_tui_erase_cursor_to_end(struct tui_context*, bool protect);
907 void arcan_tui_erase_home_to_cursor(struct tui_context*, bool protect);
908 void arcan_tui_erase_current_line(struct tui_context*, bool protect);
909 void arcan_tui_erase_chars(struct tui_context*, size_t n);
910 
911 /*
912  * Insert a new unicode codepoint (expressed as UCS4) at the current cursor
913  * position. If an attribute is provided (!null) it will be used for the
914  * write operation, otherwise, the current default will be used.
915  */
916 void arcan_tui_write(struct tui_context*,
917 	uint32_t ucode, const struct tui_screen_attr*);
918 
919 /*
920  * This converts [n] bytes from [u8] as UTF-8 into multiple UCS4 writes.
921  * It is a more expensive form of arcan_tui_write. If the UTF-8 failed to
922  * validate completely, the function will return false - but codepoints
923  * leading up to the failed sequence may have already been written. If all
924  * [n] bytes were consumed, the function returns true.
925  */
926 bool arcan_tui_writeu8(struct tui_context*,
927 	const uint8_t* u8, size_t n, struct tui_screen_attr*);
928 
929 /*
930  * This calculates the length of the provided character array and forwards
931  * into arcan_tui_writeu8, same encoding and return rules apply.
932  */
933 bool arcan_tui_writestr(
934 	struct tui_context*, const char* str, struct tui_screen_attr*);
935 
936 /*
937  * This behaves similar to the normal printf class functions, except that
938  * it takes an optional [attr] and returns the number of characters written.
939  *
940  * It expands into arcan_tui_writestr calls.
941  */
942 size_t arcan_tui_printf(struct tui_context* ctx,
943 	struct tui_screen_attr* attr, const char* msg, ...);
944 
945 /*
946  * retrieve the current cursor position into the [x:col] and [y:row] field
947  */
948 void arcan_tui_cursorpos(struct tui_context*, size_t* x, size_t* y);
949 
950 /*
951  * Convenience, get a filled out attr structure for the specific color group
952  * with the other properties being the 'default'. This consolidates:
953  * attr = arcan_tui_defattr(tui, NULL)
954  * arcan_tui_get_color(tui, group, attr.fg)
955  * arcan_tui_getbgcolor(tui, group, attr.bg)
956  */
957 struct tui_screen_attr arcan_tui_defcattr(struct tui_context* tui, int group);
958 
959 /*
960  * Fill out rgb[] with the current foreground values of the specified color
961  * group. see the enum tui_color_group for valid values.
962  */
963 void arcan_tui_get_color(struct tui_context* tui, int group, uint8_t rgb[3]);
964 
965 /*
966  * Fill out rgb[] with the matching background value for the specified color
967  * group. see the enum tui_color_group for valid values. For some groups, the
968  * foreground and background color group slots are shared.
969  */
970 void arcan_tui_get_bgcolor(struct tui_context* tui, int group, uint8_t rgb[3]);
971 
972 /*
973  * Update the foreground color field for the specified group.
974  */
975 void arcan_tui_set_color(struct tui_context* tui, int group, uint8_t rgb[3]);
976 
977 /*
978  * Update the background color field for the specified group. For some groups,
979  * the foreground and background color group slots are shared.
980  */
981 void arcan_tui_set_bgcolor(struct tui_context* tui, int group, uint8_t rgb[3]);
982 
983 /*
984  * Reset state-tracking, scrollback buffers, ...
985  * This does not reset/rebuild dynamic keybindings
986  */
987 void arcan_tui_reset(struct tui_context*);
988 
989 /*
990  * Reset and requery the list of active inputs
991  */
992 void arcan_tui_reset_labels(struct tui_context*);
993 
994 /*
995  * modify the current flags/state bitmask with the values of tui_flags ( |= )
996  * returns the mask as it.
997  * see tuisym.h for enum tui_flags
998  */
999 int arcan_tui_set_flags(struct tui_context*, int tui_flags);
1000 
1001 /*
1002  * modify the current flags/state bitmask and unset the values of tui (& ~)
1003  */
1004 void arcan_tui_reset_flags(struct tui_context*, int tui_flags);
1005 
1006 /*
1007  * use from within a on_subwindow handler in order to forward the subwindow
1008  * to an external process. Only a connection from within the handle will work.
1009  * Optional constraints suggest anchoring and sizing constraints.
1010  *
1011  * [Path] points to an absolute path of the binary to hand over control to.
1012  * [Argv] is a null-terminated array of strings that will be used as command
1013  *        line arguments.
1014  * [Env]  is a null-terminated array of strings that will be set as the new
1015  *        process environments.
1016  *
1017  * [flags] is a bitmap of resources handover controls. See tuisym.h for enum.
1018  *          TUI_DETACH_PROCESS | TUI_DETACH_STDIN | TUI_DETACH_STDOUT |
1019  *          TUI_DETACH_STDERR
1020  *
1021  * will reparent the handover window (double-fork like semantics)
1022  * otherwise the returned pid_t will need to be handled like a normal child
1023  * (using wait() class of functions or a SIGCHLD handler).
1024  *
1025  * Will return -1 on failure to spawn,exec,hand-over.
1026  */
1027 pid_t arcan_tui_handover(struct tui_context*, arcan_tui_conn*,
1028 	struct tui_constraints* constraints,
1029 	const char* path, char* const argv[], char* const env[],
1030 	int flags);
1031 
1032 /*
1033  * Hint that certain regions have scrolled:
1034  * (-1, -1) = (up, left), (1, 1 = down, right)
1035  * so that the render may smooth-scroll between the contents of the
1036  * last update and the new one.
1037  *
1038  * [ALLOCATION NOTES]
1039  * This allocation is not tracked and will be used/referenced until
1040  * the next screen refresh call. After it has been used, the dx and dy
1041  * fields will be set to 0.
1042  */
1043 void arcan_tui_scrollhint(
1044 	struct tui_context*, size_t n_regions, struct tui_region*);
1045 
1046 /*
1047  * Build a dynamically allocated state description string that can be
1048  * combined with other debug information to assist in troubleshooting.
1049  * Caller assumes ownership of returned string.
1050  */
1051 char* arcan_tui_statedescr(struct tui_context*);
1052 
1053 /*
1054  * retrieve the current dimensions (same as accessible through _resize)
1055  */
1056 void arcan_tui_dimensions(struct tui_context*, size_t* rows, size_t* cols);
1057 
1058 /* helper to convert from ucs4 (used for the cells due to random access)
1059  * to utf8 (used for input/output), returns number of bytes used in dst. */
1060 size_t arcan_tui_ucs4utf8(uint32_t, char dst[static 4]);
1061 
1062 /* version of ucs4utf8 that also ensures null-termination in the output,
1063  * returns number of bytes used in dst NOT INCLUDING \0 */
1064 size_t arcan_tui_ucs4utf8_s(uint32_t, char dst[static 5]);
1065 
1066 /* helper to convert from a single utf8 codepoint, to ucs4, returns number of
1067  * bytes consumed or -1 on broken input */
1068 ssize_t arcan_tui_utf8ucs4(const char src[static 4], uint32_t* dst);
1069 
1070 /*
1071  * override the default attributes that apply to resets etc.  This will return
1072  * the previous default attribute. If the [attr] argument is null, no change
1073  * will be performed.
1074  */
1075 struct tui_screen_attr arcan_tui_defattr(
1076 	struct tui_context*, struct tui_screen_attr* attr);
1077 
1078 /*
1079  * Simple reference counter that blocks _free from cleaning up until
1080  * no more references exist on the context.
1081  */
1082 void arcan_tui_refinc(struct tui_context*);
1083 
1084 /*
1085  * Simple reference counter that blocks _free from cleaning up until
1086  * no more references exist on the context.
1087  */
1088 void arcan_tui_refdec(struct tui_context*);
1089 
1090 /*
1091  * Set the absolute cursor position, clamped to 0,0,cols-1,rows-1
1092  */
1093 void arcan_tui_move_to(struct tui_context*, size_t x, size_t y);
1094 
1095 /*
1096  * Determine of the specific UC4 unicode codepoint can be drawn with the
1097  * current settings or not. This may be a costly operation and can generate
1098  * false positives (but true negatives), the primary intended use is for 'icon'
1099  * and box-drawing like operations with simple ascii fallbacks.
1100  */
1101 bool arcan_tui_hasglyph(struct tui_context*, uint32_t);
1102 
1103 /*
1104  * Update one of the context message slot with the contents of msg.
1105  * TUI_MESSAGE_PROMPT:
1106  *  - input overlay (e.g. command prompt in vim)
1107  * TUI_MESSAGE_ALERT:
1108  *  - signal that the window wants focus/attention and some reason for it
1109  *    should be used for events that require immediate response
1110  * TUI_MESSAGE_NOTIFICATION:
1111  *  - signal the occurence of some status event that should grab the
1112  *    user's attention, but is not as severe as ALERT
1113  * TUI_MESSAGE_FAILURE:
1114  *  - signal some asynchronous error message that does not fit within the
1115  *    current UI language
1116  */
1117 void arcan_tui_message(struct tui_context*, int target, const char* msg);
1118 
1119 /*
1120  * Indicate an estimated progression state of an operation that would
1121  * block or affect the client response to user input. [status] indicates
1122  * the percentage from (0 = new_job) to (1 = complete).
1123  *
1124  * TYPE can be one out of several:
1125  *
1126  * TUI_PROGRESS_INTERNAL :
1127  *   application specific task
1128  *
1129  * TUI_PROGRESS_BCHUNK_IN :
1130  *   reaction to last received bchunk in
1131  *
1132  * TUI_PROGRESS_BCHUNK_OUT :
1133  *   reaction to last recevied bchunk out
1134  *
1135  * TUI_PROGRESS_STATE_IN :
1136  *   reaction to last received state-input
1137  *
1138  * TUI_PROGRESS_STATE_OUT :
1139  *   reaction to last received state-output
1140  *
1141  * Regression in status (last_status > status) for a type will be treated
1142  * as any previous task for that slot has been completed.
1143  */
1144 void arcan_tui_progress(struct tui_context*, int type, float status);
1145 
1146 /*
1147  * mark the current cursor position as a tabstop
1148  * [DEPRECATE -> widget]
1149  */
1150 void arcan_tui_set_tabstop(struct tui_context*);
1151 
1152 /*
1153  * [DEPRECATE -> widget]
1154  * insert [n] number of empty lines with the default attributes
1155  */
1156 void arcan_tui_insert_lines(struct tui_context*, size_t);
1157 
1158 /*
1159  * [DEPRECATE -> widget]
1160  * CR / LF
1161  */
1162 void arcan_tui_newline(struct tui_context*);
1163 
1164 /*
1165  * remove [n] number of lines
1166  */
1167 void arcan_tui_delete_lines(struct tui_context*, size_t);
1168 
1169 /* [DEPRECATE -> widget]
1170  * insert [n] number of empty characters
1171  * (amounts to a loop of _write calls with the default attributes)
1172  */
1173 void arcan_tui_insert_chars(struct tui_context*, size_t);
1174 void arcan_tui_delete_chars(struct tui_context*, size_t);
1175 
1176 /* [DEPRECATE -> widget]
1177  * move cursor [n] tab-stops positions forward or backwards
1178  */
1179 void arcan_tui_tab_right(struct tui_context*, size_t);
1180 void arcan_tui_tab_left(struct tui_context*, size_t);
1181 
1182 /*
1183  * [DEPRECATE -> widget]
1184  * scroll the window [n] lines up or down in the scrollback
1185  * buffer this is a no-op in alt-screen.
1186  */
1187 void arcan_tui_scroll_up(struct tui_context*, size_t);
1188 void arcan_tui_scroll_down(struct tui_context*, size_t);
1189 
1190 /*
1191  * [DEPRECATE -> widget]
1192  * remove the tabstop at the current position
1193  */
1194 void arcan_tui_reset_tabstop(struct tui_context*);
1195 void arcan_tui_reset_all_tabstops(struct tui_context*);
1196 
1197 /* [DEPRECATE -> widget] */
1198 void arcan_tui_move_up(struct tui_context*, size_t num, bool scroll);
1199 
1200 /* [DEPRECATE -> widget] */
1201 void arcan_tui_move_down(struct tui_context*, size_t num, bool scroll);
1202 
1203 /* [DEPRECATE -> widget] */
1204 void arcan_tui_move_left(struct tui_context*, size_t);
1205 
1206 /* [DEPRECATE -> widget] */
1207 void arcan_tui_move_right(struct tui_context*, size_t);
1208 
1209 /* [DEPRECATE -> widget] */
1210 void arcan_tui_move_line_end(struct tui_context*);
1211 
1212 /* [DEPRECATE -> widget] */
1213 void arcan_tui_move_line_home(struct tui_context*);
1214 
1215 /* [DEPRECATE -> widget] */
1216 int arcan_tui_set_margins(struct tui_context*, size_t top, size_t bottom);
1217 
1218 #else
1219 typedef struct tui_context*(* PTUISETUP)(
1220 	arcan_tui_conn*, struct tui_context*, const struct tui_cbcfg*, size_t, ...);
1221 typedef struct tui_context*(* PTUIBIND)(arcan_tui_conn*, struct tui_context*);
1222 typedef void (* PTUIDESTROY)(struct tui_context*, const char* message);
1223 typedef struct tui_process_res (* PTUIPROCESS)(
1224 struct tui_context**, size_t, int*, size_t, int);
1225 typedef int (* PTUIREFRESH)(struct tui_context*);
1226 typedef void (* PTUIINVALIDATE)(struct tui_context*);
1227 typedef arcan_tui_conn* (* PTUIACON)(struct tui_context*);
1228 typedef arcan_tui_conn* (* PTUIOPENDISPLAY)(const char*, const char*);
1229 typedef bool (* PTUICOPY)(struct tui_context*, const char*);
1230 typedef void (* PTUIIDENT)(struct tui_context*, const char*);
1231 typedef struct tui_cell (* PTUIGETXY)(struct tui_context*, size_t, size_t, bool);
1232 typedef void (* PTUIREQSUB)(struct tui_context*, unsigned, uint16_t);
1233 typedef void (* PTUIREQSUBEXT)
1234 	(struct tui_context*, unsigned, uint16_t, struct tui_subwnd_req, size_t);
1235 typedef void (* PTUIUPDHND)(struct tui_context*, const struct tui_cbcfg*, struct tui_cbcfg*, size_t);
1236 typedef void (* PTUIWNDHINT)(struct tui_context*, struct tui_context*, struct tui_constraints);
1237 typedef void (* PTUIANNOUNCEIO)(struct tui_context*, bool, const char*, const char*);
1238 typedef void (* PTUISTATESZ)(struct tui_context*, size_t);
1239 typedef void (* PTUIPROGRESS)(struct tui_context*, int group, float status);
1240 typedef int (* PTUIALLOCSCR)(struct tui_context*);
1241 typedef bool (* PTUISWSCR)(struct tui_context*, unsigned);
1242 typedef bool (* PTUIDELSCR)(struct tui_context*, unsigned);
1243 typedef uint32_t (* PTUISCREENS)(struct tui_context*);
1244 typedef void (* PTUIWRITE)(struct tui_context*, uint32_t, struct tui_screen_attr*);
1245 typedef bool (* PTUIWRITEU8)(struct tui_context*, const uint8_t*, size_t, struct tui_screen_attr*);
1246 typedef bool (* PTUIWRITESTR)(struct tui_context*, const char*, struct tui_screen_attr*);
1247 typedef void (* PTUICURSORPOS)(struct tui_context*, size_t*, size_t*);
1248 typedef struct tui_screen_attr (* PTUIDEFCATTR)(struct tui_context*, int);
1249 typedef void (* PTUIGETCOLOR)(struct tui_context* tui, int, uint8_t*);
1250 typedef void (* PTUIGETBGCOLOR)(struct tui_context* tui, int, uint8_t*);
1251 typedef void (* PTUISETCOLOR)(struct tui_context* tui, int, uint8_t*);
1252 typedef void (* PTUISETBGCOLOR)(struct tui_context* tui, int, uint8_t*);
1253 typedef void (* PTUIRESET)(struct tui_context*);
1254 typedef void (* PTUIRESETLABELS)(struct tui_context*);
1255 typedef void (* PTUISETFLAGS)(struct tui_context*, int);
1256 typedef void (* PTUIRESETFLAGS)(struct tui_context*, int);
1257 typedef void (* PTUIHASGLYPH)(struct tui_context*, uint32_t);
1258 typedef void (* PTUIMESSAGE)(struct tui_context*, int, const char*);
1259 typedef void (* PTUISETTABSTOP)(struct tui_context*);
1260 typedef void (* PTUIINSERTLINES)(struct tui_context*, size_t);
1261 typedef void (* PTUINEWLINE)(struct tui_context*);
1262 typedef void (* PTUIDELETELINES)(struct tui_context*, size_t);
1263 typedef void (* PTUIINSERTCHARS)(struct tui_context*, size_t);
1264 typedef void (* PTUIDELETECHARS)(struct tui_context*, size_t);
1265 typedef void (* PTUITABRIGHT)(struct tui_context*, size_t);
1266 typedef void (* PTUITABLEFT)(struct tui_context*, size_t);
1267 typedef void (* PTUISCROLLUP)(struct tui_context*, size_t);
1268 typedef void (* PTUISCROLLDOWN)(struct tui_context*, size_t);
1269 typedef void (* PTUIRESETTABSTOP)(struct tui_context*);
1270 typedef void (* PTUIRESETALLTABSTOPS)(struct tui_context*);
1271 typedef void (* PTUISCROLLHINT)(struct tui_context*, size_t, struct tui_region*);
1272 typedef void (* PTUIMOVETO)(struct tui_context*, size_t, size_t);
1273 typedef void (* PTUIMOVEUP)(struct tui_context*, size_t, bool);
1274 typedef void (* PTUIMOVEDOWN)(struct tui_context*, size_t, bool);
1275 typedef void (* PTUIMOVELEFT)(struct tui_context*, size_t);
1276 typedef void (* PTUIMOVERIGHT)(struct tui_context*, size_t);
1277 typedef void (* PTUIMOVELINEEND)(struct tui_context*);
1278 typedef void (* PTUIMOVELINEHOME)(struct tui_context*);
1279 typedef void (* PTUIDIMENSIONS)(struct tui_context*, size_t*, size_t*);
1280 typedef struct tui_screen_attr
1281 	(* PTUIDEFATTR)(struct tui_context*, struct tui_screen_attr*);
1282 typedef void (* PTUIREFINC)(struct tui_context*);
1283 typedef void (* PTUIREFDEC)(struct tui_context*);
1284 typedef int (* PTUISETMARGINS)(struct tui_context*, size_t, size_t);
1285 typedef void (* PTUIERASESCREEN)(struct tui_context*, bool);
1286 typedef void (* PTUIERASEATTRSCREEN)(struct tui_context*, bool, struct tui_screen_attr);
1287 typedef void (* PTUIREGION)(struct tui_context*, size_t, size_t, size_t, size_t, bool);
1288 typedef void (* PTUIERASEATTRREGION)(
1289 	struct tui_context*, size_t, size_t, size_t, size_t, bool, struct tui_screen_attr);
1290 typedef void (* PTUIERASESB)(struct tui_context*);
1291 typedef void (* PTUIERASECURSORTOSCR)(struct tui_context*, bool);
1292 typedef void (* PTUIERASESCRTOCURSOR)(struct tui_context*, bool);
1293 typedef void (* PTUIERASETOCURSOR)(struct tui_context*, bool);
1294 typedef void (* PTUIERASECURSORTOEND)(struct tui_context*, bool);
1295 typedef void (* PTUIERASEHOMETOCURSOR)(struct tui_context*, bool);
1296 typedef void (* PTUIERASECURRENTLINE)(struct tui_context*, bool);
1297 typedef void (* PTUIERASECHARS)(struct tui_context*, size_t);
1298 typedef void (* PTUIERASEREGION)(struct tui_context*, size_t, size_t, size_t, size_t, bool);
1299 typedef char* (* PTUISTATEDESCR)(struct tui_context*);
1300 typedef size_t (* PTUIPRINTF)(struct tui_context*, struct tui_screen_attr*, const char*, ...);
1301 typedef void (* PTUIBGCOPY)(struct tui_context*, int fdin, int fdout, int sig, int fl);
1302 typedef size_t (* PTUIGETHANDLES)(struct tui_context**, size_t, int[], size_t);
1303 typedef void (* PTUIHANDOVER)(struct tui_context*, arcan_tui_conn*,
1304 	struct tui_constraints*, const char*, char* const[], char* const[], int);
1305 typedef size_t (* PTUIUCS4UTF8)(uint32_t, char dst[static 4]);
1306 typedef size_t (* PTUIUCS4UTF8_S)(uint32_t, char dst[static 5]);
1307 typedef ssize_t (* PTUIUTF8UCS4)(const char dst[static 4], uint32_t);
1308 typedef void (* PTUICONTENTSIZE)(struct tui_context*, size_t, size_t, size_t, size_t);
1309 
1310 static PTUIHANDOVER arcan_tui_handover;
1311 static PTUISETUP arcan_tui_setup;
1312 static PTUIBIND arcan_tui_bind;
1313 static PTUIDESTROY arcan_tui_destroy;
1314 static PTUIPROCESS arcan_tui_process;
1315 static PTUIREFRESH arcan_tui_refresh;
1316 static PTUIGETHANDLES arcan_tui_get_handles;
1317 static PTUIINVALIDATE arcan_tui_invalidate;
1318 static PTUIACON arcan_tui_acon;
1319 static PTUIOPENDISPLAY arcan_tui_open_display;
1320 static PTUICOPY arcan_tui_copy;
1321 static PTUIIDENT arcan_tui_ident;
1322 static PTUIGETXY arcan_tui_getxy;
1323 static PTUIREQSUB arcan_tui_request_subwnd;
1324 static PTUIREQSUBEXT arcan_tui_request_subwnd_ext;
1325 static PTUIUPDHND arcan_tui_update_handlers;
1326 static PTUIWNDHINT arcan_tui_wndhint;
1327 static PTUIANNOUNCEIO arcan_tui_announce_io;
1328 static PTUISTATESZ arcan_tui_statesize;
1329 static PTUIWRITE arcan_tui_write;
1330 static PTUIWRITEU8 arcan_tui_writeu8;
1331 static PTUIWRITESTR arcan_tui_writestr;
1332 static PTUICURSORPOS arcan_tui_cursorpos;
1333 static PTUIDEFCATTR arcan_tui_defcattr;
1334 static PTUIGETCOLOR arcan_tui_get_color;
1335 static PTUIGETBGCOLOR arcan_tui_get_bgcolor;
1336 static PTUISETCOLOR arcan_tui_set_color;
1337 static PTUISETBGCOLOR arcan_tui_set_bgcolor;
1338 static PTUIRESET arcan_tui_reset;
1339 static PTUIRESETLABELS arcan_tui_reset_labels;
1340 static PTUISETFLAGS arcan_tui_set_flags;
1341 static PTUIHASGLYPH arcan_tui_hasglyph;
1342 static PTUIMESSAGE arcan_tui_message;
1343 static PTUIPROGRESS arcan_tui_progress;
1344 static PTUIRESETFLAGS arcan_tui_reset_flags;
1345 static PTUISETTABSTOP arcan_tui_set_tabstop;
1346 static PTUIINSERTLINES arcan_tui_insert_lines;
1347 static PTUINEWLINE arcan_tui_newline;
1348 static PTUIDELETELINES arcan_tui_delete_lines;
1349 static PTUIINSERTCHARS arcan_tui_insert_chars;
1350 static PTUIDELETECHARS arcan_tui_delete_chars;
1351 static PTUITABRIGHT arcan_tui_tab_right;
1352 static PTUITABLEFT arcan_tui_tab_left;
1353 static PTUISCROLLUP arcan_tui_scroll_up;
1354 static PTUISCROLLDOWN arcan_tui_scroll_down;
1355 static PTUIRESETTABSTOP arcan_tui_reset_tabstop;
1356 static PTUIRESETALLTABSTOPS arcan_tui_reset_all_tabstops;
1357 static PTUISCROLLHINT arcan_tui_scrollhint;
1358 static PTUIMOVETO arcan_tui_move_to;
1359 static PTUIMOVEUP arcan_tui_move_up;
1360 static PTUIMOVEDOWN arcan_tui_move_down;
1361 static PTUIMOVELEFT arcan_tui_move_left;
1362 static PTUIMOVERIGHT arcan_tui_move_right;
1363 static PTUIMOVELINEEND arcan_tui_move_line_end;
1364 static PTUIMOVELINEHOME arcan_tui_move_line_home;
1365 static PTUIDIMENSIONS arcan_tui_dimensions;
1366 static PTUIDEFATTR arcan_tui_defattr;
1367 static PTUIREFINC arcan_tui_refinc;
1368 static PTUIREFDEC arcan_tui_refdec;
1369 static PTUISETMARGINS arcan_tui_set_margins;
1370 static PTUIERASESCREEN arcan_tui_erase_screen;
1371 static PTUIERASEREGION arcan_tui_erase_region;
1372 static PTUIERASEATTRREGION arcan_tui_eraseattr_region;
1373 static PTUIERASEATTRSCREEN arcan_tui_eraseattr_screen;
1374 static PTUIERASESB arcan_tui_erase_sb;
1375 static PTUIERASECURSORTOSCR arcan_tui_erase_cursor_to_screen;
1376 static PTUIERASESCRTOCURSOR arcan_tui_erase_screen_to_cursor;
1377 static PTUIERASECURSORTOEND arcan_tui_erase_cursor_to_end;
1378 static PTUIERASEHOMETOCURSOR arcan_tui_erase_home_to_cursor;
1379 static PTUIERASECURRENTLINE arcan_tui_erase_current_line;
1380 static PTUIERASECHARS arcan_tui_erase_chars;
1381 static PTUISTATEDESCR arcan_tui_statedescr;
1382 static PTUIPRINTF arcan_tui_printf;
1383 static PTUIBGCOPY arcan_tui_bgcopy;
1384 static PTUIUCS4UTF8 arcan_tui_ucs4utf8;
1385 static PTUIUCS4UTF8_S arcan_tui_ucs4utf8_s;
1386 static PTUIUTF8UCS4 arcan_tui_utf8ucs4;
1387 static PTUICONTENTSIZE arcan_tui_content_size;
1388 
1389 /* dynamic loading function */
arcan_tui_dynload(void * (* lookup)(void *,const char *),void * tag)1390 static bool arcan_tui_dynload(void*(*lookup)(void*, const char*), void* tag)
1391 {
1392 #define M(TYPE, SYM) if (! (SYM = (TYPE) lookup(tag, #SYM)) ) return false
1393 M(PTUIHANDOVER,arcan_tui_handover);
1394 M(PTUIDESTROY,arcan_tui_destroy);
1395 M(PTUISETUP,arcan_tui_setup);
1396 M(PTUIBIND,arcan_tui_bind);
1397 M(PTUIDESTROY,arcan_tui_destroy);
1398 M(PTUIPROCESS,arcan_tui_process);
1399 M(PTUIREFRESH,arcan_tui_refresh);
1400 M(PTUIGETHANDLES,arcan_tui_get_handles);
1401 M(PTUIINVALIDATE,arcan_tui_invalidate);
1402 M(PTUIACON,arcan_tui_acon);
1403 M(PTUIOPENDISPLAY,arcan_tui_open_display);
1404 M(PTUICOPY,arcan_tui_copy);
1405 M(PTUIIDENT,arcan_tui_ident);
1406 M(PTUIGETXY,arcan_tui_getxy);
1407 M(PTUIREQSUB,arcan_tui_request_subwnd);
1408 M(PTUIREQSUBEXT,arcan_tui_request_subwnd_ext);
1409 M(PTUIUPDHND,arcan_tui_update_handlers);
1410 M(PTUIWNDHINT,arcan_tui_wndhint);
1411 M(PTUIANNOUNCEIO,arcan_tui_announce_io);
1412 M(PTUISTATESZ,arcan_tui_statesize);
1413 M(PTUIWRITE,arcan_tui_write);
1414 M(PTUIWRITEU8,arcan_tui_writeu8);
1415 M(PTUIWRITESTR,arcan_tui_writestr);
1416 M(PTUICURSORPOS,arcan_tui_cursorpos);
1417 M(PTUIDEFCATTR,arcan_tui_defcattr);
1418 M(PTUIGETCOLOR,arcan_tui_get_color);
1419 M(PTUIGETBGCOLOR,arcan_tui_get_bgcolor);
1420 M(PTUISETCOLOR,arcan_tui_set_color);
1421 M(PTUISETBGCOLOR,arcan_tui_set_bgcolor);
1422 M(PTUIRESET,arcan_tui_reset);
1423 M(PTUIRESETLABELS,arcan_tui_reset_labels);
1424 M(PTUISETFLAGS,arcan_tui_set_flags);
1425 M(PTUIRESETFLAGS,arcan_tui_reset_flags);
1426 M(PTUISETTABSTOP,arcan_tui_set_tabstop);
1427 M(PTUIINSERTLINES,arcan_tui_insert_lines);
1428 M(PTUINEWLINE,arcan_tui_newline);
1429 M(PTUIDELETELINES,arcan_tui_delete_lines);
1430 M(PTUIINSERTCHARS,arcan_tui_insert_chars);
1431 M(PTUIDELETECHARS,arcan_tui_delete_chars);
1432 M(PTUITABRIGHT,arcan_tui_tab_right);
1433 M(PTUITABLEFT,arcan_tui_tab_left);
1434 M(PTUISCROLLUP,arcan_tui_scroll_up);
1435 M(PTUISCROLLDOWN,arcan_tui_scroll_down);
1436 M(PTUIRESETTABSTOP,arcan_tui_reset_tabstop);
1437 M(PTUIRESETALLTABSTOPS,arcan_tui_reset_all_tabstops);
1438 M(PTUISCROLLHINT,arcan_tui_scrollhint);
1439 M(PTUIMOVETO,arcan_tui_move_to);
1440 M(PTUIMOVEUP,arcan_tui_move_up);
1441 M(PTUIMOVEDOWN,arcan_tui_move_down);
1442 M(PTUIMOVELEFT,arcan_tui_move_left);
1443 M(PTUIMOVERIGHT,arcan_tui_move_right);
1444 M(PTUIMOVELINEEND,arcan_tui_move_line_end);
1445 M(PTUIMOVELINEHOME,arcan_tui_move_line_home);
1446 M(PTUIDIMENSIONS,arcan_tui_dimensions);
1447 M(PTUIDEFATTR,arcan_tui_defattr);
1448 M(PTUIREFINC,arcan_tui_refinc);
1449 M(PTUIREFDEC,arcan_tui_refdec);
1450 M(PTUISETMARGINS,arcan_tui_set_margins);
1451 M(PTUIERASESCREEN,arcan_tui_erase_screen);
1452 M(PTUIERASEREGION,arcan_tui_erase_region);
1453 M(PTUIERASEATTRREGION,arcan_tui_eraseattr_region);
1454 M(PTUIERASEATTRSCREEN,arcan_tui_eraseattr_screen);
1455 M(PTUIERASESB,arcan_tui_erase_sb);
1456 M(PTUIERASECURSORTOSCR,arcan_tui_erase_cursor_to_screen);
1457 M(PTUIERASESCRTOCURSOR,arcan_tui_erase_screen_to_cursor);
1458 M(PTUIERASECURSORTOEND,arcan_tui_erase_cursor_to_end);
1459 M(PTUIERASEHOMETOCURSOR,arcan_tui_erase_home_to_cursor);
1460 M(PTUIERASECURRENTLINE,arcan_tui_erase_current_line);
1461 M(PTUIERASECHARS,arcan_tui_erase_chars);
1462 M(PTUISTATEDESCR, arcan_tui_statedescr);
1463 M(PTUIPRINTF, arcan_tui_printf);
1464 M(PTUIBGCOPY, arcan_tui_bgcopy);
1465 M(PTUIHASGLYPH, arcan_tui_hasglyph);
1466 M(PTUIMESSAGE, arcan_tui_message);
1467 M(PTUIUCS4UTF8, arcan_tui_ucs4utf8);
1468 M(PTUIUCS4UTF8_S, arcan_tui_ucs4utf8_s);
1469 M(PTUIUTF8UCS4, arcan_tui_utf8ucs4);
1470 M(PTUIPROGRESS, arcan_tui_progress);
1471 M(PTUICONTENTSIZE, arcan_tui_content_size);
1472 
1473 #undef M
1474 
1475 	return true;
1476 }
1477 #endif
1478 #endif
1479