source: libcaca/trunk/caca/caca_conio.c @ 3602

Last change on this file since 3602 was 3602, checked in by Sam Hocevar, 10 years ago

Make conio_refresh() play nicer with the resources when the machine is slow.

  • Property svn:keywords set to Id
File size: 9.8 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id: caca_conio.c 3602 2009-08-02 11:09:10Z sam $
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  This file contains a full conio.h reimplementation. More information
17 *  on conio.h can be found on http://poli.cs.vsb.cz/c/help/conio.htm
18 */
19
20#include "config.h"
21
22#if !defined(__KERNEL__)
23#   include <stdio.h>
24#   include <stdlib.h>
25#endif
26
27#include "caca.h"
28#include "caca_internals.h"
29#include "caca_conio.h"
30
31static caca_canvas_t *cv;
32static caca_display_t *dp;
33
34static caca_timer_t refresh_timer = {0, 0};
35static uint64_t refresh_ticks;
36
37static int unget_ch = -1;
38static int kbhit_ch = -1;
39static char pass_buffer[BUFSIZ];
40static char cgets_buffer[BUFSIZ];
41
42static void conio_init(void);
43static void conio_refresh(void);
44static void conio_fini(void);
45
46int caca_conio_directvideo;
47int caca_conio__wscroll;
48
49/** \brief DOS conio.h cgets() equivalent */
50char * caca_conio_cgets(char *str)
51{
52    conio_init();
53
54    /* TODO: implement this function */
55    cgets_buffer[0] = '\0';
56
57    return cgets_buffer;
58}
59
60/** \brief DOS conio.h clreol() equivalent */
61void caca_conio_clreol(void)
62{
63    conio_init();
64
65    /* FIXME: must work within the currently active text window */
66    caca_fill_box(cv, caca_wherex(cv), caca_wherey(cv),
67                  caca_get_canvas_width(cv), caca_wherey(cv), ' ');
68
69    conio_refresh();
70}
71
72/** \brief DOS conio.h clrscr() equivalent */
73void caca_conio_clrscr(void)
74{
75    conio_init();
76
77    caca_clear_canvas(cv);
78    caca_gotoxy(cv, 0, 0);
79
80    conio_refresh();
81}
82
83/** \brief DOS conio.h cprintf() equivalent */
84int caca_conio_cprintf(const char *format, ...)
85{
86    va_list args;
87    int ret;
88
89    conio_init();
90
91    va_start(args, format);
92    ret = caca_vprintf(cv, caca_wherex(cv), caca_wherey(cv), format, args);
93    va_end(args);
94
95    caca_gotoxy(cv, caca_wherex(cv) + ret, caca_wherey(cv));
96
97    conio_refresh();
98
99    return ret;
100}
101
102/** \brief DOS conio.h cputs() equivalent */
103int caca_conio_cputs(const char *str)
104{
105    conio_init();
106
107    /* TODO: implement this function */
108
109    return 0;
110}
111
112/** \brief DOS conio.h cscanf() equivalent */
113int caca_conio_cscanf(char *format, ...)
114{
115    conio_init();
116
117    /* TODO: implement this function */
118
119    return 0;
120}
121
122/** \brief DOS dos.h delay() equivalent */
123void caca_conio_delay(unsigned int milliseconds)
124{
125    int64_t usec = (int64_t)milliseconds * 1000;
126    caca_timer_t timer = {0, 0};
127
128    conio_init();
129
130    _caca_getticks(&timer);
131
132    /* Refresh screen as long as we have enough time */
133    while(usec > 5000)
134    {
135        conio_refresh();
136        _caca_sleep(5000);
137        usec -= _caca_getticks(&timer);
138    }
139
140    if(usec > 0)
141        _caca_sleep(usec);
142
143    conio_refresh();
144}
145
146/** \brief DOS conio.h delline() equivalent */
147void caca_conio_delline(void)
148{
149    conio_init();
150
151    /* TODO: implement this function */
152}
153
154/** \brief DOS conio.h getch() equivalent */
155int caca_conio_getch(void)
156{
157    caca_event_t ev;
158    int ret;
159
160    conio_init();
161
162    if(unget_ch >= 0)
163    {
164        int tmp = unget_ch;
165        unget_ch = -1;
166        return tmp;
167    }
168
169    if(kbhit_ch >= 0)
170    {
171        int tmp = kbhit_ch;
172        kbhit_ch = -1;
173        return tmp;
174    }
175
176    while(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 1000) == 0)
177        conio_refresh();
178
179    ret = caca_get_event_key_ch(&ev);
180
181    conio_refresh();
182
183    return ret;
184}
185
186/** \brief DOS conio.h getche() equivalent */
187int caca_conio_getche(void)
188{
189    /* conio_init() is called here. */
190    int tmp = caca_conio_getch();
191    /* conio_refresh() is called here. */
192    caca_conio_printf("%c", tmp);
193
194    return tmp;
195}
196
197/** \brief DOS conio.h getpass() equivalent */
198char * caca_conio_getpass(const char *prompt)
199{
200    conio_init();
201
202    /* TODO: implement this function */
203    pass_buffer[0] = '\0';
204
205    return pass_buffer;
206}
207
208/** \brief DOS conio.h gettext() equivalent */
209int caca_conio_gettext(int left, int top, int right, int bottom, void *destin)
210{
211    conio_init();
212
213    /* TODO: implement this function */
214
215    return 0;
216}
217
218/** \brief DOS conio.h gettextinfo() equivalent */
219void caca_conio_gettextinfo(struct caca_conio_text_info *r)
220{
221    conio_init();
222
223    /* TODO: implement this function */
224}
225
226/** \brief DOS conio.h gotoxy() equivalent */
227void caca_conio_gotoxy(int x, int y)
228{
229    conio_init();
230
231    caca_gotoxy(cv, x - 1, y - 1);
232
233    conio_refresh();
234}
235
236/** \brief DOS conio.h highvideo() equivalent */
237void caca_conio_highvideo(void)
238{
239    conio_init();
240
241    /* TODO: implement this function */
242}
243
244/** \brief DOS conio.h insline() equivalent */
245void caca_conio_insline(void)
246{
247    conio_init();
248
249    /* TODO: implement this function */
250}
251
252/** \brief DOS conio.h kbhit() equivalent */
253int caca_conio_kbhit(void)
254{
255    static caca_timer_t timer = {0, 0};
256    static int last_failed = 0;
257    caca_event_t ev;
258
259    conio_init();
260
261    /* If last call failed and this call is made less than 100µs
262     * afterwards, we assume the caller is in a busy loop and we
263     * delay it slightly to avoid resource leakage. */
264    if(last_failed && _caca_getticks(&timer) < 100)
265    {
266        _caca_sleep(1000);
267        conio_refresh();
268    }
269
270    last_failed = 0;
271
272    if(kbhit_ch >= 0)
273        return 1;
274
275    if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, &ev, 0))
276    {
277        kbhit_ch = caca_get_event_key_ch(&ev);
278        return 1;
279    }
280
281    last_failed = 1;
282
283    return 0;
284}
285
286/** \brief DOS conio.h lowvideo() equivalent */
287void caca_conio_lowvideo(void)
288{
289    conio_init();
290
291    /* TODO: implement this function */
292}
293
294/** \brief DOS conio.h movetext() equivalent */
295int caca_conio_movetext(int left, int top, int right, int bottom,
296                        int destleft, int desttop)
297{
298    conio_init();
299
300    /* TODO: implement this function */
301
302    return 0;
303}
304
305/** \brief DOS conio.h normvideo() equivalent */
306void caca_conio_normvideo(void)
307{
308    conio_init();
309
310    /* TODO: implement this function */
311}
312
313/** \brief DOS dos.h nosound() equivalent */
314void caca_conio_nosound(void)
315{
316    conio_init();
317
318    /* TODO: implement this function */
319}
320
321/** \brief DOS stdio.h printf() equivalent */
322int caca_conio_printf(const char *format, ...)
323{
324    va_list args;
325    int ret;
326
327    conio_init();
328
329    va_start(args, format);
330    ret = caca_vprintf(cv, caca_wherex(cv), caca_wherey(cv), format, args);
331    va_end(args);
332
333    caca_gotoxy(cv, caca_wherex(cv) + ret, caca_wherey(cv));
334
335    conio_refresh();
336
337    return 0;
338}
339
340/** \brief DOS conio.h putch() equivalent */
341int caca_conio_putch(int ch)
342{
343    conio_init();
344
345    /* TODO: implement this function */
346
347    return 0;
348}
349
350/** \brief DOS conio.h puttext() equivalent */
351int caca_conio_puttext(int left, int top, int right, int bottom, void *destin)
352{
353    conio_init();
354
355    /* TODO: implement this function */
356
357    return 0;
358}
359
360/** \brief DOS conio.h _setcursortype() equivalent */
361void caca_conio__setcursortype(int cur_t)
362{
363    conio_init();
364
365    /* TODO: implement this function */
366}
367
368/** \brief DOS dos.h sleep() equivalent */
369void caca_conio_sleep(unsigned int seconds)
370{
371    int64_t usec = (int64_t)seconds * 1000000;
372    caca_timer_t timer = {0, 0};
373
374    conio_init();
375
376    _caca_getticks(&timer);
377
378    /* Refresh screen as long as we have enough time */
379    while(usec > 5000)
380    {
381        conio_refresh();
382        _caca_sleep(5000);
383        usec -= _caca_getticks(&timer);
384    }
385
386    if(usec > 0)
387        _caca_sleep(usec);
388
389    conio_refresh();
390}
391
392/** \brief DOS dos.h sound() equivalent */
393void caca_conio_sound(unsigned int frequency)
394{
395    conio_init();
396
397    /* TODO: implement this function */
398}
399
400/** \brief DOS conio.h textattr() equivalent */
401void caca_conio_textattr(int newattr)
402{
403    conio_init();
404
405    /* TODO: implement this function */
406}
407
408/** \brief DOS conio.h textbackground() equivalent */
409void caca_conio_textbackground(int newcolor)
410{
411    conio_init();
412
413    caca_set_color_ansi(cv, caca_attr_to_ansi_fg(caca_get_attr(cv, -1, -1)),
414                        newcolor);
415}
416
417/** \brief DOS conio.h textcolor() equivalent */
418void caca_conio_textcolor(int newcolor)
419{
420    conio_init();
421
422    caca_set_color_ansi(cv, newcolor,
423                        caca_attr_to_ansi_bg(caca_get_attr(cv, -1, -1)));
424}
425
426/** \brief DOS conio.h textmode() equivalent */
427void caca_conio_textmode(int newmode)
428{
429    conio_init();
430
431    /* TODO: implement this function */
432}
433
434/** \brief DOS conio.h ungetch() equivalent */
435int caca_conio_ungetch(int ch)
436{
437    conio_init();
438
439    if(unget_ch >= 0)
440        return EOF;
441
442    unget_ch = ch;
443
444    return ch;
445}
446
447/** \brief DOS conio.h wherex() equivalent */
448int caca_conio_wherex(void)
449{
450    conio_init();
451
452    return caca_wherex(cv) + 1;
453}
454
455/** \brief DOS conio.h wherey() equivalent */
456int caca_conio_wherey(void)
457{
458    conio_init();
459
460    return caca_wherey(cv) + 1;
461}
462
463/** \brief DOS conio.h window() equivalent */
464void caca_conio_window(int left, int top, int right, int bottom)
465{
466    conio_init();
467
468    /* TODO: implement this function */
469}
470
471/* XXX: the following functions are local. */
472
473static void conio_init(void)
474{
475    if(!cv)
476        cv = caca_create_canvas(80, 25);
477    if(!dp)
478    {
479        dp = caca_create_display(cv);
480        caca_refresh_display(dp);
481        caca_set_cursor(dp, 1);
482        _caca_getticks(&refresh_timer);
483        refresh_ticks = 0;
484#if defined HAVE_ATEXIT
485        atexit(conio_fini);
486#endif
487    }
488}
489
490static void conio_refresh(void)
491{
492    refresh_ticks += _caca_getticks(&refresh_timer);
493    if(refresh_ticks > 10000)
494    {
495        caca_refresh_display(dp);
496        _caca_getticks(&refresh_timer);
497        refresh_ticks = 0;
498    }
499}
500
501static void conio_fini(void)
502{
503    caca_free_display(dp);
504    dp = NULL;
505    caca_free_canvas(cv);
506    cv = NULL;
507}
508
Note: See TracBrowser for help on using the repository browser.