diff options
author | Gary Wong <gtw@gnu.org> | 2009-09-03 09:54:20 -0600 |
---|---|---|
committer | Gary Wong <gtw@gnu.org> | 2009-09-03 09:54:20 -0600 |
commit | 34f65098ed115aaed51299fbb3cec631587743d0 (patch) | |
tree | 5d37dde9ddc4172c96efd20ade77c45876263fb0 | |
parent | 5508fa4a9733b8f6e382b3b98d8de0481ebceaef (diff) |
Clean up UTF-8 processing for core text, too.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | decorate-core.c | 117 |
2 files changed, 47 insertions, 75 deletions
@@ -1,3 +1,8 @@ +2009-09-03 Gary Wong <gtw@gnu.org> + + * decorate-core.c (core_text): Use utf8_next(). + (core_window_size): Use utf8_length(). + 2009-09-02 Gary Wong <gtw@gnu.org> * utf8.c (utf8_illegal, utf8_length, utf8_next) diff --git a/decorate-core.c b/decorate-core.c index c21325a..56ba206 100644 --- a/decorate-core.c +++ b/decorate-core.c @@ -34,6 +34,7 @@ #include "button.h" #include "decorate-core.h" #include "frame.h" +#include "utf8.h" #define FONT_SIZE 12 #define STRING2(x) #x @@ -55,81 +56,44 @@ static xcb_void_cookie_t core_text( xcb_drawable_t drawable, int screen, int i, len; const unsigned char *p; uint8_t *param, *out; - uint32_t n; - - if( !text || !*text ) { - xcb_void_cookie_t r = { 0 }; - - return r; - } - - n = gwm_screens[ screen ].pixels[ col ]; - xcb_change_gc( c, gcs[ screen ], XCB_GC_FOREGROUND, &n ); + uint32_t g, n; len = 0; - p = (const unsigned char *) text; - for(;;) - if( !p[ 0 ] ) - /* End of string. */ - break; - else if( !( p[ 0 ] & 0x80 ) ) { - /* Legal single byte character. */ - len++; - p++; - } else if( *p >= 0xC2 && *p <= 0xDF && - p[ 1 ] >= 0x80 && p[ 1 ] <= 0xBF ) { - /* Legal two byte character. */ - len++; - p += 2; - } else if( *p >= 0xE0 && *p <= 0xEF && - p[ 1 ] >= 0x80 && p[ 1 ] <= 0xBF && - p[ 2 ] >= 0x80 && p[ 2 ] <= 0xBF ) { - /* Legal three byte character. */ - len++; - p += 3; - } else - /* Illegal character, or a four byte character which lies outside - the BMP and so won't be included in a core font. Either way, - ignore this byte and continue. */ - p++; - - out = param = alloca( ( len + ( len >> 7 ) + 1 ) << 1 ); - - for( p = (const unsigned char *) text, i = 0; i < len; i++, out += 2 ) { - if( !( i & 0x7F ) ) { - out[ 0 ] = len - i > 0x7F ? 0x80 : len - i; /* length */ - out[ 1 ] = 0; /* delta */ - out += 2; - } + if( text ) { + p = (const unsigned char *) text; + while( ( g = utf8_next( &p ) ) ) + if( g < 0x10000 ) + len++; + } - retry: - assert( *p ); - - if( !( p[ 0 ] & 0x80 ) ) { - /* One byte character. */ - out[ 0 ] = 0; - out[ 1 ] = *p++; - } else if( *p >= 0xC2 && *p <= 0xDF && - p[ 1 ] >= 0x80 && p[ 1 ] <= 0xBF ) { - /* Two byte character. */ - out[ 0 ] = ( p[ 0 ] >> 2 ) & 0x07; - out[ 1 ] = ( ( p[ 0 ] & 3 ) << 6 ) | ( p[ 1 ] & 0x3F ); - p += 2; - } else if( *p >= 0xE0 && *p <= 0xEF && - p[ 1 ] >= 0x80 && p[ 1 ] <= 0xBF && - p[ 2 ] >= 0x80 && p[ 2 ] <= 0xBF ) { - /* Three byte character. */ - out[ 0 ] = ( ( p[ 0 ] & 0x0F ) << 4 ) | ( ( p[ 1 ] & 0x3C ) >> 2 ); - out[ 1 ] = ( ( p[ 1 ] & 3 ) << 6 ) | ( p[ 2 ] & 0x3F ); - p += 3; - } else { - p++; - goto retry; + if( len ) { + n = gwm_screens[ screen ].pixels[ col ]; + xcb_change_gc( c, gcs[ screen ], XCB_GC_FOREGROUND, &n ); + + out = param = alloca( ( len + ( len >> 7 ) + 1 ) << 1 ); + + for( p = (const unsigned char *) text, i = 0; i < len; + i++, out += 2 ) { + if( !( i & 0x7F ) ) { + out[ 0 ] = len - i > 0x7F ? 0x80 : len - i; /* length */ + out[ 1 ] = 0; /* delta */ + out += 2; + } + + while( assert( *p ), ( g = utf8_next( &p ) ) > 0xFFFF ) + ; + + out[ 0 ] = g >> 8; + out[ 1 ] = g & 0xFF; } + + return xcb_poly_text_16( c, drawable, gcs[ screen ], x, y, out - param, + param ); + } else { + xcb_void_cookie_t r = { 0 }; + + return r; } - - return xcb_poly_text_16( c, drawable, gcs[ screen ], x, y, - out - param, param ); } extern void core_update_window( struct gwm_window *window ) { @@ -184,11 +148,14 @@ extern void core_window_size( struct gwm_window *window, int *width, switch( window->type ) { case WINDOW_MENUITEM: - /* This is nasty. But then again, core fonts are fairly nasty... - this code is only here in case RENDER isn't available, so - hopefully it will never be used. */ - *width = FONT_SIZE << 4; - *height = FONT_SIZE + 4; + if( window->u.menuitem.label ) { + *width = FONT_SIZE * utf8_length( (const unsigned char *) + window->u.menuitem.label ); + *height = FONT_SIZE + 4; + } else { + *width = 8; + *height = 4; + } return; case WINDOW_FEEDBACK: |