1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <tui/extern.h>
28 #include <tui/tui.h>
29 #include <klib/refcount.h>
30 #include <klib/rc.h>
31 #include <klib/log.h>
32
33 #include "eventring.h"
34 #include "screen.h"
35 #include "tui-priv.h"
36
37 #include <sysalloc.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41
42 /* this is the generic - not platform specific code of KTUI */
43
44 /* static const char tuimanager_classname [] = "TUIManager"; */
45 static const char tui_classname [] = "TUI_Implementation";
46
KTUIMake(const KTUIMgr * mgr,struct KTUI ** self,uint32_t timeout)47 LIB_EXPORT rc_t CC KTUIMake ( const KTUIMgr * mgr, struct KTUI ** self, uint32_t timeout )
48 {
49 rc_t rc = 0;
50 if ( self == NULL )
51 rc = RC( rcApp, rcAttr, rcCreating, rcSelf, rcNull );
52 else
53 {
54 KTUI * tui = malloc( sizeof * tui );
55 if ( tui == NULL )
56 rc = RC( rcApp, rcAttr, rcCreating, rcMemory, rcExhausted );
57 else
58 {
59 tui_ac v = { KTUI_a_none, KTUI_c_black, KTUI_c_green };
60 event_ring_init( &tui->ev_ring );
61
62 clr_tui_screen( &tui->screen, &v, false );
63
64 rc = KTUI_Init_platform( tui ); /* call the platform specific init */
65 if ( rc == 0 )
66 {
67 tui->mgr = mgr;
68 tui->timeout = timeout;
69 if ( rc == 0 )
70 KRefcountInit( &tui->refcount, 1, "TUI", "make", tui_classname );
71 }
72 if ( rc != 0 )
73 free( ( void * ) tui );
74 else
75 ( * self ) = tui;
76 }
77 }
78 return rc;
79 }
80
81
KTUIAddRef(const struct KTUI * self)82 LIB_EXPORT rc_t CC KTUIAddRef ( const struct KTUI * self )
83 {
84 rc_t rc = 0;
85 if ( self != NULL )
86 {
87 switch ( KRefcountAdd( &self->refcount, tui_classname ) )
88 {
89 case krefOkay :
90 break;
91 case krefZero :
92 rc = RC( rcNS, rcMgr, rcAttaching, rcRefcount, rcIncorrect );
93 case krefLimit :
94 rc = RC( rcNS, rcMgr, rcAttaching, rcRefcount, rcExhausted );
95 case krefNegative :
96 rc = RC( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
97 default :
98 rc = RC( rcNS, rcMgr, rcAttaching, rcRefcount, rcUnknown );
99 }
100 }
101 return rc;
102 }
103
104
KTUIDestroy(struct KTUI * self)105 static rc_t CC KTUIDestroy ( struct KTUI * self )
106 {
107 KTUI_Destroy_platform( self->pf );
108
109 event_ring_destroy( &self->ev_ring );
110 KRefcountWhack( &self->refcount, tui_classname );
111 free( self );
112 return 0;
113 }
114
115
116 /* not platform specific */
KTUIRelease(const struct KTUI * self)117 LIB_EXPORT rc_t CC KTUIRelease ( const struct KTUI * self )
118 {
119 rc_t rc = 0;
120 if ( self != NULL )
121 {
122 switch ( KRefcountDrop( &self->refcount, tui_classname ) )
123 {
124 case krefOkay :
125 case krefZero :
126 break;
127 case krefWhack :
128 rc = KTUIDestroy( ( struct KTUI * )self );
129 break;
130 case krefNegative:
131 return RC( rcNS, rcMgr, rcAttaching, rcRefcount, rcInvalid );
132 default:
133 rc = RC( rcNS, rcMgr, rcAttaching, rcRefcount, rcUnknown );
134 break;
135 }
136 }
137 return rc;
138 }
139
140
KTUISetTimeout(struct KTUI * self,uint32_t timeout)141 LIB_EXPORT rc_t CC KTUISetTimeout ( struct KTUI * self, uint32_t timeout )
142 {
143 rc_t rc = 0;
144
145 if ( self == NULL )
146 rc = RC( rcApp, rcAttr, rcCreating, rcSelf, rcNull );
147 else
148 self->timeout = timeout;
149
150 return rc;
151 }
152
153
KTUIPrint(struct KTUI * self,const tui_point * p,const tui_ac * ac,const char * s,uint32_t l)154 LIB_EXPORT rc_t CC KTUIPrint( struct KTUI * self, const tui_point * p,
155 const tui_ac * ac, const char * s, uint32_t l )
156 {
157 rc_t rc = 0;
158
159 if ( self == NULL )
160 rc = RC( rcApp, rcAttr, rcCreating, rcSelf, rcNull );
161 else if ( ac == NULL || p == NULL )
162 rc = RC( rcApp, rcAttr, rcCreating, rcParam, rcNull );
163 else
164 /* in screen.c */
165 print_into_screen( &self->screen, p->x, p->y, ac, s, l );
166
167 return rc;
168 }
169
170
KTUIRect(struct KTUI * self,const tui_rect * r,const tui_ac * ac,const char c)171 LIB_EXPORT rc_t CC KTUIRect ( struct KTUI * self, const tui_rect * r,
172 const tui_ac * ac, const char c )
173 {
174 rc_t rc = 0;
175
176 if ( self == NULL )
177 rc = RC( rcApp, rcAttr, rcCreating, rcSelf, rcNull );
178 else if ( ac == NULL )
179 rc = RC( rcApp, rcAttr, rcCreating, rcParam, rcNull );
180 else
181 {
182 if ( r != NULL )
183 paint_into_screen( &self->screen, r, ac, c );
184 else
185 clr_tui_screen( &self->screen, ac, true );
186 }
187
188 return rc;
189 }
190
191
KTUIFlush(struct KTUI * self,bool forced)192 LIB_EXPORT rc_t CC KTUIFlush ( struct KTUI * self, bool forced )
193 {
194 rc_t rc = 0;
195
196 if ( self == NULL )
197 rc = RC( rcApp, rcAttr, rcCreating, rcSelf, rcNull );
198 else
199 {
200 if ( forced )
201 {
202 tui_ac ac;
203 set_ac( &ac, KTUI_a_none, KTUI_c_white, KTUI_c_white );
204 clr_tui_screen( &self->screen, &ac, true );
205 }
206
207 /* this is platform specific! in systui.c */
208 send_tui_screen( &self->screen, self->lines, self->cols );
209 }
210
211 return rc;
212 }
213
214
215 /* not platform specific, except the call to platform specific read_from_stdin() */
KTUIGet(struct KTUI * self,tui_event * event)216 LIB_EXPORT rc_t CC KTUIGet ( struct KTUI * self, tui_event * event )
217 {
218 rc_t rc = 0;
219 if ( self == NULL )
220 rc = RC( rcApp, rcAttr, rcCreating, rcSelf, rcNull );
221 else if ( event == NULL )
222 rc = RC( rcApp, rcAttr, rcCreating, rcParam, rcNull );
223 else
224 {
225 tui_event * ev;
226 read_from_stdin( self, self->timeout ); /* that is the platform specific state-machine */
227 ev = event_ring_get( &self->ev_ring );
228 if ( ev == NULL )
229 {
230 event->event_type = ktui_event_none;
231 }
232 else
233 {
234 copy_event( ev, event );
235 event_ring_put_to_stock( &self->ev_ring, ev );
236 }
237 }
238 return rc;
239 }
240
241
242 /* not platform specific, just returns values from self-struct */
KTUIGetExtent(struct KTUI * self,int * cols,int * lines)243 LIB_EXPORT rc_t CC KTUIGetExtent ( struct KTUI * self, int * cols, int * lines )
244 {
245 rc_t rc = 0;
246 if ( self == NULL )
247 rc = RC( rcApp, rcAttr, rcCreating, rcSelf, rcNull );
248 else if ( lines == NULL || cols == NULL )
249 rc = RC( rcApp, rcAttr, rcCreating, rcParam, rcNull );
250 else
251 {
252 *lines = self->lines;
253 *cols = self->cols;
254 }
255 return rc;
256 }
257
258
KTUIClrScr(struct KTUI * self,KTUI_color bg)259 LIB_EXPORT rc_t CC KTUIClrScr( struct KTUI * self, KTUI_color bg )
260 {
261 tui_ac ac;
262 set_ac( &ac, KTUI_a_none, bg, bg );
263 clr_tui_screen( &self->screen, &ac, true );
264 return 0;
265 }
266
267
set_ac(tui_ac * dst,KTUI_attrib attr,KTUI_color fg,KTUI_color bg)268 LIB_EXPORT void set_ac( tui_ac * dst, KTUI_attrib attr, KTUI_color fg, KTUI_color bg )
269 {
270 if ( dst != NULL )
271 {
272 dst->attr = attr;
273 dst->fg = fg;
274 dst->bg = bg;
275 }
276 }
277
278
copy_ac(tui_ac * dst,const tui_ac * src)279 LIB_EXPORT void copy_ac( tui_ac * dst, const tui_ac * src )
280 {
281 if ( dst != NULL && src != NULL )
282 {
283 dst->attr = src->attr;
284 dst->fg = src->fg;
285 dst->bg = src->bg;
286 }
287 }
288
289
inverse_ac(tui_ac * dst,const tui_ac * src)290 LIB_EXPORT void inverse_ac( tui_ac * dst, const tui_ac * src )
291 {
292 if ( dst != NULL && src != NULL )
293 {
294 dst->attr = src->attr;
295 dst->fg = src->bg;
296 dst->bg = src->fg;
297 }
298 }
299
300
set_rect(tui_rect * dst,int x,int y,int w,int h)301 LIB_EXPORT void set_rect( tui_rect * dst, int x, int y, int w, int h )
302 {
303 if ( dst != NULL )
304 {
305 dst->top_left.x = x;
306 dst->top_left.y = y;
307 dst->w = w;
308 dst->h = h;
309 }
310 }
311
312
copy_rect(tui_rect * dst,const tui_rect * src)313 LIB_EXPORT void copy_rect( tui_rect * dst, const tui_rect * src )
314 {
315 if ( dst != NULL && src != NULL )
316 {
317 dst->top_left.x = src->top_left.x;
318 dst->top_left.y = src->top_left.y;
319 dst->w = src->w;
320 dst->h = src->h;
321 }
322 }
323
put_window_event(struct KTUI * self,int cols,int lines)324 void CC put_window_event( struct KTUI * self, int cols, int lines )
325 {
326 tui_event * event = event_ring_get_from_stock_or_make( &self->ev_ring );
327 if ( event != NULL )
328 {
329 event->event_type = ktui_event_window;
330 event->data.win_data.w = cols;
331 event->data.win_data.h = lines;
332 event_ring_put( &self->ev_ring, event );
333 }
334 }
335
336
put_kb_event(struct KTUI * self,int key,KTUI_key code)337 void CC put_kb_event( struct KTUI * self, int key, KTUI_key code )
338 {
339 tui_event * event = event_ring_get_from_stock_or_make( &self->ev_ring );
340 if ( event != NULL )
341 {
342 event->event_type = ktui_event_kb;
343 event->data.kb_data.key = key;
344 event->data.kb_data.code = code;
345 event_ring_put( &self->ev_ring, event );
346 }
347 }
348
put_mouse_event(struct KTUI * self,unsigned int x,unsigned int y,KTUI_mouse_button button,KTUI_mouse_action action,uint32_t raw_event)349 void CC put_mouse_event( struct KTUI * self, unsigned int x, unsigned int y,
350 KTUI_mouse_button button, KTUI_mouse_action action, uint32_t raw_event )
351 {
352 tui_event * event = event_ring_get_from_stock_or_make( &self->ev_ring );
353 if ( event != NULL )
354 {
355 event->event_type = ktui_event_mouse;
356 event->data.mouse_data.button = button;
357 event->data.mouse_data.action = action;
358 event->data.mouse_data.x = x;
359 event->data.mouse_data.y = y;
360 event->data.mouse_data.raw_event = raw_event;
361 event_ring_put( &self->ev_ring, event );
362 }
363 }
364
365
is_alpha_key(tui_event * event,char c)366 LIB_EXPORT bool CC is_alpha_key( tui_event * event, char c )
367 {
368 return ( event != NULL &&
369 event->event_type == ktui_event_kb &&
370 event->data.kb_data.code == ktui_alpha &&
371 event->data.kb_data.key == c );
372 }
373
374
is_key_code(tui_event * event,KTUI_key k)375 LIB_EXPORT bool CC is_key_code( tui_event * event, KTUI_key k )
376 {
377 return ( event != NULL &&
378 event->event_type == ktui_event_kb &&
379 event->data.kb_data.code == k );
380 }
381