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