Changeset 583 for libcaca/trunk


Ignore:
Timestamp:
Mar 10, 2006, 11:03:30 AM (15 years ago)
Author:
Sam Hocevar
Message:
  • Preliminary support for UTF-8 in cucul_putstr(). Also added a cucul_putchar32() function but I'm not convinced it will be useful.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/cucul/char.c

    r568 r583  
    3939#include "cucul_internals.h"
    4040
     41size_t utf8_strlen(const char *s);
     42const char *utf8_skip(const char *s, size_t x);
     43uint32_t utf8_to_utf32(const char *s);
     44
    4145/** \brief Set the default colour pair.
    4246 *
     
    8185}
    8286
    83 /** \brief Print a character.
    84  *
    85  *  This function prints a character at the given coordinates, using the
    86  *  default foreground and background values. If the coordinates are outside
    87  *  the screen boundaries, nothing is printed.
     87/** \brief Print an ASCII character.
     88 *
     89 *  This function prints an ASCII character at the given coordinates, using
     90 *  the default foreground and background values. If the coordinates are
     91 *  outside the screen boundaries, nothing is printed. If the character
     92 *  value is a non-printable character or is outside the ASCII range, it is
     93 *  replaced with a space. To print a sequence of bytes forming an UTF-8
     94 *  character, use cucul_putstr() instead.
    8895 *
    8996 *  \param x X coordinate.
     
    97104        return;
    98105
    99     qq->chars[x + y * qq->width] = c & 0x0000007f; /* FIXME: ASCII-only */
     106    if((unsigned char)c < 0x20 || (unsigned char)c > 0x7f)
     107        c = 0x20;
     108
     109    qq->chars[x + y * qq->width] = c;
    100110    qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
    101111}
    102112
     113/** \brief Print a Unicode character.
     114 *
     115 *  FIXME: do we really want this function?
     116 *
     117 *  This function prints a Unicode character (native-endian, 32 bits UCS-4,
     118 *  also known as UTF-32) at the given coordinates, using the default
     119 *  foreground and background values. If the coordinates are outside the
     120 *  screen boundaries, nothing is printed. If the character is an invalid
     121 *  Unicode character, it is replaced with a space.
     122 *
     123 *  \param x X coordinate.
     124 *  \param y Y coordinate.
     125 *  \param c The character to print.
     126 */
     127void cucul_putchar32(cucul_t *qq, int x, int y, unsigned long int c)
     128{
     129    if(x < 0 || x >= (int)qq->width ||
     130       y < 0 || y >= (int)qq->height)
     131        return;
     132
     133    if(c < 0x20 || c > 0x7f)
     134        c = 0x20;
     135
     136    qq->chars[x + y * qq->width] = c;
     137    qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
     138}
     139
    103140/** \brief Print a string.
    104141 *
    105  *  This function prints a string at the given coordinates, using the
     142 *  This function prints an UTF-8 string at the given coordinates, using the
    106143 *  default foreground and background values. The coordinates may be outside
    107144 *  the screen boundaries (eg. a negative Y coordinate) and the string will
     
    116153    uint32_t *chars;
    117154    uint8_t *attr;
    118     char const *t;
    119155    unsigned int len;
    120156
     
    122158        return;
    123159
    124     len = strlen(s);
     160    len = utf8_strlen(s);
    125161
    126162    if(x < 0)
     
    129165            return;
    130166        len -= -x;
    131         s += -x;
     167        s = utf8_skip(s, -x);
    132168        x = 0;
    133     }
    134 
    135     if(x + len >= qq->width)
    136     {
    137         len = qq->width - x;
    138         memcpy(qq->scratch_line, s, len);
    139         qq->scratch_line[len] = '\0';
    140         s = qq->scratch_line;
    141169    }
    142170
    143171    chars = qq->chars + x + y * qq->width;
    144172    attr = qq->attr + x + y * qq->width;
    145     t = s;
    146     while(*t)
    147     {
    148         *chars++ = *t++ & 0x0000007f; /* FIXME: ASCII-only */
     173
     174    if(x + len >= qq->width)
     175        len = qq->width - x;
     176
     177    while(len)
     178    {
     179        *chars++ = utf8_to_utf32(s);
    149180        *attr++ = (qq->bgcolor << 4) | qq->fgcolor;
     181
     182        s = utf8_skip(s, 1);
     183        len--;
    150184    }
    151185}
     
    228262}
    229263
     264/*
     265 * XXX: The following functions are local.
     266 */
     267
     268static const char trailing[256] =
     269{
     270    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     271    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     272    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     273    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     274    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     275    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     276    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
     277    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
     278};
     279
     280static const uint32_t offsets[6] =
     281{
     282    0x00000000UL, 0x00003080UL, 0x000E2080UL,
     283    0x03C82080UL, 0xFA082080UL, 0x82082080UL
     284};
     285
     286size_t utf8_strlen(const char *s)
     287{
     288    int len = 0;
     289    const char *parser = s;
     290
     291    while(*parser)
     292    {
     293        int i;
     294        int bytes = 1 + trailing[(int)(unsigned char)*parser];
     295
     296        for(i = 1; i < bytes; i++)
     297            if(!parser[i])
     298                return len;
     299        parser += bytes;
     300        len++;
     301    }
     302
     303    return len;
     304}
     305
     306const char *utf8_skip(const char *s, size_t x)
     307{
     308    const char *parser = s;
     309
     310    while(x)
     311    {
     312        int i;
     313        int bytes = 1 + trailing[(int)(unsigned char)*parser];
     314
     315        for(i = 1; i < bytes; i++)
     316            if(!parser[i])
     317                return parser;
     318        parser += bytes;
     319        x--;
     320    }
     321
     322    return parser;
     323}
     324
     325uint32_t utf8_to_utf32(const char *s)
     326{
     327    int bytes = trailing[(int)(unsigned char)*s];
     328    uint32_t ret = 0;
     329
     330    switch(bytes)
     331    {
     332        /* FIXME: do something for invalid sequences (4 and 5) */
     333        case 3: ret += (uint8_t)*s++; ret <<= 6;
     334        case 2: ret += (uint8_t)*s++; ret <<= 6;
     335        case 1: ret += (uint8_t)*s++; ret <<= 6;
     336        case 0: ret += (uint8_t)*s++;
     337    }
     338
     339    ret -= offsets[bytes];
     340
     341    return ret;
     342}
     343
Note: See TracChangeset for help on using the changeset viewer.