Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

236 rader
5.9 KiB

  1. /*
  2. * libcucul Unicode canvas library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License, Version 2, as published by Sam Hocevar. See
  9. * http://sam.zoy.org/wtfpl/COPYING for more details.
  10. */
  11. /** \file char.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief Character drawing
  15. *
  16. * This file contains character and string drawing functions.
  17. */
  18. #include "config.h"
  19. #if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME)
  20. # include <inttypes.h>
  21. #else
  22. typedef unsigned int uint32_t;
  23. typedef unsigned char uint8_t;
  24. #endif
  25. #include <stdio.h> /* BUFSIZ */
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #if defined(HAVE_UNISTD_H)
  29. # include <unistd.h>
  30. #endif
  31. #include <stdarg.h>
  32. #if defined(HAVE_SIGNAL_H)
  33. # include <signal.h>
  34. #endif
  35. #if defined(HAVE_SYS_IOCTL_H)
  36. # include <sys/ioctl.h>
  37. #endif
  38. #include "cucul.h"
  39. #include "cucul_internals.h"
  40. /** \brief Set the default colour pair.
  41. *
  42. * This function sets the default colour pair. String functions such as
  43. * caca_printf() and graphical primitive functions such as caca_draw_line()
  44. * will use these colour pairs.
  45. *
  46. * \param fgcolor The requested foreground colour.
  47. * \param bgcolor The requested background colour.
  48. */
  49. void cucul_set_color(cucul_t *qq, enum cucul_color fgcolor, enum cucul_color bgcolor)
  50. {
  51. if(fgcolor < 0 || fgcolor > 15 || bgcolor < 0 || bgcolor > 15)
  52. return;
  53. qq->fgcolor = fgcolor;
  54. qq->bgcolor = bgcolor;
  55. }
  56. /** \brief Get the current foreground colour.
  57. *
  58. * This function returns the current foreground colour that was set with
  59. * cucul_set_color().
  60. *
  61. * \return The current foreground colour.
  62. */
  63. enum cucul_color cucul_get_fg_color(cucul_t *qq)
  64. {
  65. return qq->fgcolor;
  66. }
  67. /** \brief Get the current background colour.
  68. *
  69. * This function returns the current background colour that was set with
  70. * cucul_set_color().
  71. *
  72. * \return The current background colour.
  73. */
  74. enum cucul_color cucul_get_bg_color(cucul_t *qq)
  75. {
  76. return qq->bgcolor;
  77. }
  78. /** \brief Print a character.
  79. *
  80. * This function prints a character at the given coordinates, using the
  81. * default foreground and background values. If the coordinates are outside
  82. * the screen boundaries, nothing is printed.
  83. *
  84. * \param x X coordinate.
  85. * \param y Y coordinate.
  86. * \param c The character to print.
  87. */
  88. void cucul_putchar(cucul_t *qq, int x, int y, char c)
  89. {
  90. if(x < 0 || x >= (int)qq->width ||
  91. y < 0 || y >= (int)qq->height)
  92. return;
  93. qq->chars[x + y * qq->width] = c & 0x7f; /* FIXME: ASCII-only */
  94. qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
  95. }
  96. /** \brief Print a string.
  97. *
  98. * This function prints a string at the given coordinates, using the
  99. * default foreground and background values. The coordinates may be outside
  100. * the screen boundaries (eg. a negative Y coordinate) and the string will
  101. * be cropped accordingly if it is too long.
  102. *
  103. * \param x X coordinate.
  104. * \param y Y coordinate.
  105. * \param s The string to print.
  106. */
  107. void cucul_putstr(cucul_t *qq, int x, int y, char const *s)
  108. {
  109. uint32_t *chars;
  110. uint8_t *attr;
  111. char const *t;
  112. unsigned int len;
  113. if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
  114. return;
  115. len = strlen(s);
  116. if(x < 0)
  117. {
  118. if(len < (unsigned int)-x)
  119. return;
  120. len -= -x;
  121. s += -x;
  122. x = 0;
  123. }
  124. if(x + len >= qq->width)
  125. {
  126. len = qq->width - x;
  127. memcpy(qq->scratch_line, s, len);
  128. qq->scratch_line[len] = '\0';
  129. s = qq->scratch_line;
  130. }
  131. chars = qq->chars + x + y * qq->width;
  132. attr = qq->attr + x + y * qq->width;
  133. t = s;
  134. while(*t)
  135. {
  136. *chars++ = *t++ & 0x7f; /* FIXME: ASCII-only */
  137. *attr++ = (qq->bgcolor << 4) | qq->fgcolor;
  138. }
  139. }
  140. /** \brief Format a string.
  141. *
  142. * This function formats a string at the given coordinates, using the
  143. * default foreground and background values. The coordinates may be outside
  144. * the screen boundaries (eg. a negative Y coordinate) and the string will
  145. * be cropped accordingly if it is too long. The syntax of the format
  146. * string is the same as for the C printf() function.
  147. *
  148. * \param x X coordinate.
  149. * \param y Y coordinate.
  150. * \param format The format string to print.
  151. * \param ... Arguments to the format string.
  152. */
  153. void cucul_printf(cucul_t *qq, int x, int y, char const *format, ...)
  154. {
  155. char tmp[BUFSIZ];
  156. char *buf = tmp;
  157. va_list args;
  158. if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
  159. return;
  160. if(qq->width - x + 1 > BUFSIZ)
  161. buf = malloc(qq->width - x + 1);
  162. va_start(args, format);
  163. #if defined(HAVE_VSNPRINTF)
  164. vsnprintf(buf, qq->width - x + 1, format, args);
  165. #else
  166. vsprintf(buf, format, args);
  167. #endif
  168. buf[qq->width - x] = '\0';
  169. va_end(args);
  170. cucul_putstr(qq, x, y, buf);
  171. if(buf != tmp)
  172. free(buf);
  173. }
  174. /** \brief Get the screen.
  175. *
  176. * This function fills a byte array with the character values.
  177. */
  178. void cucul_get_screen(cucul_t *qq, char *buffer)
  179. {
  180. unsigned int x, y;
  181. for(y = 0; y < qq->height; y++)
  182. {
  183. for(x = 0; x < qq->width; x++)
  184. {
  185. *buffer++ = qq->attr[x + y * qq->width];
  186. *buffer++ = qq->chars[x + y * qq->width] & 0x7f; /* FIXME: ASCII */
  187. }
  188. }
  189. }
  190. /** \brief Clear the screen.
  191. *
  192. * This function clears the screen using a black background.
  193. */
  194. void cucul_clear(cucul_t *qq)
  195. {
  196. enum cucul_color oldfg = cucul_get_fg_color(qq);
  197. enum cucul_color oldbg = cucul_get_bg_color(qq);
  198. int y = qq->height;
  199. cucul_set_color(qq, CUCUL_COLOR_LIGHTGRAY, CUCUL_COLOR_BLACK);
  200. /* We could use SLsmg_cls() etc., but drawing empty lines is much faster */
  201. while(y--)
  202. cucul_putstr(qq, 0, y, qq->empty_line);
  203. cucul_set_color(qq, oldfg, oldbg);
  204. }