Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
X11 message boxes should work with UTF-8 strings if possible.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Dec 8, 2012
1 parent 90f4cb1 commit b824049
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 40 deletions.
121 changes: 84 additions & 37 deletions src/video/x11/SDL_x11messagebox.c
Expand Up @@ -18,6 +18,9 @@
misrepresented as being the original software.
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"

#if SDL_VIDEO_DRIVER_X11
Expand All @@ -26,13 +29,16 @@
#include "SDL_x11video.h"
#include "SDL_x11dyn.h"

#include <locale.h>

#define MAX_BUTTONS 8 /* Maximum number of buttons supported */
#define MAX_TEXT_LINES 32 /* Maximum number of text lines supported */
#define MIN_BUTTON_WIDTH 64 /* Minimum button width */
#define MIN_DIALOG_WIDTH 200 /* Minimum dialog width */
#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 ] =
{
Expand Down Expand Up @@ -67,7 +73,8 @@ typedef struct TextLineData

typedef struct SDL_MessageBoxDataX11
{
Font hfont;
XFontSet font_set; /* for UTF-8 systems */
XFontStruct *font_struct; /* Latin1 (ASCII) fallback. */
Window window;
Display *display;
long event_mask;
Expand Down Expand Up @@ -105,17 +112,22 @@ IntMax( int a, int b )

/* Return width and height for a string. */
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;
int font_direction, font_ascent, font_descent;

XTextExtents( font_struct, str, nchars,
&font_direction, &font_ascent, &font_descent,
&text_structure );

*pwidth = text_structure.width;
*pheight = text_structure.ascent + text_structure.descent;
if (SDL_X11_HAVE_UTF8) {
XRectangle overall_ink, overall_logical;
Xutf8TextExtents(data->font_set, str, nbytes, &overall_ink, &overall_logical);
*pwidth = overall_logical.width;
*pheight = overall_logical.height;
} else {
XCharStruct text_structure;
int font_direction, font_ascent, font_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. */
Expand Down Expand Up @@ -169,10 +181,24 @@ X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * mess
return -1;
}

data->hfont = XLoadFont( data->display, g_MessageBoxFont );
if ( data->hfont == None ) {
SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
return -1;
if (SDL_X11_HAVE_UTF8) {
char **missing = NULL;
int num_missing = 0;
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 ) {
Expand Down Expand Up @@ -200,12 +226,6 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
int button_width = MIN_BUTTON_WIDTH;
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. */
if ( messageboxdata->message && messageboxdata->message[ 0 ] )
{
Expand All @@ -223,7 +243,7 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( 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. */
data->text_height = IntMax( data->text_height, height );
Expand All @@ -248,7 +268,7 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
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 );

button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
Expand Down Expand Up @@ -312,18 +332,23 @@ X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
}
}

XFreeFontInfo( NULL, fontinfo, 1 );
return 0;
}

/* Free SDL_MessageBoxData data. */
static void
X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
{
if ( data->hfont != None )
if ( data->font_set != NULL )
{
XFreeFontSet( data->display, data->font_set );
data->font_set = NULL;
}

if ( data->font_struct != NULL )
{
XUnloadFont( data->display, data->hfont );
data->hfont = None;
XFreeFont( data->display, data->font_struct );
data->font_struct = NULL;
}

if ( data->display )
Expand Down Expand Up @@ -434,9 +459,15 @@ X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
{
TextLineData *plinedata = &data->linedata[ i ];

XDrawString( display, window, ctx,
data->xtext, data->ytext + i * data->text_height,
plinedata->text, plinedata->length );
if (SDL_X11_HAVE_UTF8) {
Xutf8DrawString( display, window, data->font_set, ctx,
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++ )
Expand All @@ -459,9 +490,17 @@ X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
XDrawString( display, window, ctx,
buttondatax11->x + offset, buttondatax11->y + offset,
buttondata->text, buttondatax11->length );

if (SDL_X11_HAVE_UTF8) {
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 );
}
}
}

Expand All @@ -474,12 +513,18 @@ X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data )
SDL_bool close_dialog = SDL_FALSE;
SDL_bool has_focus = SDL_TRUE;
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.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 ) {
SDL_SetError("Couldn't create graphics context");
return -1;
Expand Down Expand Up @@ -610,7 +655,9 @@ X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
int ret;
SDL_MessageBoxDataX11 data;

SDL_memset( &data, 0, sizeof( data ) );
SDL_zero(data);

setlocale(LC_ALL, "");

if ( !SDL_X11_LoadSymbols() )
return -1;
Expand Down
10 changes: 7 additions & 3 deletions src/video/x11/SDL_x11sym.h
Expand Up @@ -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(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(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(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)
Expand All @@ -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,XFree,(void*a),(a),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,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,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(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)
Expand All @@ -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(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(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(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)
Expand All @@ -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,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(XFontStruct*,XQueryFont,(Display* a,XID 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(int,XRaiseWindow,(Display* a,Window b),(a,b),return)
Expand Down Expand Up @@ -181,6 +183,8 @@ SDL_X11_SYM(void,XSetICFocus,(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(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

#ifndef NO_SHARED_MEMORY
Expand Down

0 comments on commit b824049

Please sign in to comment.