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