1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2021 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_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_OS2
24 
25 /* Display a OS/2 message box */
26 
27 #include "SDL.h"
28 #include "../../core/os2/SDL_os2.h"
29 #include "SDL_os2video.h"
30 #define INCL_WIN
31 #include <os2.h>
32 
33 #define IDD_TEXT_MESSAGE    1001
34 #define IDD_BITMAP          1002
35 #define IDD_PB_FIRST        1003
36 
37 typedef struct _MSGBOXDLGDATA {
38     USHORT       cb;
39     HWND         hwndUnder;
40 } MSGBOXDLGDATA;
41 
_wmInitDlg(HWND hwnd,MSGBOXDLGDATA * pDlgData)42 static VOID _wmInitDlg(HWND hwnd, MSGBOXDLGDATA *pDlgData)
43 {
44     HPS     hps = WinGetPS(hwnd);
45     POINTL  aptText[TXTBOX_COUNT];
46     HENUM   hEnum;
47     HWND    hWndNext;
48     CHAR    acBuf[256];
49     ULONG   cbBuf;
50     ULONG   cButtons = 0;
51     ULONG   ulButtonsCY = 0;
52     ULONG   ulButtonsCX = 0;
53     RECTL   rectl;
54     ULONG   ulX;
55     ULONG   ulIdx;
56     struct _BUTTON {
57       HWND  hwnd;   /* Button window handle. */
58       ULONG ulCX;   /* Button width in dialog coordinates. */
59     } aButtons[32];
60     RECTL   rectlItem;
61     HAB     hab = WinQueryAnchorBlock(hwnd);
62 
63     /* --- Align the buttons to the right/bottom. --- */
64 
65     /* Collect window handles of all buttons in dialog. */
66     hEnum = WinBeginEnumWindows(hwnd);
67 
68     while ((hWndNext = WinGetNextWindow(hEnum)) != NULLHANDLE) {
69         if (WinQueryClassName(hWndNext, sizeof(acBuf), acBuf) == 0) {
70             continue;
71         }
72         if (SDL_strcmp(acBuf, "#3") == 0) { /* Class name of button. */
73             if (cButtons < sizeof(aButtons) / sizeof(struct _BUTTON)) {
74                 aButtons[cButtons].hwnd = hWndNext;
75                 cButtons++;
76             }
77         }
78     }
79     WinEndEnumWindows(hEnum);
80 
81     /* Query size of text for each button, get width of each button, total
82      * buttons width (ulButtonsCX) and max. height (ulButtonsCX) in _dialog
83      * coordinates_. */
84     hps = WinGetPS(hwnd);
85 
86     for(ulIdx = 0; ulIdx < cButtons; ulIdx++) {
87         /* Query size of text in window coordinates. */
88         cbBuf = WinQueryWindowText(aButtons[ulIdx].hwnd, sizeof(acBuf), acBuf);
89         GpiQueryTextBox(hps, cbBuf, acBuf, TXTBOX_COUNT, aptText);
90         aptText[TXTBOX_TOPRIGHT].x -= aptText[TXTBOX_BOTTOMLEFT].x;
91         aptText[TXTBOX_TOPRIGHT].y -= aptText[TXTBOX_BOTTOMLEFT].y;
92         /* Convert text size to dialog coordinates. */
93         WinMapDlgPoints(hwnd, &aptText[TXTBOX_TOPRIGHT], 1, FALSE);
94         /* Add vertical and horizontal space for button's frame (dialog coord.). */
95         if (aptText[TXTBOX_TOPRIGHT].x < 30) {          /* Minimal button width. */
96             aptText[TXTBOX_TOPRIGHT].x = 30;
97         } else {
98             aptText[TXTBOX_TOPRIGHT].x += 4;
99         }
100         aptText[TXTBOX_TOPRIGHT].y += 3;
101 
102         aButtons[ulIdx].ulCX = aptText[TXTBOX_TOPRIGHT].x; /* Store button width   */
103         ulButtonsCX += aptText[TXTBOX_TOPRIGHT].x + 2;     /* Add total btn. width */
104         /* Get max. height for buttons. */
105         if (ulButtonsCY < aptText[TXTBOX_TOPRIGHT].y)
106             ulButtonsCY = aptText[TXTBOX_TOPRIGHT].y + 1;
107     }
108 
109     WinReleasePS(hps);
110 
111     /* Expand horizontal size of the window to fit all buttons and move window
112      * to the center of parent window. */
113 
114     /* Convert total width of buttons to window coordinates. */
115     aptText[0].x = ulButtonsCX + 4;
116     WinMapDlgPoints(hwnd, &aptText[0], 1, TRUE);
117     /* Check width of the window and expand as needed. */
118     WinQueryWindowRect(hwnd, &rectlItem);
119     if (rectlItem.xRight <= aptText[0].x)
120         rectlItem.xRight = aptText[0].x;
121 
122     /* Move window rectangle to the center of owner window. */
123     WinQueryWindowRect(pDlgData->hwndUnder, &rectl);
124     /* Left-bottom point of centered dialog on owner window. */
125     rectl.xLeft = (rectl.xRight - rectlItem.xRight) / 2;
126     rectl.yBottom = (rectl.yTop - rectlItem.yTop) / 2;
127     /* Map left-bottom point to desktop. */
128     WinMapWindowPoints(pDlgData->hwndUnder, HWND_DESKTOP, (PPOINTL)&rectl, 1);
129     WinOffsetRect(hab, &rectlItem, rectl.xLeft, rectl.yBottom);
130 
131     /* Set new rectangle for the window. */
132     WinSetWindowPos(hwnd, HWND_TOP, rectlItem.xLeft, rectlItem.yBottom,
133                     rectlItem.xRight - rectlItem.xLeft,
134                     rectlItem.yTop - rectlItem.yBottom,
135                     SWP_SIZE | SWP_MOVE);
136 
137     /* Set buttons positions. */
138 
139     /* Get horizontal position for the first button. */
140     WinMapDlgPoints(hwnd, (PPOINTL)&rectlItem, 2, FALSE);       /* Win size to dlg coord. */
141     ulX = rectlItem.xRight - rectlItem.xLeft - ulButtonsCX - 2; /* First button position. */
142 
143     /* Set positions and sizes for all buttons. */
144     for (ulIdx = 0; ulIdx < cButtons; ulIdx++) {
145         /* Get poisition and size for the button in dialog coordinates. */
146         aptText[0].x = ulX;
147         aptText[0].y = 2;
148         aptText[1].x = aButtons[ulIdx].ulCX;
149         aptText[1].y = ulButtonsCY;
150         /* Convert to window coordinates. */
151         WinMapDlgPoints(hwnd, aptText, 2, TRUE);
152 
153         WinSetWindowPos(aButtons[ulIdx].hwnd, HWND_TOP,
154                         aptText[0].x, aptText[0].y, aptText[1].x, aptText[1].y,
155                         SWP_MOVE | SWP_SIZE);
156 
157         /* Offset horizontal position for the next button. */
158         ulX += aButtons[ulIdx].ulCX + 2;
159     }
160 
161     /* Set right bound of the text to right bound of the last button and
162      * bottom bound of the text just above the buttons. */
163 
164     aptText[2].x = 25;              /* Left bound of text in dlg coordinates.  */
165     aptText[2].y = ulButtonsCY + 3; /* Bottom bound of the text in dlg coords. */
166     WinMapDlgPoints(hwnd, &aptText[2], 1, TRUE); /* Convert ^^^ to win. coords */
167     hWndNext = WinWindowFromID(hwnd, IDD_TEXT_MESSAGE);
168     WinQueryWindowRect(hWndNext, &rectlItem);
169     rectlItem.xLeft = aptText[2].x;
170     rectlItem.yBottom = aptText[2].y;
171     /* Right bound of the text equals right bound of the last button. */
172     rectlItem.xRight = aptText[0].x + aptText[1].x;
173     WinSetWindowPos(hWndNext, HWND_TOP, rectlItem.xLeft, rectlItem.yBottom,
174                     rectlItem.xRight - rectlItem.xLeft,
175                     rectlItem.yTop - rectlItem.yBottom,
176                     SWP_MOVE | SWP_SIZE);
177 }
178 
DynDlgProc(HWND hwnd,USHORT message,MPARAM mp1,MPARAM mp2)179 static MRESULT EXPENTRY DynDlgProc(HWND hwnd, USHORT message, MPARAM mp1, MPARAM mp2)
180 {
181     switch (message) {
182     case WM_INITDLG:
183         _wmInitDlg(hwnd, (MSGBOXDLGDATA*)mp2);
184         break;
185 
186     case WM_COMMAND:
187         switch (SHORT1FROMMP(mp1)) {
188         case DID_OK:
189             WinDismissDlg(hwnd, FALSE);
190             break;
191         default:
192             break;
193         }
194 
195     default:
196         return(WinDefDlgProc(hwnd, message, mp1, mp2));
197     }
198 
199     return FALSE;
200 }
201 
_makeDlg(const SDL_MessageBoxData * messageboxdata)202 static HWND _makeDlg(const SDL_MessageBoxData *messageboxdata)
203 {
204     SDL_MessageBoxButtonData*
205         pSDLBtnData =  (SDL_MessageBoxButtonData *)messageboxdata->buttons;
206     ULONG               cSDLBtnData = messageboxdata->numbuttons;
207 
208     PSZ                 pszTitle = OS2_UTF8ToSys((PSZ) messageboxdata->title);
209     ULONG               cbTitle  = (pszTitle == NULL)? 1 : (SDL_strlen(pszTitle) + 1);
210     PSZ                 pszText  = OS2_UTF8ToSys((PSZ) messageboxdata->message);
211     ULONG               cbText   = (pszText  == NULL)? 1 : (SDL_strlen(pszText) + 1);
212 
213     PDLGTEMPLATE        pTemplate;
214     ULONG               cbTemplate;
215     ULONG               ulIdx;
216     PCHAR               pcDlgData;
217     PDLGTITEM           pDlgItem;
218     PSZ                 pszBtnText;
219     ULONG               cbBtnText;
220     HWND                hwnd;
221 
222     const SDL_MessageBoxColor* pSDLColors = (messageboxdata->colorScheme == NULL)?
223                                        NULL : messageboxdata->colorScheme->colors;
224     const SDL_MessageBoxColor* pSDLColor;
225 
226     MSGBOXDLGDATA       stDlgData;
227 
228     /* Build a dialog tamplate in memory */
229 
230     /* Size of template */
231     cbTemplate = sizeof(DLGTEMPLATE) + ((2 + cSDLBtnData) * sizeof(DLGTITEM)) +
232                  sizeof(ULONG) +  /* First item data - frame control data. */
233                  cbTitle       +  /* First item data - frame title + ZERO. */
234                  cbText        +  /* Second item data - ststic text + ZERO.*/
235                  3;               /* Third item data - system icon Id.     */
236 
237     /* Button items datas - text for buttons. */
238     for (ulIdx = 0; ulIdx < cSDLBtnData; ulIdx++) {
239         pszBtnText = (PSZ)pSDLBtnData[ulIdx].text;
240         cbTemplate += (pszBtnText == NULL)? 1 : (SDL_strlen(pszBtnText) + 1);
241     }
242 
243     /* Presentation parameter space. */
244     if (pSDLColors != NULL) {
245         cbTemplate += 26 /* PP for frame.       */ +
246                       26 /* PP for static text. */ +
247                      (48 * cSDLBtnData); /* PP for buttons. */
248     }
249 
250     /* Allocate memory for the dialog template. */
251     pTemplate = (PDLGTEMPLATE) SDL_malloc(cbTemplate);
252     /* Pointer on data for dialog items in allocated memory. */
253     pcDlgData = &((PCHAR)pTemplate)[sizeof(DLGTEMPLATE) +
254                                     ((2 + cSDLBtnData) * sizeof(DLGTITEM))];
255 
256     /* Header info */
257     pTemplate->cbTemplate = cbTemplate; /* size of dialog template to pass to WinCreateDlg() */
258     pTemplate->type = 0;                /* Currently always 0. */
259     pTemplate->codepage = 0;
260     pTemplate->offadlgti = 14;          /* Offset to array of DLGTITEMs. */
261     pTemplate->fsTemplateStatus = 0;    /* Reserved field?  */
262 
263     /* Index in array of dlg items of item to get focus,          */
264     /* if 0 then focus goes to first control that can have focus. */
265     pTemplate->iItemFocus = 0;
266     pTemplate->coffPresParams = 0;
267 
268     /* First item info - frame */
269     pDlgItem = pTemplate->adlgti;
270     pDlgItem->fsItemStatus = 0;  /* Reserved? */
271     /* Number of dialog item child windows owned by this item. */
272     pDlgItem->cChildren = 2 + cSDLBtnData; /* Ststic text + buttons. */
273     /* Length of class name, if 0 then offClassname contains a WC_ value. */
274     pDlgItem->cchClassName = 0;
275     pDlgItem->offClassName = (USHORT)WC_FRAME;
276     /* Length of text. */
277     pDlgItem->cchText = cbTitle;
278     pDlgItem->offText = pcDlgData - (PCHAR)pTemplate; /* Offset to title text.  */
279     /* Copy text for the title into the dialog template. */
280     if (pszTitle != NULL) {
281         SDL_memcpy(pcDlgData, pszTitle, cbTitle);
282     } else {
283         *pcDlgData = '\0';
284     }
285     pcDlgData += pDlgItem->cchText;
286 
287     pDlgItem->flStyle = WS_GROUP | WS_VISIBLE | WS_CLIPSIBLINGS |
288                         FS_DLGBORDER | WS_SAVEBITS;
289     pDlgItem->x  = 100;
290     pDlgItem->y  = 100;
291     pDlgItem->cx = 175;
292     pDlgItem->cy = 65;
293     pDlgItem->id = DID_OK; /* An ID value? */
294     if (pSDLColors == NULL)
295         pDlgItem->offPresParams = 0;
296     else {
297         /* Presentation parameter for the frame - dialog colors. */
298         pDlgItem->offPresParams = pcDlgData - (PCHAR)pTemplate;
299         ((PPRESPARAMS)pcDlgData)->cb = 22;
300         pcDlgData += 4;
301         ((PPARAM)pcDlgData)->id = PP_FOREGROUNDCOLOR;
302         ((PPARAM)pcDlgData)->cb = 3;
303         ((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].b;
304         ((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].g;
305         ((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].r;
306         pcDlgData += 11;
307         ((PPARAM)pcDlgData)->id = PP_BACKGROUNDCOLOR;
308         ((PPARAM)pcDlgData)->cb = 3;
309         ((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].b;
310         ((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].g;
311         ((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].r;
312         pcDlgData += 11;
313     }
314 
315     /* Offset to ctl data. */
316     pDlgItem->offCtlData = pcDlgData - (PCHAR)pTemplate;
317     /* Put CtlData for the dialog in here */
318     *((PULONG)pcDlgData) = FCF_TITLEBAR | FCF_SYSMENU;
319     pcDlgData += sizeof(ULONG);
320 
321     /* Second item info - static text (message). */
322     pDlgItem++;
323     pDlgItem->fsItemStatus = 0;
324     /* No children since its a control, it could have child control */
325     /* (ex. a group box).                                           */
326     pDlgItem->cChildren = 0;
327     /* Length of class name, 0 - offClassname contains a WC_ constant. */
328     pDlgItem->cchClassName = 0;
329     pDlgItem->offClassName = (USHORT)WC_STATIC;
330 
331     pDlgItem->cchText = cbText;
332     pDlgItem->offText = pcDlgData - (PCHAR)pTemplate;   /* Offset to the text. */
333     /* Copy message text into the dialog template. */
334     if (pszText != NULL) {
335         SDL_memcpy(pcDlgData, pszText, cbText);
336     } else {
337         *pcDlgData = '\0';
338     }
339     pcDlgData += pDlgItem->cchText;
340 
341     pDlgItem->flStyle = SS_TEXT | DT_TOP | DT_LEFT | DT_WORDBREAK | WS_VISIBLE;
342     /* It will be really set in _wmInitDlg(). */
343     pDlgItem->x = 25;
344     pDlgItem->y = 13;
345     pDlgItem->cx = 147;
346     pDlgItem->cy = 62;  /* It will be used. */
347 
348     pDlgItem->id = IDD_TEXT_MESSAGE;      /* an ID value */
349     if (pSDLColors == NULL)
350         pDlgItem->offPresParams = 0;
351     else {
352         /* Presentation parameter for the static text - dialog colors. */
353         pDlgItem->offPresParams = pcDlgData - (PCHAR)pTemplate;
354         ((PPRESPARAMS)pcDlgData)->cb = 22;
355         pcDlgData += 4;
356         ((PPARAM)pcDlgData)->id = PP_FOREGROUNDCOLOR;
357         ((PPARAM)pcDlgData)->cb = 3;
358         ((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].b;
359         ((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].g;
360         ((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].r;
361         pcDlgData += 11;
362         ((PPARAM)pcDlgData)->id = PP_BACKGROUNDCOLOR;
363         ((PPARAM)pcDlgData)->cb = 3;
364         ((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].b;
365         ((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].g;
366         ((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].r;
367         pcDlgData += 11;
368     }
369     pDlgItem->offCtlData = 0;
370 
371     /* Third item info - static bitmap. */
372     pDlgItem++;
373     pDlgItem->fsItemStatus = 0;
374     pDlgItem->cChildren = 0;
375     pDlgItem->cchClassName = 0;
376     pDlgItem->offClassName = (USHORT)WC_STATIC;
377 
378     pDlgItem->cchText = 3; /* 0xFF, low byte of the icon Id, high byte of icon Id. */
379     pDlgItem->offText = pcDlgData - (PCHAR)pTemplate;   /* Offset to the Id. */
380     /* Write susyem icon ID into dialog template. */
381     *pcDlgData = 0xFF; /* First byte is 0xFF - next 2 bytes is system pointer Id. */
382     pcDlgData++;
383     *((PUSHORT)pcDlgData) = ((messageboxdata->flags & SDL_MESSAGEBOX_ERROR) != 0)?
384                               SPTR_ICONERROR :
385                                 ((messageboxdata->flags & SDL_MESSAGEBOX_WARNING) != 0)?
386                                   SPTR_ICONWARNING : SPTR_ICONINFORMATION;
387     pcDlgData += 2;
388 
389     pDlgItem->flStyle = SS_SYSICON | WS_VISIBLE;
390 
391     pDlgItem->x = 4;
392     pDlgItem->y = 45; /* It will be really set in _wmInitDlg(). */
393     pDlgItem->cx = 0;
394     pDlgItem->cy = 0;
395 
396     pDlgItem->id = IDD_BITMAP;
397     pDlgItem->offPresParams = 0;
398     pDlgItem->offCtlData = 0;
399 
400     /* Next items - buttons. */
401     for (ulIdx = 0; ulIdx < cSDLBtnData; ulIdx++) {
402         pDlgItem++;
403 
404         pDlgItem->fsItemStatus = 0;
405         pDlgItem->cChildren = 0;     /* No children. */
406         pDlgItem->cchClassName = 0;  /* 0 - offClassname is WC_ constant. */
407         pDlgItem->offClassName = (USHORT)WC_BUTTON;
408 
409         pszBtnText = OS2_UTF8ToSys((PSZ)pSDLBtnData[ulIdx].text);
410         cbBtnText = (pszBtnText == NULL)? 1 : (SDL_strlen(pszBtnText) + 1);
411         pDlgItem->cchText = cbBtnText;
412         pDlgItem->offText = pcDlgData - (PCHAR)pTemplate; /* Offset to the text. */
413         /* Copy text for the button into the dialog template. */
414         if (pszBtnText != NULL) {
415             SDL_memcpy(pcDlgData, pszBtnText, cbBtnText);
416         } else {
417             *pcDlgData = '\0';
418         }
419         pcDlgData += pDlgItem->cchText;
420         SDL_free(pszBtnText);
421 
422         pDlgItem->flStyle = BS_PUSHBUTTON | WS_TABSTOP | WS_VISIBLE;
423         if (pSDLBtnData[ulIdx].flags == SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
424             pDlgItem->flStyle |= BS_DEFAULT;
425             pTemplate->iItemFocus = ulIdx + 3; /* +3 - frame, static text and icon. */
426             pSDLColor = &pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED];
427         } else {
428             pSDLColor = &pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT];
429         }
430 
431         /* It will be really set in _wmInitDlg() */
432         pDlgItem->x = 10;
433         pDlgItem->y = 10;
434         pDlgItem->cx = 70;
435         pDlgItem->cy = 15;
436 
437         pDlgItem->id = IDD_PB_FIRST + ulIdx;  /* an ID value */
438         if (pSDLColors == NULL)
439             pDlgItem->offPresParams = 0;
440         else {
441             /* Presentation parameter for the button - dialog colors. */
442             pDlgItem->offPresParams = pcDlgData - (PCHAR)pTemplate;
443             ((PPRESPARAMS)pcDlgData)->cb = 44;
444             pcDlgData += 4;
445             ((PPARAM)pcDlgData)->id = PP_FOREGROUNDCOLOR;
446             ((PPARAM)pcDlgData)->cb = 3;
447             ((PPARAM)pcDlgData)->ab[0] = pSDLColor->b;
448             ((PPARAM)pcDlgData)->ab[1] = pSDLColor->g;
449             ((PPARAM)pcDlgData)->ab[2] = pSDLColor->r;
450             pcDlgData += 11;
451             ((PPARAM)pcDlgData)->id = PP_BACKGROUNDCOLOR;
452             ((PPARAM)pcDlgData)->cb = 3;
453             ((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND].b;
454             ((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND].g;
455             ((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND].r;
456             pcDlgData += 11;
457             ((PPARAM)pcDlgData)->id = PP_BORDERLIGHTCOLOR;
458             ((PPARAM)pcDlgData)->cb = 3;
459             ((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].b;
460             ((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].g;
461             ((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].r;
462             pcDlgData += 11;
463             ((PPARAM)pcDlgData)->id = PP_BORDERDARKCOLOR;
464             ((PPARAM)pcDlgData)->cb = 3;
465             ((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].b;
466             ((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].g;
467             ((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].r;
468             pcDlgData += 11;
469         }
470         pDlgItem->offCtlData = 0;
471     }
472     /* Check, end of templ. data: &((PCHAR)pTemplate)[cbTemplate] == pcDlgData */
473 
474     /* Create the dialog from template. */
475     stDlgData.cb = sizeof(MSGBOXDLGDATA);
476     stDlgData.hwndUnder = (messageboxdata->window != NULL && messageboxdata->window->driverdata != NULL)?
477                             ((WINDATA *)messageboxdata->window->driverdata)->hwnd : HWND_DESKTOP;
478 
479     hwnd = WinCreateDlg(HWND_DESKTOP, /* Parent is desktop. */
480                         stDlgData.hwndUnder,
481                         (PFNWP)DynDlgProc, pTemplate, &stDlgData);
482     SDL_free(pTemplate);
483     SDL_free(pszTitle);
484     SDL_free(pszText);
485 
486     return hwnd;
487 }
488 
489 
OS2_ShowMessageBox(const SDL_MessageBoxData * messageboxdata,int * buttonid)490 int OS2_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
491 {
492     HWND    hwnd;
493     ULONG   ulRC;
494     SDL_MessageBoxButtonData
495             *pSDLBtnData = (SDL_MessageBoxButtonData *)messageboxdata->buttons;
496     ULONG   cSDLBtnData = messageboxdata->numbuttons;
497     BOOL    fVideoInitialized = SDL_WasInit(SDL_INIT_VIDEO);
498     HAB     hab;
499     HMQ     hmq;
500     BOOL    fSuccess = FALSE;
501 
502     if (!fVideoInitialized) {
503         PTIB    tib;
504         PPIB    pib;
505 
506         DosGetInfoBlocks(&tib, &pib);
507         if (pib->pib_ultype == 2 || pib->pib_ultype == 0) {
508             /* VIO windowable or fullscreen protect-mode session */
509             pib->pib_ultype = 3; /* Presentation Manager protect-mode session */
510         }
511 
512         hab = WinInitialize(0);
513         if (hab == NULLHANDLE) {
514             debug_os2("WinInitialize() failed");
515             return -1;
516         }
517         hmq = WinCreateMsgQueue(hab, 0);
518         if (hmq == NULLHANDLE) {
519             debug_os2("WinCreateMsgQueue() failed");
520             return -1;
521         }
522     }
523 
524     /* Create dynamic dialog. */
525     hwnd = _makeDlg(messageboxdata);
526     /* Show dialog and obtain button Id. */
527     ulRC = WinProcessDlg(hwnd);
528     /* Destroy dialog, */
529     WinDestroyWindow(hwnd);
530 
531     if (ulRC == DID_CANCEL) {
532         /* Window closed by ESC, Alt+F4 or system menu. */
533         ULONG   ulIdx;
534 
535         for (ulIdx = 0; ulIdx < cSDLBtnData; ulIdx++, pSDLBtnData++) {
536             if (pSDLBtnData->flags == SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
537                 *buttonid = pSDLBtnData->buttonid;
538                 fSuccess = TRUE;
539                 break;
540             }
541         }
542     } else {
543         /* Button pressed. */
544         ulRC -= IDD_PB_FIRST;
545         if (ulRC < cSDLBtnData) {
546             *buttonid = pSDLBtnData[ulRC].buttonid;
547             fSuccess = TRUE;
548         }
549     }
550 
551     if (!fVideoInitialized) {
552         WinDestroyMsgQueue(hmq);
553         WinTerminate(hab);
554     }
555 
556     return (fSuccess)? 0 : -1;
557 }
558 
559 #endif /* SDL_VIDEO_DRIVER_OS2 */
560 
561 /* vi: set ts=4 sw=4 expandtab: */
562