src/video/x11/SDL_x11messagebox.c
changeset 6723 7c464a9ecf48
parent 6615 d7a463bde4d7
child 6724 6c5ed0c4cc6d
equal deleted inserted replaced
6722:37283d4416e0 6723:7c464a9ecf48
    16      appreciated but is not required.
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    20 */
       
    21 
       
    22 /* !!! FIXME: clean up differences in coding style in this file. */
       
    23 
    21 #include "SDL_config.h"
    24 #include "SDL_config.h"
    22 
    25 
    23 #if SDL_VIDEO_DRIVER_X11
    26 #if SDL_VIDEO_DRIVER_X11
    24 
    27 
    25 #include "SDL.h"
    28 #include "SDL.h"
    26 #include "SDL_x11video.h"
    29 #include "SDL_x11video.h"
    27 #include "SDL_x11dyn.h"
    30 #include "SDL_x11dyn.h"
       
    31 
       
    32 #include <locale.h>
    28 
    33 
    29 #define MAX_BUTTONS             8       /* Maximum number of buttons supported */
    34 #define MAX_BUTTONS             8       /* Maximum number of buttons supported */
    30 #define MAX_TEXT_LINES          32      /* Maximum number of text lines supported */
    35 #define MAX_TEXT_LINES          32      /* Maximum number of text lines supported */
    31 #define MIN_BUTTON_WIDTH        64      /* Minimum button width */
    36 #define MIN_BUTTON_WIDTH        64      /* Minimum button width */
    32 #define MIN_DIALOG_WIDTH        200     /* Minimum dialog width */
    37 #define MIN_DIALOG_WIDTH        200     /* Minimum dialog width */
    33 #define MIN_DIALOG_HEIGHT       100     /* Minimum dialog height */
    38 #define MIN_DIALOG_HEIGHT       100     /* Minimum dialog height */
    34 
    39 
    35 static const char g_MessageBoxFont[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
    40 static const char g_MessageBoxFontLatin1[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
       
    41 static const char g_MessageBoxFont[] = "-*-*-*-*-*-*-*-*-*-*-*-*-*-*";
    36 
    42 
    37 static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] =
    43 static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] =
    38 {
    44 {
    39     { 56,  54,  53  }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,       
    45     { 56,  54,  53  }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,       
    40     { 209, 207, 205 }, // SDL_MESSAGEBOX_COLOR_TEXT,             
    46     { 209, 207, 205 }, // SDL_MESSAGEBOX_COLOR_TEXT,             
    65     const char *text;                   /* Text for this line */
    71     const char *text;                   /* Text for this line */
    66 } TextLineData;
    72 } TextLineData;
    67 
    73 
    68 typedef struct SDL_MessageBoxDataX11
    74 typedef struct SDL_MessageBoxDataX11
    69 {
    75 {
    70     Font hfont;
    76     XFontSet font_set;                  /* for UTF-8 systems */
       
    77     XFontStruct *font_struct;            /* Latin1 (ASCII) fallback. */
    71     Window window;
    78     Window window;
    72     Display *display;
    79     Display *display;
    73     long event_mask;
    80     long event_mask;
    74     Atom wm_protocols;
    81     Atom wm_protocols;
    75     Atom wm_delete_message;
    82     Atom wm_delete_message;
   103     return ( a > b  ) ? a : b;
   110     return ( a > b  ) ? a : b;
   104 }
   111 }
   105 
   112 
   106 /* Return width and height for a string. */
   113 /* Return width and height for a string. */
   107 static void
   114 static void
   108 GetTextWidthHeight( XFontStruct *font_struct, const char *str, int nchars, int *pwidth, int *pheight )
   115 GetTextWidthHeight( SDL_MessageBoxDataX11 *data, const char *str, int nbytes, int *pwidth, int *pheight )
   109 {
   116 {
   110     XCharStruct text_structure;
   117     if (SDL_X11_HAVE_UTF8) {
   111     int font_direction, font_ascent, font_descent;
   118         XRectangle overall_ink, overall_logical;
   112 
   119         Xutf8TextExtents(data->font_set, str, nbytes, &overall_ink, &overall_logical);
   113     XTextExtents( font_struct, str, nchars,
   120         *pwidth = overall_logical.width;
   114                      &font_direction, &font_ascent, &font_descent,
   121         *pheight = overall_logical.height;
   115                      &text_structure );
   122     } else {
   116 
   123         XCharStruct text_structure;
   117     *pwidth = text_structure.width;
   124         int font_direction, font_ascent, font_descent;
   118     *pheight = text_structure.ascent + text_structure.descent;
   125         XTextExtents( data->font_struct, str, nbytes,
       
   126                       &font_direction, &font_ascent, &font_descent,
       
   127                       &text_structure );
       
   128         *pwidth = text_structure.width;
       
   129         *pheight = text_structure.ascent + text_structure.descent;
       
   130     }
   119 }
   131 }
   120 
   132 
   121 /* Return index of button if position x,y is contained therein. */
   133 /* Return index of button if position x,y is contained therein. */
   122 static int
   134 static int
   123 GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y )
   135 GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y )
   167     if ( !data->display ) {
   179     if ( !data->display ) {
   168         SDL_SetError("Couldn't open X11 display");
   180         SDL_SetError("Couldn't open X11 display");
   169         return -1;
   181         return -1;
   170     }
   182     }
   171 
   183 
   172     data->hfont = XLoadFont( data->display, g_MessageBoxFont );
   184     if (SDL_X11_HAVE_UTF8) {
   173     if ( data->hfont == None ) {
   185         char **missing = NULL;
   174         SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
   186         int num_missing = 0;
   175         return -1;
   187         data->font_set = XCreateFontSet(data->display, g_MessageBoxFont,
       
   188                                         &missing, &num_missing, NULL);
       
   189         if ( missing != NULL ) {
       
   190             XFreeStringList(missing);
       
   191         }
       
   192         if ( data->font_set == NULL ) {
       
   193             SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
       
   194             return -1;
       
   195         }
       
   196     } else {
       
   197         data->font_struct = XLoadQueryFont( data->display, g_MessageBoxFontLatin1 );
       
   198         if ( data->font_struct == NULL ) {
       
   199             SDL_SetError("Couldn't load font %s", g_MessageBoxFontLatin1);
       
   200             return -1;
       
   201         }
   176     }
   202     }
   177 
   203 
   178     if ( messageboxdata->colorScheme ) {
   204     if ( messageboxdata->colorScheme ) {
   179         colorhints = messageboxdata->colorScheme->colors;
   205         colorhints = messageboxdata->colorScheme->colors;
   180     } else {
   206     } else {
   198     int text_width_max = 0;
   224     int text_width_max = 0;
   199     int button_text_height = 0;
   225     int button_text_height = 0;
   200     int button_width = MIN_BUTTON_WIDTH;
   226     int button_width = MIN_BUTTON_WIDTH;
   201     const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
   227     const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
   202 
   228 
   203     XFontStruct *fontinfo = XQueryFont( data->display, data->hfont );
       
   204     if ( !fontinfo ) {
       
   205         SDL_SetError("Couldn't get font info");
       
   206         return -1;
       
   207     }
       
   208 
       
   209     /* Go over text and break linefeeds into separate lines. */
   229     /* Go over text and break linefeeds into separate lines. */
   210     if ( messageboxdata->message && messageboxdata->message[ 0 ] )
   230     if ( messageboxdata->message && messageboxdata->message[ 0 ] )
   211     {
   231     {
   212         const char *text = messageboxdata->message;
   232         const char *text = messageboxdata->message;
   213         TextLineData *plinedata = data->linedata;
   233         TextLineData *plinedata = data->linedata;
   221 
   241 
   222             /* Only grab length up to lf if it exists and isn't the last line. */
   242             /* Only grab length up to lf if it exists and isn't the last line. */
   223             plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text );
   243             plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text );
   224             plinedata->text = text;
   244             plinedata->text = text;
   225 
   245 
   226             GetTextWidthHeight( fontinfo, text, plinedata->length, &plinedata->width, &height );
   246             GetTextWidthHeight( data, text, plinedata->length, &plinedata->width, &height );
   227 
   247 
   228             /* Text and widths are the largest we've ever seen. */
   248             /* Text and widths are the largest we've ever seen. */
   229             data->text_height = IntMax( data->text_height, height );
   249             data->text_height = IntMax( data->text_height, height );
   230             text_width_max = IntMax( text_width_max, plinedata->width );
   250             text_width_max = IntMax( text_width_max, plinedata->width );
   231 
   251 
   246         int height;
   266         int height;
   247 
   267 
   248         data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
   268         data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
   249         data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
   269         data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
   250 
   270 
   251         GetTextWidthHeight( fontinfo, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
   271         GetTextWidthHeight( data, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
   252                             &data->buttonpos[ i ].text_width, &height );
   272                             &data->buttonpos[ i ].text_width, &height );
   253 
   273 
   254         button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
   274         button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
   255         button_text_height = IntMax( button_text_height, height );
   275         button_text_height = IntMax( button_text_height, height );
   256     }
   276     }
   310             /* Scoot over for next button. */
   330             /* Scoot over for next button. */
   311             x += button_width + button_spacing;
   331             x += button_width + button_spacing;
   312         }
   332         }
   313     }
   333     }
   314 
   334 
   315     XFreeFontInfo( NULL, fontinfo, 1 );
       
   316     return 0;
   335     return 0;
   317 }
   336 }
   318 
   337 
   319 /* Free SDL_MessageBoxData data. */
   338 /* Free SDL_MessageBoxData data. */
   320 static void
   339 static void
   321 X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
   340 X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
   322 {
   341 {
   323     if ( data->hfont != None )
   342     if ( data->font_set != NULL )
   324     {
   343     {
   325         XUnloadFont( data->display, data->hfont );
   344         XFreeFontSet( data->display, data->font_set );
   326         data->hfont = None;
   345         data->font_set = NULL;
       
   346     }
       
   347 
       
   348     if ( data->font_struct != NULL )
       
   349     {
       
   350         XFreeFont( data->display, data->font_struct );
       
   351         data->font_struct = NULL;
   327     }
   352     }
   328 
   353 
   329     if ( data->display )
   354     if ( data->display )
   330     {
   355     {
   331         if ( data->window != None )
   356         if ( data->window != None )
   432     XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   457     XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   433     for ( i = 0; i < data->numlines; i++ )
   458     for ( i = 0; i < data->numlines; i++ )
   434     {
   459     {
   435         TextLineData *plinedata = &data->linedata[ i ];
   460         TextLineData *plinedata = &data->linedata[ i ];
   436 
   461 
   437         XDrawString( display, window, ctx,
   462         if (SDL_X11_HAVE_UTF8) {
   438                      data->xtext, data->ytext + i * data->text_height,
   463             Xutf8DrawString( display, window, data->font_set, ctx,
   439                      plinedata->text, plinedata->length );
   464                              data->xtext, data->ytext + i * data->text_height,
       
   465                              plinedata->text, plinedata->length );
       
   466         } else {
       
   467             XDrawString( display, window, ctx,
       
   468                          data->xtext, data->ytext + i * data->text_height,
       
   469                          plinedata->text, plinedata->length );
       
   470         }
   440     }
   471     }
   441 
   472 
   442     for ( i = 0; i < data->numbuttons; i++ )
   473     for ( i = 0; i < data->numbuttons; i++ )
   443     {
   474     {
   444         SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
   475         SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
   457                         buttondatax11->rect.w, buttondatax11->rect.h );
   488                         buttondatax11->rect.w, buttondatax11->rect.h );
   458 
   489 
   459         XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
   490         XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
   460                         data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
   491                         data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
   461                         data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   492                         data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
   462         XDrawString( display, window, ctx,
   493 
   463             buttondatax11->x + offset, buttondatax11->y + offset,
   494         if (SDL_X11_HAVE_UTF8) {
   464             buttondata->text, buttondatax11->length );
   495             Xutf8DrawString( display, window, data->font_set, ctx,
       
   496                              buttondatax11->x + offset,
       
   497                              buttondatax11->y + offset,
       
   498                              buttondata->text, buttondatax11->length );
       
   499         } else {
       
   500             XDrawString( display, window, ctx,
       
   501                          buttondatax11->x + offset, buttondatax11->y + offset,
       
   502                          buttondata->text, buttondatax11->length );
       
   503         }
   465     }
   504     }
   466 }
   505 }
   467 
   506 
   468 /* Loop and handle message box event messages until something kills it. */
   507 /* Loop and handle message box event messages until something kills it. */
   469 static int
   508 static int
   472     GC ctx;
   511     GC ctx;
   473     XGCValues ctx_vals;
   512     XGCValues ctx_vals;
   474     SDL_bool close_dialog = SDL_FALSE;
   513     SDL_bool close_dialog = SDL_FALSE;
   475     SDL_bool has_focus = SDL_TRUE;
   514     SDL_bool has_focus = SDL_TRUE;
   476     KeySym last_key_pressed = XK_VoidSymbol;
   515     KeySym last_key_pressed = XK_VoidSymbol;
   477 
   516     unsigned long gcflags = GCForeground | GCBackground;
   478     ctx_vals.font = data->hfont;
   517 
       
   518     SDL_zero(ctx_vals);
   479     ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   519     ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   480     ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   520     ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
   481 
   521 
   482     ctx = XCreateGC( data->display, data->window, GCForeground | GCBackground | GCFont, &ctx_vals );
   522     if (!SDL_X11_HAVE_UTF8) {
       
   523         gcflags |= GCFont;
       
   524         ctx_vals.font = data->font_struct->fid;
       
   525     }
       
   526 
       
   527     ctx = XCreateGC( data->display, data->window, gcflags, &ctx_vals );
   483     if ( ctx == None ) {
   528     if ( ctx == None ) {
   484         SDL_SetError("Couldn't create graphics context");
   529         SDL_SetError("Couldn't create graphics context");
   485         return -1;
   530         return -1;
   486     }
   531     }
   487 
   532 
   608 X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   653 X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   609 {
   654 {
   610     int ret;
   655     int ret;
   611     SDL_MessageBoxDataX11 data;
   656     SDL_MessageBoxDataX11 data;
   612 
   657 
   613     SDL_memset( &data, 0, sizeof( data ) );
   658     SDL_zero(data);
       
   659 
       
   660     setlocale(LC_ALL, "");
   614 
   661 
   615     if ( !SDL_X11_LoadSymbols() )
   662     if ( !SDL_X11_LoadSymbols() )
   616         return -1;
   663         return -1;
   617 
   664 
   618     /* This code could get called from multiple threads maybe? */
   665     /* This code could get called from multiple threads maybe? */