source: libcaca/trunk/caca/graphics.c @ 2305

Last change on this file since 2305 was 2305, checked in by Sam Hocevar, 12 years ago
  • Remove all unsigned ints from exported functions. Signed arithmetic is far better for error checking.
  • Property svn:keywords set to Id
File size: 7.4 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: graphics.c 2305 2008-04-19 19:25:52Z 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 character and string drawing functions.
17 */
18
19#include "config.h"
20
21#if !defined(__KERNEL__)
22#   include <stdio.h>
23#   include <stdlib.h>
24#   include <string.h>
25#endif
26
27#include "cucul.h"
28#include "caca.h"
29#include "caca_internals.h"
30
31/** \brief Set the display title.
32 *
33 *  If libcaca runs in a window, try to change its title. This works with
34 *  the ncurses, S-Lang, OpenGL, X11 and Win32 drivers.
35 *
36 *  If an error occurs, -1 is returned and \b errno is set accordingly:
37 *  - \c ENOSYS Display driver does not support setting the window title.
38 *
39 *  \param dp The libcaca display context.
40 *  \param title The desired display title.
41 *  \return 0 upon success, -1 if an error occurred.
42 */
43int caca_set_display_title(caca_display_t *dp, char const *title)
44{
45    int ret = dp->drv.set_display_title(dp, title);
46
47    if(ret)
48        seterrno(ENOSYS);
49
50    return ret;
51}
52
53/** \brief Get the display width.
54 *
55 *  If libcaca runs in a window, get the usable window width. This value can
56 *  be used for aspect ratio calculation. If libcaca does not run in a window
57 *  or if there is no way to know the font size, most drivers will assume a
58 *  6x10 font is being used. Note that the units are not necessarily pixels.
59 *
60 *  This function never fails.
61 *
62 *  \param dp The libcaca display context.
63 *  \return The display width.
64 */
65int caca_get_display_width(caca_display_t const *dp)
66{
67    return dp->drv.get_display_width(dp);
68}
69
70/** \brief Get the display height.
71 *
72 *  If libcaca runs in a window, get the usable window height. This value can
73 *  be used for aspect ratio calculation. If libcaca does not run in a window
74 *  or if there is no way to know the font size, assume a 6x10 font is being
75 *  used. Note that the units are not necessarily pixels.
76 *
77 *  This function never fails.
78 *
79 *  \param dp The libcaca display context.
80 *  \return The display height.
81 */
82int caca_get_display_height(caca_display_t const *dp)
83{
84    return dp->drv.get_display_height(dp);
85}
86
87/** \brief Set the refresh delay.
88 *
89 *  Set the refresh delay in microseconds. The refresh delay is used by
90 *  caca_refresh_display() to achieve constant framerate. See the
91 *  caca_refresh_display() documentation for more details.
92 *
93 *  If the argument is zero, constant framerate is disabled. This is the
94 *  default behaviour.
95 *
96 *  If an error occurs, -1 is returned and \b errno is set accordingly:
97 *  - \c EINVAL Refresh delay value is invalid.
98 *
99 *  \param dp The libcaca display context.
100 *  \param usec The refresh delay in microseconds.
101 *  \return 0 upon success, -1 if an error occurred.
102 */
103int caca_set_display_time(caca_display_t *dp, int usec)
104{
105    if(usec < 0)
106    {
107        seterrno(EINVAL);
108        return -1;
109    }
110
111    dp->delay = usec;
112    return 0;
113}
114
115/** \brief Get the display's average rendering time.
116 *
117 *  Get the average rendering time, which is the average measured time
118 *  between two caca_refresh_display() calls, in microseconds. If constant
119 *  framerate was activated by calling caca_set_display_time(), the average
120 *  rendering time will be close to the requested delay even if the real
121 *  rendering time was shorter.
122 *
123 *  This function never fails.
124 *
125 *  \param dp The libcaca display context.
126 *  \return The render time in microseconds.
127 */
128int caca_get_display_time(caca_display_t const *dp)
129{
130    return dp->rendertime;
131}
132
133/** \brief Flush pending changes and redraw the screen.
134 *
135 *  Flush all graphical operations and print them to the display device.
136 *  Nothing will show on the screen until this function is called.
137 *
138 *  If caca_set_display_time() was called with a non-zero value,
139 *  caca_refresh_display() will use that value to achieve constant
140 *  framerate: if two consecutive calls to caca_refresh_display() are within
141 *  a time range shorter than the value set with caca_set_display_time(),
142 *  the second call will be delayed before performing the screen refresh.
143 *
144 *  This function never fails.
145 *
146 *  \param dp The libcaca display context.
147 *  \return This function always returns 0.
148 */
149int caca_refresh_display(caca_display_t *dp)
150{
151#if !defined(_DOXYGEN_SKIP_ME)
152#define IDLE_USEC 5000
153#endif
154    int ticks = dp->lastticks + _caca_getticks(&dp->timer);
155
156    dp->drv.display(dp);
157
158    /* Once the display is finished, we can ack resizes */
159    if(dp->resize.resized)
160    {
161        dp->resize.resized = 0;
162        _caca_handle_resize(dp);
163    }
164
165    /* Wait until dp->delay + time of last call */
166    ticks += _caca_getticks(&dp->timer);
167    for(ticks += _caca_getticks(&dp->timer);
168        ticks + IDLE_USEC < (int)dp->delay;
169        ticks += _caca_getticks(&dp->timer))
170    {
171        _caca_sleep(IDLE_USEC);
172    }
173
174    /* Update the sliding mean of the render time */
175    dp->rendertime = (7 * dp->rendertime + ticks) / 8;
176
177    dp->lastticks = ticks - dp->delay;
178
179    /* If we drifted too much, it's bad, bad, bad. */
180    if(dp->lastticks > (int)dp->delay)
181        dp->lastticks = 0;
182
183    return 0;
184}
185
186/** \brief Show or hide the cursor.
187 *
188 *  Show or hide the cursor, for devices that support such a feature.
189 *
190 *  If an error occurs, -1 is returned and \b errno is set accordingly:
191 *  - \c ENOSYS Display driver does not support showing the cursor.
192 *
193 *  \param dp The libcaca display context.
194 *  \param flag 0 hides the cursor, 1 shows the system's default cursor
195 *              (usually a white rectangle). Other values are reserved for
196 *              future use.
197 *  \return 0 upon success, -1 if an error occurred.
198 */
199int caca_set_cursor(caca_display_t *dp, int flag)
200{
201    if(!dp->drv.set_cursor)
202    {
203        seterrno(ENOSYS);
204        return -1;
205    }
206
207    dp->drv.set_cursor(dp, flag);
208    return 0;
209}
210
211/** \brief Show or hide the mouse pointer.
212 *
213 *  Show or hide the mouse pointer. This function works with the ncurses,
214 *  S-Lang and X11 drivers.
215 *
216 *  If an error occurs, -1 is returned and \b errno is set accordingly:
217 *  - \c ENOSYS Display driver does not support hiding the mouse pointer.
218 *
219 *  \param dp The libcaca display context.
220 *  \param flag 0 hides the pointer, 1 shows the system's default pointer
221 *              (usually an arrow). Other values are reserved for future use.
222 *  \return 0 upon success, -1 if an error occurred.
223 */
224int caca_set_mouse(caca_display_t *dp, int flag)
225{
226    if(!dp->drv.set_mouse)
227    {
228        seterrno(ENOSYS);
229        return -1;
230    }
231
232    dp->drv.set_mouse(dp, flag);
233    return 0;
234}
235
236/*
237 * XXX: following functions are local
238 */
239
240void _caca_handle_resize(caca_display_t *dp)
241{
242    dp->drv.handle_resize(dp);
243
244    /* Tell libcucul we changed size */
245    if(dp->resize.w != cucul_get_canvas_width(dp->cv)
246        || dp->resize.h != cucul_get_canvas_height(dp->cv))
247    {
248        dp->resize.allow = 1;
249        cucul_set_canvas_size(dp->cv, dp->resize.w, dp->resize.h);
250        dp->resize.allow = 0;
251    }
252}
253
254void _caca_set_term_title(char const *str)
255{
256#if defined(HAVE_GETENV)
257    char *term;
258
259    term = getenv("TERM");
260
261    if(!term || !strcmp(term, "linux"))
262        return;
263#endif
264
265    fprintf(stdout, "\x1b]0;%s\x07", str);
266    fflush(stdout);
267}
268
Note: See TracBrowser for help on using the repository browser.