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