From 819dab40e7368ab3bc205f5fb943e7e8952b28b4 Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Fri, 10 Nov 2006 10:29:54 +0000
Subject: [PATCH]   * Implemented cucul_putattr(), cucul_putchar()'s attribute
 equivalent.

---
 cucul/Makefile.am          |  2 +-
 cucul/{colour.c => attr.c} | 55 ++++++++++++++++++++++++++++++++++++--
 cucul/cucul.h              |  1 +
 3 files changed, 55 insertions(+), 3 deletions(-)
 rename cucul/{colour.c => attr.c} (84%)

diff --git a/cucul/Makefile.am b/cucul/Makefile.am
index 8d3b354..e6c6da6 100644
--- a/cucul/Makefile.am
+++ b/cucul/Makefile.am
@@ -18,7 +18,7 @@ libcucul_la_SOURCES = \
 	canvas.c \
 	transform.c \
 	charset.c \
-	colour.c \
+	attr.c \
 	line.c \
 	box.c \
 	conic.c \
diff --git a/cucul/colour.c b/cucul/attr.c
similarity index 84%
rename from cucul/colour.c
rename to cucul/attr.c
index 4a41094..c1d2335 100644
--- a/cucul/colour.c
+++ b/cucul/attr.c
@@ -12,8 +12,8 @@
  */
 
 /*
- *  This file contains functions for converting colour values between
- *  various colourspaces.
+ *  This file contains functions for attribute management and colourspace
+ *  conversions.
  */
 
 #include "config.h"
@@ -101,6 +101,57 @@ int cucul_set_attr(cucul_canvas_t *cv, unsigned long int attr)
     return 0;
 }
 
+/** \brief Set the character attribute at the given coordinates.
+ *
+ *  Set the character attribute, without changing the character's value. If
+ *  the character at the given coordinates is a fullwidth character, both
+ *  cells' attributes are replaced.
+ *
+ *  The value of \e attr is either:
+ *  - a 32-bit integer as returned by cucul_get_attr(), in which case it
+ *    also contains colour information,
+ *  - a combination (bitwise OR) of style values (\e CUCUL_UNDERLINE,
+ *    \e CUCUL_BLINK, \e CUCUL_BOLD and \e CUCUL_ITALICS), in which case
+ *    setting the attribute does not modify the current colour information.
+ *
+ *  If an error occurs, -1 is returned and \b errno is set accordingly:
+ *  - \c EINVAL The attribute value is out of the 32-bit range.
+ *
+ *  \param cv A handle to the libcucul canvas.
+ *  \param x X coordinate.
+ *  \param y Y coordinate.
+ *  \param attr The requested attribute value.
+ *  \return 0 in case of success, -1 if an error occurred.
+ */
+int cucul_putattr(cucul_canvas_t *cv, int x, int y, unsigned long int attr)
+{
+    uint32_t *curattr, *curchar;
+
+    if(sizeof(unsigned long int) > sizeof(uint32_t) && attr > 0xffffffff)
+    {
+#if defined(HAVE_ERRNO_H)
+        errno = EINVAL;
+#endif
+        return -1;
+    }
+
+    if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
+        return 0;
+
+    curchar = cv->chars + x + y * cv->width;
+    curattr = cv->attrs + x + y * cv->width;
+
+    if(curattr[0] < 0x00000010)
+        curattr[0] = (cv->curattr & 0xfffffff0) | curattr[0];
+
+    if(x && curchar[0] == CUCUL_MAGIC_FULLWIDTH)
+        curattr[-1] = curattr[0];
+    else if(x + 1 < (int)cv->width && curchar[1] == CUCUL_MAGIC_FULLWIDTH)
+        curattr[1] = curattr[0];
+
+    return 0;
+}
+
 /** \brief Set the default colour pair for text (ANSI version).
  *
  *  Set the default ANSI colour pair for text drawing. String functions such
diff --git a/cucul/cucul.h b/cucul/cucul.h
index 36bc66c..1168055 100644
--- a/cucul/cucul.h
+++ b/cucul/cucul.h
@@ -91,6 +91,7 @@ int cucul_rand(int, int);
 #define CUCUL_MAGIC_FULLWIDTH 0x000ffffe /**< Used to indicate that the previous character was a fullwidth glyph. */
 unsigned long int cucul_get_attr(cucul_canvas_t *, int, int);
 int cucul_set_attr(cucul_canvas_t *, unsigned long int);
+int cucul_putattr(cucul_canvas_t *, int, int, unsigned long int);
 int cucul_set_color_ansi(cucul_canvas_t *, unsigned char, unsigned char);
 int cucul_set_color_argb(cucul_canvas_t *, unsigned int, unsigned int);
 int cucul_putchar(cucul_canvas_t *, int, int, unsigned long int);