X11 message boxes should work with UTF-8 strings if possible.

This commit is contained in:
Ryan C. Gordon 2012-12-07 20:00:42 -05:00
parent 60a837b5aa
commit 2c1f08ae4b
2 changed files with 91 additions and 40 deletions

View file

@ -18,6 +18,9 @@
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
/* !!! FIXME: clean up differences in coding style in this file. */
#include "SDL_config.h" #include "SDL_config.h"
#if SDL_VIDEO_DRIVER_X11 #if SDL_VIDEO_DRIVER_X11
@ -26,13 +29,16 @@
#include "SDL_x11video.h" #include "SDL_x11video.h"
#include "SDL_x11dyn.h" #include "SDL_x11dyn.h"
#include <locale.h>
#define MAX_BUTTONS 8 /* Maximum number of buttons supported */ #define MAX_BUTTONS 8 /* Maximum number of buttons supported */
#define MAX_TEXT_LINES 32 /* Maximum number of text lines supported */ #define MAX_TEXT_LINES 32 /* Maximum number of text lines supported */
#define MIN_BUTTON_WIDTH 64 /* Minimum button width */ #define MIN_BUTTON_WIDTH 64 /* Minimum button width */
#define MIN_DIALOG_WIDTH 200 /* Minimum dialog width */ #define MIN_DIALOG_WIDTH 200 /* Minimum dialog width */
#define MIN_DIALOG_HEIGHT 100 /* Minimum dialog height */ #define MIN_DIALOG_HEIGHT 100 /* Minimum dialog height */
static const char g_MessageBoxFont[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1"; static const char g_MessageBoxFontLatin1[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
static const char g_MessageBoxFont[] = "-*-*-*-*-*-*-*-*-*-*-*-*-*-*";
static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] = static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] =
{ {
@ -67,7 +73,8 @@ typedef struct TextLineData
typedef struct SDL_MessageBoxDataX11 typedef struct SDL_MessageBoxDataX11
{ {
Font hfont; XFontSet font_set; /* for UTF-8 systems */
XFontStruct *font_struct; /* Latin1 (ASCII) fallback. */
Window window; Window window;
Display *display; Display *display;
long event_mask; long event_mask;
@ -105,17 +112,22 @@ IntMax( int a, int b )
/* Return width and height for a string. */ /* Return width and height for a string. */
static void static void
GetTextWidthHeight( XFontStruct *font_struct, const char *str, int nchars, int *pwidth, int *pheight ) GetTextWidthHeight( SDL_MessageBoxDataX11 *data, const char *str, int nbytes, int *pwidth, int *pheight )
{ {
XCharStruct text_structure; if (SDL_X11_HAVE_UTF8) {
int font_direction, font_ascent, font_descent; XRectangle overall_ink, overall_logical;
Xutf8TextExtents(data->font_set, str, nbytes, &overall_ink, &overall_logical);
XTextExtents( font_struct, str, nchars, *pwidth = overall_logical.width;
&font_direction, &font_ascent, &font_descent, *pheight = overall_logical.height;
&text_structure ); } else {
XCharStruct text_structure;
*pwidth = text_structure.width; int font_direction, font_ascent, font_descent;
*pheight = text_structure.ascent + text_structure.descent; XTextExtents( data->font_struct, str, nbytes,
&font_direction, &font_ascent, &font_descent,
&text_structure );
*pwidth = text_structure.width;
*pheight = text_structure.ascent + text_structure.descent;
}
} }
/* Return index of button if position x,y is contained therein. */ /* Return index of button if position x,y is contained therein. */
@ -169,10 +181,24 @@ X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * mess
return -1; return -1;
} }
data->hfont = XLoadFont( data->display, g_MessageBoxFont ); if (SDL_X11_HAVE_UTF8) {
if ( data->hfont == None ) { char **missing = NULL;
SDL_SetError("Couldn't load font %s", g_MessageBoxFont); int num_missing = 0;
return -1; data->font_set = XCreateFontSet(data->display, g_MessageBoxFont,
&missing, &num_missing, NULL);
if ( missing != NULL ) {
XFreeStringList(missing);
}
if ( data->font_set == NULL ) {
SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
return -1;
}
} else {
data->font_struct = XLoadQueryFont( data->display, g_MessageBoxFontLatin1 );
if ( data->font_struct == NULL ) {
SDL_SetError("Couldn't load font %s", g_MessageBoxFontLatin1);
return -1;
}
} }
if ( messageboxdata->colorScheme ) { if ( messageboxdata->colorScheme ) {
@ -200,12 +226,6 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
int button_width = MIN_BUTTON_WIDTH; int button_width = MIN_BUTTON_WIDTH;
const SDL_MessageBoxData *messageboxdata = data->messageboxdata; const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
XFontStruct *fontinfo = XQueryFont( data->display, data->hfont );
if ( !fontinfo ) {
SDL_SetError("Couldn't get font info");
return -1;
}
/* Go over text and break linefeeds into separate lines. */ /* Go over text and break linefeeds into separate lines. */
if ( messageboxdata->message && messageboxdata->message[ 0 ] ) if ( messageboxdata->message && messageboxdata->message[ 0 ] )
{ {
@ -223,7 +243,7 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text ); plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text );
plinedata->text = text; plinedata->text = text;
GetTextWidthHeight( fontinfo, text, plinedata->length, &plinedata->width, &height ); GetTextWidthHeight( data, text, plinedata->length, &plinedata->width, &height );
/* Text and widths are the largest we've ever seen. */ /* Text and widths are the largest we've ever seen. */
data->text_height = IntMax( data->text_height, height ); data->text_height = IntMax( data->text_height, height );
@ -248,7 +268,7 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
data->buttonpos[ i ].buttondata = &data->buttondata[ i ]; data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text ); data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
GetTextWidthHeight( fontinfo, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ), GetTextWidthHeight( data, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
&data->buttonpos[ i ].text_width, &height ); &data->buttonpos[ i ].text_width, &height );
button_width = IntMax( button_width, data->buttonpos[ i ].text_width ); button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
@ -312,7 +332,6 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
} }
} }
XFreeFontInfo( NULL, fontinfo, 1 );
return 0; return 0;
} }
@ -320,10 +339,16 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
static void static void
X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data ) X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
{ {
if ( data->hfont != None ) if ( data->font_set != NULL )
{ {
XUnloadFont( data->display, data->hfont ); XFreeFontSet( data->display, data->font_set );
data->hfont = None; data->font_set = NULL;
}
if ( data->font_struct != NULL )
{
XFreeFont( data->display, data->font_struct );
data->font_struct = NULL;
} }
if ( data->display ) if ( data->display )
@ -434,9 +459,15 @@ X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
{ {
TextLineData *plinedata = &data->linedata[ i ]; TextLineData *plinedata = &data->linedata[ i ];
XDrawString( display, window, ctx, if (SDL_X11_HAVE_UTF8) {
data->xtext, data->ytext + i * data->text_height, Xutf8DrawString( display, window, data->font_set, ctx,
plinedata->text, plinedata->length ); data->xtext, data->ytext + i * data->text_height,
plinedata->text, plinedata->length );
} else {
XDrawString( display, window, ctx,
data->xtext, data->ytext + i * data->text_height,
plinedata->text, plinedata->length );
}
} }
for ( i = 0; i < data->numbuttons; i++ ) for ( i = 0; i < data->numbuttons; i++ )
@ -459,9 +490,17 @@ X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
XSetForeground( display, ctx, ( data->mouse_over_index == i ) ? XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] : data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] ); data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
XDrawString( display, window, ctx,
buttondatax11->x + offset, buttondatax11->y + offset, if (SDL_X11_HAVE_UTF8) {
buttondata->text, buttondatax11->length ); Xutf8DrawString( display, window, data->font_set, ctx,
buttondatax11->x + offset,
buttondatax11->y + offset,
buttondata->text, buttondatax11->length );
} else {
XDrawString( display, window, ctx,
buttondatax11->x + offset, buttondatax11->y + offset,
buttondata->text, buttondatax11->length );
}
} }
} }
@ -474,12 +513,18 @@ X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data )
SDL_bool close_dialog = SDL_FALSE; SDL_bool close_dialog = SDL_FALSE;
SDL_bool has_focus = SDL_TRUE; SDL_bool has_focus = SDL_TRUE;
KeySym last_key_pressed = XK_VoidSymbol; KeySym last_key_pressed = XK_VoidSymbol;
unsigned long gcflags = GCForeground | GCBackground;
ctx_vals.font = data->hfont; SDL_zero(ctx_vals);
ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ]; ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ]; ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
ctx = XCreateGC( data->display, data->window, GCForeground | GCBackground | GCFont, &ctx_vals ); if (!SDL_X11_HAVE_UTF8) {
gcflags |= GCFont;
ctx_vals.font = data->font_struct->fid;
}
ctx = XCreateGC( data->display, data->window, gcflags, &ctx_vals );
if ( ctx == None ) { if ( ctx == None ) {
SDL_SetError("Couldn't create graphics context"); SDL_SetError("Couldn't create graphics context");
return -1; return -1;
@ -610,7 +655,9 @@ X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
int ret; int ret;
SDL_MessageBoxDataX11 data; SDL_MessageBoxDataX11 data;
SDL_memset( &data, 0, sizeof( data ) ); SDL_zero(data);
setlocale(LC_ALL, "");
if ( !SDL_X11_LoadSymbols() ) if ( !SDL_X11_LoadSymbols() )
return -1; return -1;

View file

@ -37,6 +37,7 @@ SDL_X11_SYM(Pixmap,XCreateBitmapFromData,(Display *dpy,Drawable d,_Xconst char *
SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return) SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return)
SDL_X11_SYM(Cursor,XCreatePixmapCursor,(Display* a,Pixmap b,Pixmap c,XColor* d,XColor* e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return) SDL_X11_SYM(Cursor,XCreatePixmapCursor,(Display* a,Pixmap b,Pixmap c,XColor* d,XColor* e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return)
SDL_X11_SYM(Cursor,XCreateFontCursor,(Display* a,unsigned int b),(a,b),return) SDL_X11_SYM(Cursor,XCreateFontCursor,(Display* a,unsigned int b),(a,b),return)
SDL_X11_SYM(XFontSet,XCreateFontSet,(Display* a, _Xconst char* b, char*** c, int* d, char** e),(a,b,c,d,e),return)
SDL_X11_SYM(GC,XCreateGC,(Display* a,Drawable b,unsigned long c,XGCValues* d),(a,b,c,d),return) SDL_X11_SYM(GC,XCreateGC,(Display* a,Drawable b,unsigned long c,XGCValues* d),(a,b,c,d),return)
SDL_X11_SYM(XImage*,XCreateImage,(Display* a,Visual* b,unsigned int c,int d,int e,char* f,unsigned int g,unsigned int h,int i,int j),(a,b,c,d,e,f,g,h,i,j),return) SDL_X11_SYM(XImage*,XCreateImage,(Display* a,Visual* b,unsigned int c,int d,int e,char* f,unsigned int g,unsigned int h,int i,int j),(a,b,c,d,e,f,g,h,i,j),return)
SDL_X11_SYM(Window,XCreateWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l),(a,b,c,d,e,f,g,h,i,j,k,l),return) SDL_X11_SYM(Window,XCreateWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l),(a,b,c,d,e,f,g,h,i,j,k,l),return)
@ -53,10 +54,12 @@ SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event,Window w),(event,w),return)
SDL_X11_SYM(int,XFlush,(Display* a),(a),return) SDL_X11_SYM(int,XFlush,(Display* a),(a),return)
SDL_X11_SYM(int,XFree,(void*a),(a),return) SDL_X11_SYM(int,XFree,(void*a),(a),return)
SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return) SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return)
SDL_X11_SYM(void,XFreeFontSet,(Display* a, XFontSet b),(a,b),)
SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return) SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return)
SDL_X11_SYM(int,XFreeFontInfo,(char** a,XFontStruct* b,int c),(a,b,c),return) SDL_X11_SYM(int,XFreeFont,(Display* a, XFontStruct* b),(a,b),return)
SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return) SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return)
SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return) SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return)
SDL_X11_SYM(void,XFreeStringList,(char** a),(a),)
SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return) SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return)
SDL_X11_SYM(int,XGetInputFocus,(Display *a,Window *b,int *c),(a,b,c),return) SDL_X11_SYM(int,XGetInputFocus,(Display *a,Window *b,int *c),(a,b,c),return)
SDL_X11_SYM(int,XGetErrorDatabaseText,(Display* a,_Xconst char* b,_Xconst char* c,_Xconst char* d,char* e,int f),(a,b,c,d,e,f),return) SDL_X11_SYM(int,XGetErrorDatabaseText,(Display* a,_Xconst char* b,_Xconst char* c,_Xconst char* d,char* e,int f),(a,b,c,d,e,f),return)
@ -78,7 +81,7 @@ SDL_X11_SYM(char*,XKeysymToString,(KeySym a),(a),return)
SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return) SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return)
SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return) SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return)
SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return) SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return)
SDL_X11_SYM(Font,XLoadFont,(Display* a,_Xconst char* b),(a,b),return) SDL_X11_SYM(XFontStruct*,XLoadQueryFont,(Display* a,_Xconst char* b),(a,b),return)
SDL_X11_SYM(KeySym,XLookupKeysym,(XKeyEvent* a,int b),(a,b),return) SDL_X11_SYM(KeySym,XLookupKeysym,(XKeyEvent* a,int b),(a,b),return)
SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return) SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return)
SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return)
@ -91,7 +94,6 @@ SDL_X11_SYM(Status,XInitThreads,(void),(),return)
SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return) SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return)
SDL_X11_SYM(int,XPending,(Display* a),(a),return) SDL_X11_SYM(int,XPending,(Display* a),(a),return)
SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return) SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return)
SDL_X11_SYM(XFontStruct*,XQueryFont,(Display* a,XID b),(a,b),return)
SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return) SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return)
SDL_X11_SYM(Bool,XQueryPointer,(Display* a,Window b,Window* c,Window* d,int* e,int* f,int* g,int* h,unsigned int* i),(a,b,c,d,e,f,g,h,i),return) SDL_X11_SYM(Bool,XQueryPointer,(Display* a,Window b,Window* c,Window* d,int* e,int* f,int* g,int* h,unsigned int* i),(a,b,c,d,e,f,g,h,i),return)
SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return)
@ -181,6 +183,8 @@ SDL_X11_SYM(void,XSetICFocus,(XIC a),(a),)
SDL_X11_SYM(void,XUnsetICFocus,(XIC a),(a),) SDL_X11_SYM(void,XUnsetICFocus,(XIC a),(a),)
SDL_X11_SYM(XIM,XOpenIM,(Display* a,struct _XrmHashBucketRec* b,char* c,char* d),(a,b,c,d),return) SDL_X11_SYM(XIM,XOpenIM,(Display* a,struct _XrmHashBucketRec* b,char* c,char* d),(a,b,c,d),return)
SDL_X11_SYM(Status,XCloseIM,(XIM a),(a),return) SDL_X11_SYM(Status,XCloseIM,(XIM a),(a),return)
SDL_X11_SYM(void,Xutf8DrawString,(Display *a, Drawable b, XFontSet c, GC d, int e, int f, _Xconst char *g, int h),(a,b,c,d,e,f,g,h),)
SDL_X11_SYM(int,Xutf8TextExtents,(XFontSet a, _Xconst char* b, int c, XRectangle* d, XRectangle* e),(a,b,c,d,e),return)
#endif #endif
#ifndef NO_SHARED_MEMORY #ifndef NO_SHARED_MEMORY