src/video/windows/SDL_windowsmessagebox.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 06 Mar 2013 11:59:19 -0800
changeset 6973 ae30ec97694a
parent 6885 700f1b25f77f
child 7028 55f2cc0a09d5
permissions -rw-r--r--
Fixed 64-bit compile warnings on Visual C++
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_WINDOWS
    24 
    25 #include "SDL.h"
    26 #include "SDL_windowsvideo.h"
    27 
    28 
    29 /* Display a Windows message box */
    30 
    31 typedef struct
    32 {
    33     LPDLGTEMPLATE lpDialog;
    34     Uint8 *data;
    35     size_t size;
    36     size_t used;
    37 } WIN_DialogData;
    38 
    39 
    40 static INT_PTR MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)
    41 {
    42     switch ( iMessage ) {
    43     case WM_COMMAND:
    44         /* Return the ID of the button that was pushed */
    45 		EndDialog(hDlg, LOWORD(wParam));
    46         return TRUE;
    47 
    48     default:
    49         break;
    50     }
    51     return FALSE;
    52 }
    53 
    54 static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog, size_t space)
    55 {
    56     size_t size = dialog->size;
    57 
    58     if (size == 0) {
    59         size = space;
    60     } else {
    61         while ((dialog->used + space) > size) {
    62             size *= 2;
    63         }
    64     }
    65     if (size > dialog->size) {
    66         void *data = SDL_realloc(dialog->data, size);
    67         if (!data) {
    68             SDL_OutOfMemory();
    69             return SDL_FALSE;
    70         }
    71         dialog->data = data;
    72         dialog->size = size;
    73         dialog->lpDialog = (LPDLGTEMPLATE)dialog->data;
    74     }
    75     return SDL_TRUE;
    76 }
    77  
    78 static SDL_bool AlignDialogData(WIN_DialogData *dialog, size_t size)
    79 {
    80     size_t padding = (dialog->used % size);
    81 
    82     if (!ExpandDialogSpace(dialog, padding)) {
    83         return SDL_FALSE;
    84     }
    85 
    86     dialog->used += padding;
    87 
    88     return SDL_TRUE;
    89 }
    90 
    91 static SDL_bool AddDialogData(WIN_DialogData *dialog, const void *data, size_t size)
    92 {
    93     if (!ExpandDialogSpace(dialog, size)) {
    94         return SDL_FALSE;
    95     }
    96 
    97     SDL_memcpy(dialog->data+dialog->used, data, size);
    98     dialog->used += size;
    99 
   100     return SDL_TRUE;
   101 }
   102 
   103 static SDL_bool AddDialogString(WIN_DialogData *dialog, const char *string)
   104 {
   105     WCHAR *wstring;
   106     WCHAR *p;
   107     size_t count;
   108     SDL_bool status;
   109 
   110     if (!string) {
   111         string = "";
   112     }
   113 
   114     wstring = WIN_UTF8ToString(string);
   115     if (!wstring) {
   116         return SDL_FALSE;
   117     }
   118 
   119     /* Find out how many characters we have, including null terminator */
   120     count = 0;
   121     for (p = wstring; *p; ++p) {
   122         ++count;
   123     }
   124     ++count;
   125 
   126     status = AddDialogData(dialog, wstring, count*sizeof(WCHAR));
   127     SDL_free(wstring);
   128     return status;
   129 }
   130 
   131 static SDL_bool AddDialogControl(WIN_DialogData *dialog, WORD type, DWORD style, DWORD exStyle, int x, int y, int w, int h, int id, const char *caption)
   132 {
   133     DLGITEMTEMPLATE item;
   134     WORD marker = 0xFFFF;
   135     WORD extraData = 0;
   136 
   137     SDL_zero(item);
   138     item.style = style;
   139     item.dwExtendedStyle = exStyle;
   140     item.x = x;
   141     item.y = y;
   142     item.cx = w;
   143     item.cy = h;
   144     item.id = id;
   145 
   146     if (!AlignDialogData(dialog, sizeof(DWORD))) {
   147         return SDL_FALSE;
   148     }
   149     if (!AddDialogData(dialog, &item, sizeof(item))) {
   150         return SDL_FALSE;
   151     }
   152     if (!AddDialogData(dialog, &marker, sizeof(marker))) {
   153         return SDL_FALSE;
   154     }
   155     if (!AddDialogData(dialog, &type, sizeof(type))) {
   156         return SDL_FALSE;
   157     }
   158     if (!AddDialogString(dialog, caption)) {
   159         return SDL_FALSE;
   160     }
   161     if (!AddDialogData(dialog, &extraData, sizeof(extraData))) {
   162         return SDL_FALSE;
   163     }
   164     ++dialog->lpDialog->cdit;
   165 
   166     return SDL_TRUE;
   167 }
   168 
   169 static SDL_bool AddDialogStatic(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text)
   170 {
   171     DWORD style = WS_VISIBLE | WS_CHILD | SS_LEFT | SS_NOPREFIX;
   172     return AddDialogControl(dialog, 0x0082, style, 0, x, y, w, h, -1, text);
   173 }
   174 
   175 static SDL_bool AddDialogButton(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text, int id, SDL_bool isDefault)
   176 {
   177     DWORD style = WS_VISIBLE | WS_CHILD;
   178     if (isDefault) {
   179         style |= BS_DEFPUSHBUTTON;
   180     } else {
   181         style |= BS_PUSHBUTTON;
   182     }
   183     return AddDialogControl(dialog, 0x0080, style, 0, x, y, w, h, id, text);
   184 }
   185 
   186 static void FreeDialogData(WIN_DialogData *dialog)
   187 {
   188     if (dialog->data) {
   189         SDL_free(dialog->data);
   190     }
   191     SDL_free(dialog);
   192 }
   193 
   194 static WIN_DialogData *CreateDialogData(int w, int h, const char *caption)
   195 {
   196     WIN_DialogData *dialog;
   197     DLGTEMPLATE dialogTemplate;
   198 
   199     SDL_zero(dialogTemplate);
   200     dialogTemplate.style = (WS_CAPTION | DS_CENTER);
   201     dialogTemplate.x = 0;
   202     dialogTemplate.y = 0;
   203     dialogTemplate.cx = w;
   204     dialogTemplate.cy = h;
   205 
   206     dialog = (WIN_DialogData *)SDL_calloc(1, sizeof(*dialog));
   207     if (!dialog) {
   208         return NULL;
   209     }
   210 
   211     if (!AddDialogData(dialog, &dialogTemplate, sizeof(dialogTemplate))) {
   212         FreeDialogData(dialog);
   213         return NULL;
   214     }
   215 
   216     /* There is no menu or special class */
   217     if (!AddDialogString(dialog, "") || !AddDialogString(dialog, "")) {
   218         FreeDialogData(dialog);
   219         return NULL;
   220     }
   221 
   222     if (!AddDialogString(dialog, caption)) {
   223         FreeDialogData(dialog);
   224         return NULL;
   225     }
   226 
   227     return dialog;
   228 }
   229 
   230 int
   231 WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   232 {
   233     WIN_DialogData *dialog;
   234     int i, x, y, w, h, gap;
   235     INT_PTR which;
   236     const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
   237  
   238     /* FIXME: Need a better algorithm for laying out the message box */
   239 
   240     dialog = CreateDialogData(570, 260, messageboxdata->title);
   241     if (!dialog) {
   242         return -1;
   243     }
   244 
   245     w = 100;
   246     h = 25;
   247     gap = 10;
   248     x = gap;
   249     y = 50;
   250 
   251     if (!AddDialogStatic(dialog, x, y, 550, 100, messageboxdata->message)) {
   252         FreeDialogData(dialog);
   253         return -1;
   254     }
   255 
   256     y += 110;
   257 
   258     for (i = 0; i < messageboxdata->numbuttons; ++i) {
   259         SDL_bool isDefault;
   260 
   261         if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
   262             isDefault = SDL_TRUE;
   263         } else {
   264             isDefault = SDL_FALSE;
   265         }
   266         if (!AddDialogButton(dialog, x, y, w, h, buttons[i].text, i, isDefault)) {
   267             FreeDialogData(dialog);
   268             return -1;
   269         }
   270         x += w + gap;
   271     }
   272 
   273     /* FIXME: If we have a parent window, get the Instance and HWND for them */
   274     which = DialogBoxIndirect(NULL, dialog->lpDialog, NULL, (DLGPROC)MessageBoxDialogProc);
   275     *buttonid = buttons[which].buttonid;
   276 
   277     FreeDialogData(dialog);
   278     return 0;
   279 }
   280 
   281 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   282 
   283 /* vi: set ts=4 sw=4 expandtab: */