* Use that in the SLang driver so that it supports UTF-8 input.tags/v0.99.beta14
| @@ -211,17 +211,16 @@ static void slang_display(caca_display_t *dp) | |||||
| uint32_t ch = *chars++; | uint32_t ch = *chars++; | ||||
| #if defined(OPTIMISE_SLANG_PALETTE) | #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 fgcolor = _cucul_argb32_to_ansi4fg(*attr); | ||||
| uint8_t bgcolor = _cucul_argb32_to_ansi4bg(*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) | if(fgcolor == CUCUL_COLOR_BLACK) | ||||
| fgcolor = CUCUL_COLOR_WHITE; | fgcolor = CUCUL_COLOR_WHITE; | ||||
| @@ -234,6 +233,12 @@ static void slang_display(caca_display_t *dp) | |||||
| SLsmg_write_char(' '); | SLsmg_write_char(' '); | ||||
| attr++; | attr++; | ||||
| } | } | ||||
| else | |||||
| #endif | |||||
| { | |||||
| SLsmg_set_color(slang_assoc[_cucul_argb32_to_ansi8(*attr++)]); | |||||
| slang_write_utf32(ch); | |||||
| } | |||||
| #else | #else | ||||
| SLsmg_set_color(_cucul_argb32_to_ansi8(*attr++)); | SLsmg_set_color(_cucul_argb32_to_ansi8(*attr++)); | ||||
| slang_write_utf32(ch); | slang_write_utf32(ch); | ||||
| @@ -285,6 +290,41 @@ static int slang_get_event(caca_display_t *dp, caca_event_t *ev) | |||||
| return 1; | 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) | if(intkey == 0x3e9) | ||||
| { | { | ||||
| int button = (SLang_getkey() - ' ' + 1) & 0xf; | 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(11): ev->data.key.ch = CACA_KEY_F11; break; | ||||
| case SL_KEY_F(12): ev->data.key.ch = CACA_KEY_F12; 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; | ev->type = CACA_EVENT_KEY_PRESS; | ||||
| @@ -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(x2 > xmax) x2 = xmax; | ||||
| if(y2 > ymax) y2 = ymax; | 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(y = y1; y <= y2; y++) | ||||
| for(x = x1; x <= x2; x++) | for(x = x1; x <= x2; x++) | ||||
| @@ -116,7 +116,7 @@ int cucul_putstr(cucul_canvas_t *cv, int x, int y, char const *s) | |||||
| while(len) | while(len) | ||||
| { | { | ||||
| *chars++ = cucul_utf8_to_utf32(s); | |||||
| *chars++ = cucul_utf8_to_utf32(s, NULL); | |||||
| *attr++ = (cv->bgcolor << 16) | cv->fgcolor; | *attr++ = (cv->bgcolor << 16) | cv->fgcolor; | ||||
| s = _cucul_skip_utf8(s, 1); | s = _cucul_skip_utf8(s, 1); | ||||
| @@ -95,31 +95,45 @@ static uint32_t const cp437_lookup2[] = | |||||
| /** \brief Convert a UTF-8 character to UTF-32. | /** \brief Convert a UTF-8 character to UTF-32. | ||||
| * | * | ||||
| * This function converts a UTF-8 character read from a string and returns | * 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 | * This function never fails, but its behaviour with illegal UTF-8 sequences | ||||
| * is undefined. | * is undefined. | ||||
| * | * | ||||
| * \param s A string containing the UTF-8 character. | * \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; | 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. | /** \brief Convert a UTF-32 character to UTF-8. | ||||
| @@ -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 cucul_draw_circle(cucul_canvas_t *cv, int x, int y, int r, char const *str) | ||||
| { | { | ||||
| int test, dx, dy; | 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. */ | /* Optimized Bresenham. Kick ass. */ | ||||
| for(test = 0, dx = 0, dy = r ; dx <= dy ; dx++) | 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 x = 0; | ||||
| int y = b; | int y = b; | ||||
| int d1 = b*b - (a*a*b) + (a*a/4); | 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); | ellipsepoints(cv, xo, yo, x, y, ch); | ||||
| @@ -123,7 +123,7 @@ int cucul_rotate(cucul_canvas_t *); | |||||
| * These functions perform conversions between usual character sets. | * 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 int cucul_utf32_to_utf8(char *, unsigned long int); | ||||
| extern unsigned char cucul_utf32_to_cp437(unsigned long int); | extern unsigned char cucul_utf32_to_cp437(unsigned long int); | ||||
| extern unsigned long int cucul_cp437_to_utf32(unsigned char); | extern unsigned long int cucul_cp437_to_utf32(unsigned char); | ||||
| @@ -61,7 +61,7 @@ int cucul_draw_line(cucul_canvas_t *cv, int x1, int y1, int x2, int y2, | |||||
| s.y1 = y1; | s.y1 = y1; | ||||
| s.x2 = x2; | s.x2 = x2; | ||||
| s.y2 = y2; | s.y2 = y2; | ||||
| s.ch = cucul_utf8_to_utf32(str); | |||||
| s.ch = cucul_utf8_to_utf32(str, NULL); | |||||
| s.draw = draw_solid_line; | s.draw = draw_solid_line; | ||||
| clip_line(cv, &s); | clip_line(cv, &s); | ||||
| @@ -89,7 +89,7 @@ int cucul_draw_polyline(cucul_canvas_t *cv, int const x[], int const y[], | |||||
| { | { | ||||
| int i; | int i; | ||||
| struct line s; | struct line s; | ||||
| s.ch = cucul_utf8_to_utf32(str); | |||||
| s.ch = cucul_utf8_to_utf32(str, NULL); | |||||
| s.draw = draw_solid_line; | s.draw = draw_solid_line; | ||||
| for(i = 0; i < n; i++) | for(i = 0; i < n; i++) | ||||
| @@ -109,7 +109,7 @@ int cucul_fill_triangle(cucul_canvas_t *cv, int x1, int y1, int x2, int y2, | |||||
| xmax = cv->width - 1; | xmax = cv->width - 1; | ||||
| ymax = cv->height - 1; | ymax = cv->height - 1; | ||||
| ch = cucul_utf8_to_utf32(str); | |||||
| ch = cucul_utf8_to_utf32(str, NULL); | |||||
| /* Rasterize our triangle */ | /* Rasterize our triangle */ | ||||
| for(y = y1 < 0 ? 0 : y1; y <= y3 && y <= ymax; y++) | for(y = y1 < 0 ? 0 : y1; y <= y3 && y <= ymax; y++) | ||||