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.
 
 
 
 
 
 

230 lines
5.8 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(__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, enum cucul_color bgcolor)
  46. {
  47. if(fgcolor < 0 || fgcolor > 15 || bgcolor < 0 || bgcolor > 15)
  48. return;
  49. qq->fgcolor = fgcolor;
  50. qq->bgcolor = bgcolor;
  51. }
  52. /** \brief Get the current foreground colour.
  53. *
  54. * This function returns the current foreground colour that was set with
  55. * cucul_set_color().
  56. *
  57. * \return The current foreground colour.
  58. */
  59. enum cucul_color cucul_get_fg_color(cucul_t *qq)
  60. {
  61. return qq->fgcolor;
  62. }
  63. /** \brief Get the current background colour.
  64. *
  65. * This function returns the current background colour that was set with
  66. * cucul_set_color().
  67. *
  68. * \return The current background colour.
  69. */
  70. enum cucul_color cucul_get_bg_color(cucul_t *qq)
  71. {
  72. return qq->bgcolor;
  73. }
  74. /** \brief Print a character.
  75. *
  76. * This function prints a character at the given coordinates, using the
  77. * default foreground and background values. If the coordinates are outside
  78. * the screen boundaries, nothing is printed.
  79. *
  80. * \param x X coordinate.
  81. * \param y Y coordinate.
  82. * \param c The character to print.
  83. */
  84. void cucul_putchar(cucul_t *qq, int x, int y, char c)
  85. {
  86. if(x < 0 || x >= (int)qq->width ||
  87. y < 0 || y >= (int)qq->height)
  88. return;
  89. qq->chars[x + y * qq->width] = c & 0x0000007f; /* FIXME: ASCII-only */
  90. qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
  91. }
  92. /** \brief Print a string.
  93. *
  94. * This function prints a string at the given coordinates, using the
  95. * default foreground and background values. The coordinates may be outside
  96. * the screen boundaries (eg. a negative Y coordinate) and the string will
  97. * be cropped accordingly if it is too long.
  98. *
  99. * \param x X coordinate.
  100. * \param y Y coordinate.
  101. * \param s The string to print.
  102. */
  103. void cucul_putstr(cucul_t *qq, int x, int y, char const *s)
  104. {
  105. uint32_t *chars;
  106. uint8_t *attr;
  107. char const *t;
  108. unsigned int len;
  109. if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
  110. return;
  111. len = strlen(s);
  112. if(x < 0)
  113. {
  114. if(len < (unsigned int)-x)
  115. return;
  116. len -= -x;
  117. s += -x;
  118. x = 0;
  119. }
  120. if(x + len >= qq->width)
  121. {
  122. len = qq->width - x;
  123. memcpy(qq->scratch_line, s, len);
  124. qq->scratch_line[len] = '\0';
  125. s = qq->scratch_line;
  126. }
  127. chars = qq->chars + x + y * qq->width;
  128. attr = qq->attr + x + y * qq->width;
  129. t = s;
  130. while(*t)
  131. {
  132. *chars++ = *t++ & 0x0000007f; /* FIXME: ASCII-only */
  133. *attr++ = (qq->bgcolor << 4) | qq->fgcolor;
  134. }
  135. }
  136. /** \brief Format a string.
  137. *
  138. * This function formats a string at the given coordinates, using the
  139. * default foreground and background values. The coordinates may be outside
  140. * the screen boundaries (eg. a negative Y coordinate) and the string will
  141. * be cropped accordingly if it is too long. The syntax of the format
  142. * string is the same as for the C printf() function.
  143. *
  144. * \param x X coordinate.
  145. * \param y Y coordinate.
  146. * \param format The format string to print.
  147. * \param ... Arguments to the format string.
  148. */
  149. void cucul_printf(cucul_t *qq, int x, int y, char const *format, ...)
  150. {
  151. char tmp[BUFSIZ];
  152. char *buf = tmp;
  153. va_list args;
  154. if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
  155. return;
  156. if(qq->width - x + 1 > BUFSIZ)
  157. buf = malloc(qq->width - x + 1);
  158. va_start(args, format);
  159. #if defined(HAVE_VSNPRINTF)
  160. vsnprintf(buf, qq->width - x + 1, format, args);
  161. #else
  162. vsprintf(buf, format, args);
  163. #endif
  164. buf[qq->width - x] = '\0';
  165. va_end(args);
  166. cucul_putstr(qq, x, y, buf);
  167. if(buf != tmp)
  168. free(buf);
  169. }
  170. /** \brief Get the screen.
  171. *
  172. * This function fills a byte array with the character values.
  173. */
  174. void cucul_get_screen(cucul_t *qq, char *buffer)
  175. {
  176. unsigned int x, y;
  177. for(y = 0; y < qq->height; y++)
  178. {
  179. for(x = 0; x < qq->width; x++)
  180. {
  181. *buffer++ = qq->attr[x + y * qq->width];
  182. *buffer++ = qq->chars[x + y * qq->width] & 0x7f; /* FIXME: ASCII */
  183. }
  184. }
  185. }
  186. /** \brief Clear the screen.
  187. *
  188. * This function clears the screen using a black background.
  189. */
  190. void cucul_clear(cucul_t *qq)
  191. {
  192. enum cucul_color oldfg = cucul_get_fg_color(qq);
  193. enum cucul_color oldbg = cucul_get_bg_color(qq);
  194. int y = qq->height;
  195. cucul_set_color(qq, CUCUL_COLOR_LIGHTGRAY, CUCUL_COLOR_BLACK);
  196. /* We could use SLsmg_cls() etc., but drawing empty lines is much faster */
  197. while(y--)
  198. cucul_putstr(qq, 0, y, qq->empty_line);
  199. cucul_set_color(qq, oldfg, oldbg);
  200. }