src/video/windows/SDL_windowsmessagebox.c
changeset 6620 62fe18dc6841
child 6885 700f1b25f77f
equal deleted inserted replaced
6619:42214b6959c5 6620:62fe18dc6841
       
     1 /*
       
     2   Simple DirectMedia Layer
       
     3   Copyright (C) 1997-2012 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, which;
       
   235     const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
       
   236  
       
   237     /* FIXME: Need a better algorithm for laying out the message box */
       
   238 
       
   239     dialog = CreateDialogData(570, 260, messageboxdata->title);
       
   240     if (!dialog) {
       
   241         return -1;
       
   242     }
       
   243 
       
   244     w = 100;
       
   245     h = 25;
       
   246     gap = 10;
       
   247     x = gap;
       
   248     y = 50;
       
   249 
       
   250     if (!AddDialogStatic(dialog, x, y, 550, 100, messageboxdata->message)) {
       
   251         FreeDialogData(dialog);
       
   252         return -1;
       
   253     }
       
   254 
       
   255     y += 110;
       
   256 
       
   257     for (i = 0; i < messageboxdata->numbuttons; ++i) {
       
   258         SDL_bool isDefault;
       
   259 
       
   260         if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
       
   261             isDefault = SDL_TRUE;
       
   262         } else {
       
   263             isDefault = SDL_FALSE;
       
   264         }
       
   265         if (!AddDialogButton(dialog, x, y, w, h, buttons[i].text, i, isDefault)) {
       
   266             FreeDialogData(dialog);
       
   267             return -1;
       
   268         }
       
   269         x += w + gap;
       
   270     }
       
   271 
       
   272     /* FIXME: If we have a parent window, get the Instance and HWND for them */
       
   273     which = DialogBoxIndirect(NULL, dialog->lpDialog, NULL, (DLGPROC)MessageBoxDialogProc);
       
   274     *buttonid = buttons[which].buttonid;
       
   275 
       
   276     FreeDialogData(dialog);
       
   277     return 0;
       
   278 }
       
   279 
       
   280 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
       
   281 
       
   282 /* vi: set ts=4 sw=4 expandtab: */