diff --git a/caca/driver_slang.c b/caca/driver_slang.c index c7a9d3a..016346d 100644 --- a/caca/driver_slang.c +++ b/caca/driver_slang.c @@ -211,17 +211,16 @@ static void slang_display(caca_display_t *dp) uint32_t ch = *chars++; #if defined(OPTIMISE_SLANG_PALETTE) + /* If foreground == background, just don't use this colour + * pair, and print a space instead of the real character. + * XXX: disabled, because I can't remember what it was + * here for, and in cases where SLang does not render + * bright backgrounds, it's just fucked up. */ +#if 0 uint8_t fgcolor = _cucul_argb32_to_ansi4fg(*attr); uint8_t bgcolor = _cucul_argb32_to_ansi4bg(*attr); - /* If foreground == background, just don't use this colour - * pair, and print a space instead of the real character. */ - if(fgcolor != bgcolor) - { - SLsmg_set_color(slang_assoc[_cucul_argb32_to_ansi8(*attr++)]); - slang_write_utf32(ch); - } - else + if(fgcolor == bgcolor) { if(fgcolor == CUCUL_COLOR_BLACK) fgcolor = CUCUL_COLOR_WHITE; @@ -234,6 +233,12 @@ static void slang_display(caca_display_t *dp) SLsmg_write_char(' '); attr++; } + else +#endif + { + SLsmg_set_color(slang_assoc[_cucul_argb32_to_ansi8(*attr++)]); + slang_write_utf32(ch); + } #else SLsmg_set_color(_cucul_argb32_to_ansi8(*attr++)); slang_write_utf32(ch); @@ -285,6 +290,41 @@ static int slang_get_event(caca_display_t *dp, caca_event_t *ev) return 1; } + /* If the key was UTF-8, parse the whole sequence */ + if(intkey >= 0x80 && intkey < 0x100) + { + int keys[7]; /* Necessary for ungetkey(); */ + char utf8[7]; + uint32_t utf32; + unsigned int i, bytes = 0; + + keys[0] = intkey; + utf8[0] = intkey; + + for(i = 1; i < 6; i++) + { + if(!SLang_input_pending(0)) + break; + keys[i] = SLang_getkey(); + utf8[i] = (unsigned char)keys[i]; + } + + utf8[i] = '\0'; + utf32 = cucul_utf8_to_utf32(utf8, &bytes); + + while(i > bytes) + SLang_ungetkey(keys[--i]); + + if(bytes) + { + ev->type = CACA_EVENT_KEY_PRESS; + ev->data.key.ch = 0; + ev->data.key.utf32 = utf32; + strcpy(ev->data.key.utf8, utf8); + return 1; + } + } + if(intkey == 0x3e9) { int button = (SLang_getkey() - ' ' + 1) & 0xf; @@ -338,7 +378,9 @@ static int slang_get_event(caca_display_t *dp, caca_event_t *ev) case SL_KEY_F(11): ev->data.key.ch = CACA_KEY_F11; break; case SL_KEY_F(12): ev->data.key.ch = CACA_KEY_F12; break; - default: ev->type = CACA_EVENT_NONE; return 0; + default: + /* Unknown key */ + ev->type = CACA_EVENT_NONE; return 0; } ev->type = CACA_EVENT_KEY_PRESS; diff --git a/cucul/box.c b/cucul/box.c index 6302a33..c2703dc 100644 --- a/cucul/box.c +++ b/cucul/box.c @@ -155,7 +155,7 @@ int cucul_fill_box(cucul_canvas_t *cv, int x1, int y1, int x2, int y2, if(x2 > xmax) x2 = xmax; if(y2 > ymax) y2 = ymax; - ch = cucul_utf8_to_utf32(str); + ch = cucul_utf8_to_utf32(str, NULL); for(y = y1; y <= y2; y++) for(x = x1; x <= x2; x++) diff --git a/cucul/canvas.c b/cucul/canvas.c index a43a229..012054c 100644 --- a/cucul/canvas.c +++ b/cucul/canvas.c @@ -116,7 +116,7 @@ int cucul_putstr(cucul_canvas_t *cv, int x, int y, char const *s) while(len) { - *chars++ = cucul_utf8_to_utf32(s); + *chars++ = cucul_utf8_to_utf32(s, NULL); *attr++ = (cv->bgcolor << 16) | cv->fgcolor; s = _cucul_skip_utf8(s, 1); diff --git a/cucul/charset.c b/cucul/charset.c index aae4ab8..b1a4958 100644 --- a/cucul/charset.c +++ b/cucul/charset.c @@ -95,31 +95,45 @@ static uint32_t const cp437_lookup2[] = /** \brief Convert a UTF-8 character to UTF-32. * * This function converts a UTF-8 character read from a string and returns - * its value in the UTF-32 character set. + * its value in the UTF-32 character set. If the second argument is not null, + * the total number of read bytes is written in it. + * + * If a null byte was reached before the expected end of the UTF-8 sequence, + * this function returns zero and the number of read bytes is set to zero. * * This function never fails, but its behaviour with illegal UTF-8 sequences * is undefined. * * \param s A string containing the UTF-8 character. - * \return The corresponding UTF-32 character. + * \param read A pointer to an unsigned integer to store the number of + * bytes in the character, or NULL. + * \return The corresponding UTF-32 character, or zero if the character + * is incomplete. */ -unsigned long int cucul_utf8_to_utf32(char const *s) +unsigned long int cucul_utf8_to_utf32(char const *s, unsigned int *read) { - int bytes = trailing[(int)(unsigned char)*s]; + unsigned int bytes = trailing[(int)(unsigned char)*s]; + unsigned int i = 0; uint32_t ret = 0; - switch(bytes) + for(;;) { - /* FIXME: do something for invalid sequences (4 and 5) */ - case 3: ret += (uint8_t)*s++; ret <<= 6; - case 2: ret += (uint8_t)*s++; ret <<= 6; - case 1: ret += (uint8_t)*s++; ret <<= 6; - case 0: ret += (uint8_t)*s++; + if(!*s) + { + if(read) + *read = 0; + return 0; + } + + ret += ((uint32_t)(unsigned char)*s++) << (6 * (bytes - i)); + + if(bytes == i++) + { + if(read) + *read = i; + return ret - offsets[bytes]; + } } - - ret -= offsets[bytes]; - - return ret; } /** \brief Convert a UTF-32 character to UTF-8. diff --git a/cucul/conic.c b/cucul/conic.c index 6ca7183..bc07719 100644 --- a/cucul/conic.c +++ b/cucul/conic.c @@ -43,7 +43,7 @@ static void ellipsepoints(cucul_canvas_t *, int, int, int, int, uint32_t); int cucul_draw_circle(cucul_canvas_t *cv, int x, int y, int r, char const *str) { int test, dx, dy; - uint32_t ch = cucul_utf8_to_utf32(str); + uint32_t ch = cucul_utf8_to_utf32(str, NULL); /* Optimized Bresenham. Kick ass. */ for(test = 0, dx = 0, dy = r ; dx <= dy ; dx++) @@ -138,7 +138,7 @@ int cucul_draw_ellipse(cucul_canvas_t *cv, int xo, int yo, int a, int b, int x = 0; int y = b; int d1 = b*b - (a*a*b) + (a*a/4); - uint32_t ch = cucul_utf8_to_utf32(str); + uint32_t ch = cucul_utf8_to_utf32(str, NULL); ellipsepoints(cv, xo, yo, x, y, ch); diff --git a/cucul/cucul.h b/cucul/cucul.h index e55f45e..2fed11d 100644 --- a/cucul/cucul.h +++ b/cucul/cucul.h @@ -123,7 +123,7 @@ int cucul_rotate(cucul_canvas_t *); * These functions perform conversions between usual character sets. * * @{ */ -extern unsigned long int cucul_utf8_to_utf32(char const *); +extern unsigned long int cucul_utf8_to_utf32(char const *, unsigned int *); extern unsigned int cucul_utf32_to_utf8(char *, unsigned long int); extern unsigned char cucul_utf32_to_cp437(unsigned long int); extern unsigned long int cucul_cp437_to_utf32(unsigned char); diff --git a/cucul/line.c b/cucul/line.c index 0e558d7..19c3782 100644 --- a/cucul/line.c +++ b/cucul/line.c @@ -61,7 +61,7 @@ int cucul_draw_line(cucul_canvas_t *cv, int x1, int y1, int x2, int y2, s.y1 = y1; s.x2 = x2; s.y2 = y2; - s.ch = cucul_utf8_to_utf32(str); + s.ch = cucul_utf8_to_utf32(str, NULL); s.draw = draw_solid_line; clip_line(cv, &s); @@ -89,7 +89,7 @@ int cucul_draw_polyline(cucul_canvas_t *cv, int const x[], int const y[], { int i; struct line s; - s.ch = cucul_utf8_to_utf32(str); + s.ch = cucul_utf8_to_utf32(str, NULL); s.draw = draw_solid_line; for(i = 0; i < n; i++) diff --git a/cucul/triangle.c b/cucul/triangle.c index 6e13a9d..6d787cb 100644 --- a/cucul/triangle.c +++ b/cucul/triangle.c @@ -109,7 +109,7 @@ int cucul_fill_triangle(cucul_canvas_t *cv, int x1, int y1, int x2, int y2, xmax = cv->width - 1; ymax = cv->height - 1; - ch = cucul_utf8_to_utf32(str); + ch = cucul_utf8_to_utf32(str, NULL); /* Rasterize our triangle */ for(y = y1 < 0 ? 0 : y1; y <= y3 && y <= ymax; y++)