21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_WINDOWS
29 #define SIZE_MAX ((size_t)-1)
32 #include "../../core/windows/SDL_windows.h"
37 #ifndef SS_EDITCONTROL
38 #define SS_EDITCONTROL 0x2000
51 #define IDINVALPTRINIT 50
52 #define IDINVALPTRCOMMAND 51
53 #define IDINVALPTRSETFOCUS 52
54 #define IDINVALPTRDLGITEM 53
56 #define IDBUTTONINDEX0 100
58 #define DLGITEMTYPEBUTTON 0x0080
59 #define DLGITEMTYPESTATIC 0x0082
66 #define MAX_BUTTONS (0xffff - 100)
103 DLGTEMPLATEEX* lpDialog;
120 static INT_PTR MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)
125 switch ( iMessage ) {
128 EndDialog(hDlg, IDINVALPTRINIT);
132 SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
136 HWND buttonctl = GetDlgItem(hDlg, (
int)(IDBUTTONINDEX0 + buttonindex));
137 if (buttonctl ==
NULL) {
138 EndDialog(hDlg, IDINVALPTRDLGITEM);
140 PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)buttonctl,
TRUE);
148 if (messageboxdata ==
NULL) {
149 EndDialog(hDlg, IDINVALPTRSETFOCUS);
160 if (messageboxdata ==
NULL) {
161 EndDialog(hDlg, IDINVALPTRCOMMAND);
166 if (wParam == IDOK) {
168 EndDialog(hDlg, IDBUTTONINDEX0 + buttonindex);
170 }
else if (wParam == IDCANCEL) {
172 EndDialog(hDlg, IDBUTTONINDEX0 + buttonindex);
175 EndDialog(hDlg, IDCLOSED);
177 }
else if (wParam >= IDBUTTONINDEX0 && (
int)wParam - IDBUTTONINDEX0 < messageboxdata->numbuttons) {
178 EndDialog(hDlg, wParam);
188 static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog,
size_t space)
191 const size_t sizestep = 0x10000;
192 size_t size = dialog->size;
199 }
else if (space >
size) {
200 size = (space + sizestep) & ~(sizestep - 1);
202 }
else if (
SIZE_MAX - dialog->used < space) {
205 }
else if (
SIZE_MAX - (dialog->used + space) < sizestep) {
207 size = dialog->used + space;
210 size = dialog->used + space;
214 if (
size > dialog->size) {
222 dialog->lpDialog = (DLGTEMPLATEEX*)dialog->data;
227 static SDL_bool AlignDialogData(WIN_DialogData *dialog,
size_t size)
229 size_t padding = (dialog->used %
size);
231 if (!ExpandDialogSpace(dialog, padding)) {
235 dialog->used += padding;
240 static SDL_bool AddDialogData(WIN_DialogData *dialog,
const void *
data,
size_t size)
242 if (!ExpandDialogSpace(dialog,
size)) {
247 dialog->used +=
size;
252 static SDL_bool AddDialogString(WIN_DialogData *dialog,
const char *
string)
270 for (
p = wstring; *
p; ++
p) {
275 status = AddDialogData(dialog, wstring,
count*
sizeof(WCHAR));
280 static int s_BaseUnitsX;
281 static int s_BaseUnitsY;
282 static void Vec2ToDLU(
short *
x,
short *
y)
286 *
x = MulDiv(*
x, 4, s_BaseUnitsX);
287 *
y = MulDiv(*
y, 8, s_BaseUnitsY);
291 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, WORD ordinal)
293 DLGITEMTEMPLATEEX item;
299 item.exStyle = exStyle;
306 Vec2ToDLU(&item.x, &item.y);
307 Vec2ToDLU(&item.cx, &item.cy);
309 if (!AlignDialogData(dialog,
sizeof(DWORD))) {
312 if (!AddDialogData(dialog, &item,
sizeof(item))) {
318 if (!AddDialogData(dialog, &
type,
sizeof(
type))) {
321 if (
type == DLGITEMTYPEBUTTON || (
type == DLGITEMTYPESTATIC && caption !=
NULL)) {
322 if (!AddDialogString(dialog, caption)) {
329 if (!AddDialogData(dialog, &ordinal,
sizeof(ordinal))) {
333 if (!AddDialogData(dialog, &extraData,
sizeof(extraData))) {
336 if (
type == DLGITEMTYPEBUTTON) {
337 dialog->numbuttons++;
339 ++dialog->lpDialog->cDlgItems;
344 static SDL_bool AddDialogStaticText(WIN_DialogData *dialog,
int x,
int y,
int w,
int h,
const char *
text)
346 DWORD style = WS_VISIBLE | WS_CHILD | SS_LEFT | SS_NOPREFIX | SS_EDITCONTROL | WS_GROUP;
347 return AddDialogControl(dialog, DLGITEMTYPESTATIC, style, 0,
x,
y,
w,
h, -1,
text, 0);
350 static SDL_bool AddDialogStaticIcon(WIN_DialogData *dialog,
int x,
int y,
int w,
int h,
Uint16 ordinal)
352 DWORD style = WS_VISIBLE | WS_CHILD | SS_ICON | WS_GROUP;
353 return AddDialogControl(dialog, DLGITEMTYPESTATIC, style, 0,
x,
y,
w,
h, -2,
NULL, ordinal);
356 static SDL_bool AddDialogButton(WIN_DialogData *dialog,
int x,
int y,
int w,
int h,
const char *
text,
int id,
SDL_bool isDefault)
358 DWORD style = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
360 style |= BS_DEFPUSHBUTTON;
362 style |= BS_PUSHBUTTON;
365 if (dialog->numbuttons == 0) {
368 return AddDialogControl(dialog, DLGITEMTYPEBUTTON, style, 0,
x,
y,
w,
h,
id,
text, 0);
371 static void FreeDialogData(WIN_DialogData *dialog)
377 static WIN_DialogData *CreateDialogData(
int w,
int h,
const char *caption)
379 WIN_DialogData *dialog;
380 DLGTEMPLATEEX dialogTemplate;
384 dialogTemplate.dlgVer = 1;
385 dialogTemplate.signature = 0xffff;
386 dialogTemplate.style = (WS_CAPTION | DS_CENTER | DS_SHELLFONT);
387 dialogTemplate.x = 0;
388 dialogTemplate.y = 0;
389 dialogTemplate.cx =
w;
390 dialogTemplate.cy =
h;
391 Vec2ToDLU(&dialogTemplate.cx, &dialogTemplate.cy);
393 dialog = (WIN_DialogData *)
SDL_calloc(1,
sizeof(*dialog));
398 if (!AddDialogData(dialog, &dialogTemplate,
sizeof(dialogTemplate))) {
399 FreeDialogData(dialog);
405 if (!AddDialogData(dialog, &WordToPass, 2)) {
406 FreeDialogData(dialog);
411 if (!AddDialogData(dialog, &WordToPass, 2)) {
412 FreeDialogData(dialog);
417 if (!AddDialogString(dialog, caption)) {
418 FreeDialogData(dialog);
429 NONCLIENTMETRICSA NCM;
430 NCM.cbSize =
sizeof(NCM);
431 SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
435 HDC ScreenDC = GetDC(
NULL);
436 int LogicalPixelsY = GetDeviceCaps(ScreenDC, LOGPIXELSY);
439 WordToPass = (WORD)(-72 * NCM.lfMessageFont.lfHeight / LogicalPixelsY);
440 ReleaseDC(
NULL, ScreenDC);
443 if (!AddDialogData(dialog, &WordToPass, 2)) {
444 FreeDialogData(dialog);
449 WordToPass = (WORD)NCM.lfMessageFont.lfWeight;
450 if (!AddDialogData(dialog, &WordToPass, 2)) {
451 FreeDialogData(dialog);
456 ToPass = NCM.lfMessageFont.lfItalic;
457 if (!AddDialogData(dialog, &ToPass, 1)) {
458 FreeDialogData(dialog);
463 ToPass = NCM.lfMessageFont.lfCharSet;
464 if (!AddDialogData(dialog, &ToPass, 1)) {
465 FreeDialogData(dialog);
470 if (!AddDialogString(dialog, NCM.lfMessageFont.lfFaceName)) {
471 FreeDialogData(dialog);
488 static const char *EscapeAmpersands(
char **
dst,
size_t *dstlen,
const char *
src)
498 while (
src[srclen]) {
499 if (
src[srclen] ==
'&') {
513 if (*
dst ==
NULL || *dstlen < srclen + ampcount) {
515 size_t extraspace =
SIZE_MAX - (srclen + ampcount);
516 if (extraspace > 512) {
519 *dstlen = srclen + ampcount + extraspace;
523 if (newdst ==
NULL) {
546 WIN_DialogData *dialog;
555 char *ampescape =
NULL;
556 size_t ampescapesize = 0;
557 Uint16 defbuttoncount = 0;
560 HWND ParentWindow =
NULL;
562 const int ButtonWidth = 88;
563 const int ButtonHeight = 26;
564 const int TextMargin = 16;
565 const int ButtonMargin = 12;
566 const int IconWidth = GetSystemMetrics(SM_CXICON);
567 const int IconHeight = GetSystemMetrics(SM_CYICON);
568 const int IconMargin = 20;
570 if (messageboxdata->
numbuttons > MAX_BUTTONS) {
571 return SDL_SetError(
"Number of butons exceeds limit of %d", MAX_BUTTONS);
574 switch (messageboxdata->
flags) {
576 icon = (
Uint16)(
size_t)IDI_ERROR;
579 icon = (
Uint16)(
size_t)IDI_WARNING;
582 icon = (
Uint16)(
size_t)IDI_INFORMATION;
615 FontDC = CreateCompatibleDC(0);
620 NONCLIENTMETRICS NCM;
621 NCM.cbSize =
sizeof(NCM);
622 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
623 lf = NCM.lfMessageFont;
624 DialogFont = CreateFontIndirect(&lf);
628 SelectObject(FontDC, DialogFont);
632 GetTextMetrics(FontDC, &TM);
640 GetTextExtentPoint32A(FontDC,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &extent);
641 s_BaseUnitsX = (extent.cx / 26 + 1) / 2;
644 s_BaseUnitsY = TM.tmHeight;
650 DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT | DT_LEFT | DT_NOPREFIX | DT_EDITCONTROL);
653 TextSize.left += TextMargin;
654 TextSize.right += TextMargin + 2;
655 TextSize.top += TextMargin;
656 TextSize.bottom += TextMargin + 2;
663 Size.cx = TextSize.right - TextSize.left;
664 Size.cy = TextSize.bottom - TextSize.top;
665 Size.cx += TextMargin * 2;
666 Size.cy += TextMargin * 2;
670 Size.cx += IconMargin + IconWidth;
671 TextSize.left += IconMargin + IconWidth;
672 TextSize.right += IconMargin + IconWidth;
676 if (Size.cx < messageboxdata->
numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin)
677 Size.cx = messageboxdata->
numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin;
680 if (icon && Size.cy < IconMargin * 2 + IconHeight) {
681 Size.cy = IconMargin * 2 + IconHeight;
685 Size.cy += ButtonHeight + TextMargin;
687 dialog = CreateDialogData(Size.cx, Size.cy, messageboxdata->
title);
692 if (icon && ! AddDialogStaticIcon(dialog, IconMargin, IconMargin, IconWidth, IconHeight, icon)) {
693 FreeDialogData(dialog);
697 if (!AddDialogStaticText(dialog, TextSize.left, TextSize.top, TextSize.right - TextSize.left, TextSize.bottom - TextSize.top, messageboxdata->
message)) {
698 FreeDialogData(dialog);
703 x = Size.cx - (ButtonWidth + ButtonMargin) * messageboxdata->
numbuttons;
704 y = Size.cy - ButtonHeight - ButtonMargin;
707 const char *buttontext;
714 sdlButton = &messageboxdata->
buttons[
i];
721 if (defbuttoncount == 1) {
726 buttontext = EscapeAmpersands(&escape, &escapesize, sdlButton->
text);
729 if (buttontext ==
NULL || !AddDialogButton(dialog,
x,
y, ButtonWidth, ButtonHeight, buttontext, IDBUTTONINDEX0 + (
int)(sdlButton - messageboxdata->
buttons), isdefault)) {
730 FreeDialogData(dialog);
735 x += ButtonWidth + ButtonMargin;
741 if (messageboxdata->
window) {
745 result = DialogBoxIndirectParam(
NULL, (DLGTEMPLATE*)dialog->lpDialog, ParentWindow, (DLGPROC)MessageBoxDialogProc, (LPARAM)messageboxdata);
746 if (
result >= IDBUTTONINDEX0 &&
result - IDBUTTONINDEX0 < messageboxdata->numbuttons) {
749 }
else if (
result == IDCLOSED) {
757 }
else if (
result == -1) {
759 }
else if (
result == IDINVALPTRINIT ||
result == IDINVALPTRSETFOCUS ||
result == IDINVALPTRCOMMAND) {
760 SDL_SetError(
"Invalid message box pointer in dialog procedure");
761 }
else if (
result == IDINVALPTRDLGITEM) {
762 SDL_SetError(
"Couldn't find dialog control of the default enter-key button");
769 FreeDialogData(dialog);
776 typedef HRESULT(
FAR WINAPI *TASKDIALOGINDIRECTPROC)(
const TASKDIALOGCONFIG *pTaskConfig,
int *pnButton,
int *pnRadioButton, BOOL *pfVerificationFlagChecked);
781 HWND ParentWindow =
NULL;
788 TASKDIALOGINDIRECTPROC pfnTaskDialogIndirect;
790 char *ampescape =
NULL;
791 size_t ampescapesize = 0;
801 hComctl32 = LoadLibrary(TEXT(
"Comctl32.dll"));
802 if (hComctl32 ==
NULL) {
803 return WIN_ShowOldMessageBox(messageboxdata, buttonid);
813 pfnTaskDialogIndirect = (TASKDIALOGINDIRECTPROC) GetProcAddress(hComctl32,
"TaskDialogIndirect");
814 if (pfnTaskDialogIndirect ==
NULL) {
815 FreeLibrary(hComctl32);
816 return WIN_ShowOldMessageBox(messageboxdata, buttonid);
821 if (messageboxdata->
window) {
850 const char *buttontext;
852 pButton = &pButtons[
i];
854 pButton = &pButtons[messageboxdata->
numbuttons - 1 -
i];
862 buttontext = EscapeAmpersands(&escape, &escapesize, messageboxdata->
buttons[
i].
text);
863 if (buttontext ==
NULL) {
865 FreeLibrary(hComctl32);
869 for (
j = 0;
j <
i;
j++) {
870 SDL_free((
wchar_t *) pButtons[
j].pszButtonText);
883 hr = pfnTaskDialogIndirect(&TaskConfig, &nButton,
NULL,
NULL);
886 FreeLibrary(hComctl32);
891 SDL_free((
wchar_t *) pButtons[
i].pszButtonText);
897 if (nButton == IDCANCEL) {
898 *buttonid = nCancelButton;
899 }
else if (nButton >= IDBUTTONINDEX0 && nButton < IDBUTTONINDEX0 + messageboxdata->numbuttons) {
900 *buttonid = messageboxdata->
buttons[nButton - IDBUTTONINDEX0].
buttonid;
908 return WIN_ShowOldMessageBox(messageboxdata, buttonid);
#define SDL_assert(condition)
#define SDL_OutOfMemory()
@ SDL_MESSAGEBOX_INFORMATION
@ SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT
@ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT
@ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT
GLint GLint GLint GLint GLint GLint y
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLint GLint GLint GLint GLint x
GLuint GLuint GLsizei GLenum type
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
#define WIN_UTF8ToString(S)
#define TD_INFORMATION_ICON
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
MessageBox structure containing title, text, window, etc.
const SDL_MessageBoxButtonData * buttons
const TASKDIALOG_BUTTON * pButtons
static char text[MAX_TEXT_LENGTH]