You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 19 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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(__KERNEL__)
  20. # include <stdio.h> /* BUFSIZ */
  21. # include <string.h>
  22. # include <stdlib.h>
  23. # include <stdarg.h>
  24. # if defined(HAVE_UNISTD_H)
  25. # include <unistd.h>
  26. # endif
  27. # if defined(HAVE_SIGNAL_H)
  28. # include <signal.h>
  29. # endif
  30. # if defined(HAVE_SYS_IOCTL_H)
  31. # include <sys/ioctl.h>
  32. # endif
  33. #endif
  34. #include "cucul.h"
  35. #include "cucul_internals.h"
  36. /** \brief Set the default colour pair.
  37. *
  38. * This function sets the default colour pair. String functions such as
  39. * caca_printf() and graphical primitive functions such as caca_draw_line()
  40. * will use these colour pairs.
  41. *
  42. * \param fgcolor The requested foreground colour.
  43. * \param bgcolor The requested background colour.
  44. */
  45. void cucul_set_color(cucul_t *qq, enum cucul_color fgcolor,
  46. enum cucul_color bgcolor)
  47. {
  48. if(fgcolor < 0 || fgcolor > 15 || bgcolor < 0 || bgcolor > 15)
  49. return;
  50. qq->fgcolor = fgcolor;
  51. qq->bgcolor = bgcolor;
  52. }
  53. /** \brief Get the current foreground colour.
  54. *
  55. * This function returns the current foreground colour that was set with
  56. * cucul_set_color().
  57. *
  58. * \return The current foreground colour.
  59. */
  60. enum cucul_color cucul_get_fg_color(cucul_t *qq)
  61. {
  62. return qq->fgcolor;
  63. }
  64. /** \brief Get the current background colour.
  65. *
  66. * This function returns the current background colour that was set with
  67. * cucul_set_color().
  68. *
  69. * \return The current background colour.
  70. */
  71. enum cucul_color cucul_get_bg_color(cucul_t *qq)
  72. {
  73. return qq->bgcolor;
  74. }
  75. /** \brief Print an ASCII character.
  76. *
  77. * This function prints an ASCII character at the given coordinates, using
  78. * the default foreground and background values. If the coordinates are
  79. * outside the screen boundaries, nothing is printed. If the character
  80. * value is a non-printable character or is outside the ASCII range, it is
  81. * replaced with a space. To print a sequence of bytes forming an UTF-8
  82. * character, use cucul_putstr() instead.
  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. if((unsigned char)c < 0x20 || (unsigned char)c > 0x7f)
  94. c = 0x20;
  95. qq->chars[x + y * qq->width] = c;
  96. qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
  97. }
  98. /** \brief Print a Unicode character.
  99. *
  100. * FIXME: do we really want this function?
  101. *
  102. * This function prints a Unicode character (native-endian, 32 bits UCS-4,
  103. * also known as UTF-32) at the given coordinates, using the default
  104. * foreground and background values. If the coordinates are outside the
  105. * screen boundaries, nothing is printed. If the character is an invalid
  106. * Unicode character, it is replaced with a space.
  107. *
  108. * \param x X coordinate.
  109. * \param y Y coordinate.
  110. * \param c The character to print.
  111. */
  112. void cucul_putchar32(cucul_t *qq, int x, int y, unsigned long int c)
  113. {
  114. if(x < 0 || x >= (int)qq->width ||
  115. y < 0 || y >= (int)qq->height)
  116. return;
  117. if(c < 0x20 || c > 0x7f)
  118. c = 0x20;
  119. qq->chars[x + y * qq->width] = c;
  120. qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
  121. }
  122. /** \brief Print a string.
  123. *
  124. * This function prints an UTF-8 string at the given coordinates, using the
  125. * default foreground and background values. The coordinates may be outside
  126. * the screen boundaries (eg. a negative Y coordinate) and the string will
  127. * be cropped accordingly if it is too long.
  128. *
  129. * \param x X coordinate.
  130. * \param y Y coordinate.
  131. * \param s The string to print.
  132. */
  133. void cucul_putstr(cucul_t *qq, int x, int y, char const *s)
  134. {
  135. uint32_t *chars;
  136. uint8_t *attr;
  137. unsigned int len;
  138. if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
  139. return;
  140. len = _cucul_strlen_utf8(s);
  141. if(x < 0)
  142. {
  143. if(len < (unsigned int)-x)
  144. return;
  145. len -= -x;
  146. s = _cucul_skip_utf8(s, -x);
  147. x = 0;
  148. }
  149. chars = qq->chars + x + y * qq->width;
  150. attr = qq->attr + x + y * qq->width;
  151. if(x + len >= qq->width)
  152. len = qq->width - x;
  153. while(len)
  154. {
  155. *chars++ = _cucul_utf8_to_utf32(s);
  156. *attr++ = (qq->bgcolor << 4) | qq->fgcolor;
  157. s = _cucul_skip_utf8(s, 1);
  158. len--;
  159. }
  160. }
  161. /** \brief Format a string.
  162. *
  163. * This function formats a string at the given coordinates, using the
  164. * default foreground and background values. The coordinates may be outside
  165. * the screen boundaries (eg. a negative Y coordinate) and the string will
  166. * be cropped accordingly if it is too long. The syntax of the format
  167. * string is the same as for the C printf() function.
  168. *
  169. * \param x X coordinate.
  170. * \param y Y coordinate.
  171. * \param format The format string to print.
  172. * \param ... Arguments to the format string.
  173. */
  174. void cucul_printf(cucul_t *qq, int x, int y, char const *format, ...)
  175. {
  176. char tmp[BUFSIZ];
  177. char *buf = tmp;
  178. va_list args;
  179. if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
  180. return;
  181. if(qq->width - x + 1 > BUFSIZ)
  182. buf = malloc(qq->width - x + 1);
  183. va_start(args, format);
  184. #if defined(HAVE_VSNPRINTF)
  185. vsnprintf(buf, qq->width - x + 1, format, args);
  186. #else
  187. vsprintf(buf, format, args);
  188. #endif
  189. buf[qq->width - x] = '\0';
  190. va_end(args);
  191. cucul_putstr(qq, x, y, buf);
  192. if(buf != tmp)
  193. free(buf);
  194. }
  195. /** \brief Get the screen.
  196. *
  197. * This function fills a byte array with the character values.
  198. */
  199. void cucul_get_screen(cucul_t *qq, char *buffer)
  200. {
  201. unsigned int x, y;
  202. for(y = 0; y < qq->height; y++)
  203. {
  204. for(x = 0; x < qq->width; x++)
  205. {
  206. *buffer++ = qq->attr[x + y * qq->width];
  207. *buffer++ = qq->chars[x + y * qq->width] & 0x7f; /* FIXME: ASCII */
  208. }
  209. }
  210. }
  211. /** \brief Clear the screen.
  212. *
  213. * This function clears the screen using a black background.
  214. */
  215. void cucul_clear(cucul_t *qq)
  216. {
  217. enum cucul_color oldfg = cucul_get_fg_color(qq);
  218. enum cucul_color oldbg = cucul_get_bg_color(qq);
  219. int y = qq->height;
  220. cucul_set_color(qq, CUCUL_COLOR_LIGHTGRAY, CUCUL_COLOR_BLACK);
  221. /* We could use SLsmg_cls() etc., but drawing empty lines is much faster */
  222. while(y--)
  223. cucul_putstr(qq, 0, y, qq->empty_line);
  224. cucul_set_color(qq, oldfg, oldbg);
  225. }