1 /*
2  Arcan Text-Oriented User Interface Library, Extensions
3  Copyright: 2018-2019, Bjorn Stahl
4  License: 3-clause BSD
5  Description: This widget adds support for transforming a tui context
6  into a line oriented window with scrollback.
7 */
8 
9 #ifndef HAVE_TUI_LINEWND
10 #define HAVE_TUI_LINEWND
11 
12 
13 /*
14  * Description:
15  *
16  * Arguments:
17  * [ctx] (!null) references the context to control
18  *
19  * Returns:
20  * true if context was allocated and setup, false on allocation failure or
21  * argument errors.
22  *
23  * Handlers/Allocation:
24  * This dynamically allocates internally, and replaces the normal set of
25  * handlers. Use _linewnd_restore to return the context to the state it was
26  * in before this function was called.
27  *
28  * This hooks and forwards all the normal table handlers, it is only in the
29  * context of scrollback state where events gets masked and so on.
30  *
31  * Example:
32  * See the #ifdef EXAMPLE block at the bottom of tui_linewnd.c
33  */
34 
35 struct tui_linewnd_line;
36 struct tui_linewnd_line {
37 	size_t n_cells;
38 	struct tui_cell* cells;
39 };
40 
41 #ifndef ARCAN_TUI_DYNAMIC
42 bool arcan_tui_linewnd_setup(
43 	struct tui_context*, struct tui_constraints* cons);
44 
45 /*
46  * Layout / render function, this can be used on a non-linewnd context
47  * as well in order to get consistent wrapping modes, in other widgets.
48  *
49  * If [start_row] or [start_col] is out-of-bounds, 0 will be returned and
50  * no drawing will be performed.
51  *
52  * If [end_row, end_col] is out-of-bounds or less than [start_row, start_col]
53  * it will be set to the context dimensions.
54  *
55  * Returns the row-advance after processing the line buffer
56  *   if > n_lines wrapping was applied on long lines.
57  *   if < n_lines rendering was cancelled due to reaching the end of the screen.
58  */
59 
60 enum linewnd_render_flags {
61 	LINEWND_RENDER_NOTAB = 1,
62 	LINEWND_RENDER_WRAP = 2
63 };
64 
65 size_t arcan_tui_linewnd_render(struct tui_context*,
66 	struct tui_linewnd_line*, size_t n_lines,
67 	size_t start_row, size_t start_col,
68 	size_t end_row, size_t end_col,
69 	size_t* tabs, size_t n_tabs,
70 	int flags
71 );
72 
73 /*
74  * Replace the current history buffer with a new one
75  */
76 void arcan_tui_linewnd_set_buffer(
77 	struct tui_context*, struct tui_linewnd_line*, size_t n_lines);
78 
79 /*
80  * Retrieve a snapshot of the last n_lines of the history buffer,
81  * returns the actual number of lines in the buffer.
82  */
83 size_t arcan_tui_linewnd_get_buffer(
84 	struct tui_context*, struct tui_linewnd_line*, size_t n_lines);
85 
86 /*
87  * Commit the set line(s) to the currently active buffer,
88  * this will create an internal copy as part of the buffer management
89  */
90 void arcan_tui_linewnd_add_line(
91 	struct tui_context*, const struct tui_linewnd_line*);
92 
93 /*
94  * Return handler set to the state it was before the linewindow was
95  * setup.
96  */
97 void arcan_tui_linewnd_release(struct tui_context*);
98 
99 /*
100  * The cases where we want to dynamically load the library as a plugin
101  */
102 #else
103 typedef size_t(* PTUILINEWND_RENDER)(
104 	struct tui_context*, struct tui_linewnd_line*, size_t n_line,
105 	size_t start_row, size_t start_col, size_t end_row, size_t end_col,
106 	size_t* tabs, size_t n_tabs, int flags);
107 typedef bool(* PTUILINEWND_SETUP)(
108 	struct tui_context*, struct tui_list_entry*, size_t n_entries);
109 typedef void(* PTUILINEWND_SETBUFFER)(
110 	struct tui_context*, struct tui_linewnd_line*, size_t n_lines);
111 typedef void(* PTUILINEWND_RELEASE)(struct tui_context*);
112 
113 static PTUILINEWND_RENDER arcan_tui_linewnd_render;
114 static PTUILINEWND_SETUP arcan_tui_linewnd_setup;
115 static PTUILINEWND_SETBUFFER arcan_tui_linewnd_set_buffer;
116 static PTUILINEWND_ADDLINE arcan_tui_linewnd_add_line;
117 static PTUILINEWND_RELEASE arcan_tui_linewnd_release;
118 
arcan_tui_linewnd_dynload(void * (* lookup)(void *,const char *),void * tag)119 static bool arcan_tui_linewnd_dynload(
120 	void*(*lookup)(void*, const char*), void* tag)
121 {
122 #define M(TYPE, SYM) if (! (SYM = (TYPE) lookup(tag, #SYM)) ) return false
123 M(PTUILINEWND_SETUP, arcan_tui_linewnd_setup);
124 M(PTUILINEWND_SETBUFFER, arcan_tui_linewnd_set_buffer);
125 M(PTUILINEWND_ADDLINE, arcan_tui_linewnd_add_line);
126 M(PTUILINEWND_RELEASE, arcan_tui_linewnd_release);
127 M(PTUILINEWND_RENDER, arcan_tui_linewnd_render);
128 #undef M
129 return true;
130 }
131 #endif
132 #endif
133