21 #include "../../SDL_internal.h" 23 #if SDL_VIDEO_DRIVER_WINDOWS 29 #define SIZE_MAX ((size_t)-1) 33 #include "../../core/windows/SDL_windows.h" 39 #ifndef SS_EDITCONTROL 40 #define SS_EDITCONTROL 0x2000 53 #define IDINVALPTRINIT 50 54 #define IDINVALPTRCOMMAND 51 55 #define IDINVALPTRSETFOCUS 52 56 #define IDINVALPTRDLGITEM 53 58 #define IDBUTTONINDEX0 100 60 #define DLGITEMTYPEBUTTON 0x0080 61 #define DLGITEMTYPESTATIC 0x0082 68 #define MAX_BUTTONS (0xffff - 100) 105 DLGTEMPLATEEX* lpDialog;
122 static INT_PTR MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)
127 switch ( iMessage ) {
130 EndDialog(hDlg, IDINVALPTRINIT);
134 SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
138 HWND buttonctl = GetDlgItem(hDlg, (
int)(IDBUTTONINDEX0 + buttonindex));
139 if (buttonctl ==
NULL) {
140 EndDialog(hDlg, IDINVALPTRDLGITEM);
142 PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)buttonctl,
TRUE);
150 if (messageboxdata ==
NULL) {
151 EndDialog(hDlg, IDINVALPTRSETFOCUS);
162 if (messageboxdata ==
NULL) {
163 EndDialog(hDlg, IDINVALPTRCOMMAND);
168 if (wParam == IDOK) {
170 EndDialog(hDlg, IDBUTTONINDEX0 + buttonindex);
172 }
else if (wParam == IDCANCEL) {
174 EndDialog(hDlg, IDBUTTONINDEX0 + buttonindex);
177 EndDialog(hDlg, IDCLOSED);
179 }
else if (wParam >= IDBUTTONINDEX0 && (
int)wParam - IDBUTTONINDEX0 < messageboxdata->numbuttons) {
180 EndDialog(hDlg, wParam);
190 static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog,
size_t space)
193 const size_t sizestep = 0x10000;
194 size_t size = dialog->size;
199 if (SIZE_MAX - sizestep < space) {
201 }
else if (space > size) {
202 size = (space + sizestep) & ~(sizestep - 1);
204 }
else if (SIZE_MAX - dialog->used < space) {
207 }
else if (SIZE_MAX - (dialog->used + space) < sizestep) {
209 size = dialog->used + space;
212 size = dialog->used + space;
213 size += sizestep - size % sizestep;
216 if (size > dialog->size) {
224 dialog->lpDialog = (DLGTEMPLATEEX*)dialog->data;
229 static SDL_bool AlignDialogData(WIN_DialogData *dialog,
size_t size)
231 size_t padding = (dialog->used %
size);
233 if (!ExpandDialogSpace(dialog, padding)) {
237 dialog->used += padding;
242 static SDL_bool AddDialogData(WIN_DialogData *dialog,
const void *
data,
size_t size)
244 if (!ExpandDialogSpace(dialog, size)) {
248 SDL_memcpy(dialog->data+dialog->used, data, size);
249 dialog->used +=
size;
254 static SDL_bool AddDialogString(WIN_DialogData *dialog,
const char *
string)
272 for (p = wstring; *
p; ++
p) {
277 status = AddDialogData(dialog, wstring, count*
sizeof(WCHAR));
282 static int s_BaseUnitsX;
283 static int s_BaseUnitsY;
284 static void Vec2ToDLU(
short *
x,
short *
y)
288 *x = MulDiv(*x, 4, s_BaseUnitsX);
289 *y = MulDiv(*y, 8, s_BaseUnitsY);
293 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)
295 DLGITEMTEMPLATEEX item;
301 item.exStyle = exStyle;
308 Vec2ToDLU(&item.x, &item.y);
309 Vec2ToDLU(&item.cx, &item.cy);
311 if (!AlignDialogData(dialog,
sizeof(DWORD))) {
314 if (!AddDialogData(dialog, &item,
sizeof(item))) {
317 if (!AddDialogData(dialog, &marker,
sizeof(marker))) {
320 if (!AddDialogData(dialog, &type,
sizeof(type))) {
323 if (type == DLGITEMTYPEBUTTON || (type == DLGITEMTYPESTATIC && caption !=
NULL)) {
324 if (!AddDialogString(dialog, caption)) {
328 if (!AddDialogData(dialog, &marker,
sizeof(marker))) {
331 if (!AddDialogData(dialog, &ordinal,
sizeof(ordinal))) {
335 if (!AddDialogData(dialog, &extraData,
sizeof(extraData))) {
338 if (type == DLGITEMTYPEBUTTON) {
339 dialog->numbuttons++;
341 ++dialog->lpDialog->cDlgItems;
346 static SDL_bool AddDialogStaticText(WIN_DialogData *dialog,
int x,
int y,
int w,
int h,
const char *
text)
348 DWORD style = WS_VISIBLE | WS_CHILD | SS_LEFT | SS_NOPREFIX | SS_EDITCONTROL | WS_GROUP;
349 return AddDialogControl(dialog, DLGITEMTYPESTATIC, style, 0, x, y, w, h, -1, text, 0);
352 static SDL_bool AddDialogStaticIcon(WIN_DialogData *dialog,
int x,
int y,
int w,
int h,
Uint16 ordinal)
354 DWORD style = WS_VISIBLE | WS_CHILD | SS_ICON | WS_GROUP;
355 return AddDialogControl(dialog, DLGITEMTYPESTATIC, style, 0, x, y, w, h, -2,
NULL, ordinal);
358 static SDL_bool AddDialogButton(WIN_DialogData *dialog,
int x,
int y,
int w,
int h,
const char *
text,
int id,
SDL_bool isDefault)
360 DWORD style = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
362 style |= BS_DEFPUSHBUTTON;
364 style |= BS_PUSHBUTTON;
367 if (dialog->numbuttons == 0) {
370 return AddDialogControl(dialog, DLGITEMTYPEBUTTON, style, 0, x, y, w, h, IDBUTTONINDEX0 + dialog->numbuttons, text, 0);
373 static void FreeDialogData(WIN_DialogData *dialog)
379 static WIN_DialogData *CreateDialogData(
int w,
int h,
const char *caption)
381 WIN_DialogData *dialog;
382 DLGTEMPLATEEX dialogTemplate;
386 dialogTemplate.dlgVer = 1;
387 dialogTemplate.signature = 0xffff;
388 dialogTemplate.style = (WS_CAPTION | DS_CENTER | DS_SHELLFONT);
389 dialogTemplate.x = 0;
390 dialogTemplate.y = 0;
391 dialogTemplate.cx =
w;
392 dialogTemplate.cy =
h;
393 Vec2ToDLU(&dialogTemplate.cx, &dialogTemplate.cy);
395 dialog = (WIN_DialogData *)
SDL_calloc(1,
sizeof(*dialog));
400 if (!AddDialogData(dialog, &dialogTemplate,
sizeof(dialogTemplate))) {
401 FreeDialogData(dialog);
407 if (!AddDialogData(dialog, &WordToPass, 2)) {
408 FreeDialogData(dialog);
413 if (!AddDialogData(dialog, &WordToPass, 2)) {
414 FreeDialogData(dialog);
419 if (!AddDialogString(dialog, caption)) {
420 FreeDialogData(dialog);
431 NONCLIENTMETRICSA NCM;
432 NCM.cbSize =
sizeof(NCM);
433 SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
437 HDC ScreenDC = GetDC(
NULL);
438 int LogicalPixelsY = GetDeviceCaps(ScreenDC, LOGPIXELSY);
441 WordToPass = (WORD)(-72 * NCM.lfMessageFont.lfHeight / LogicalPixelsY);
442 ReleaseDC(
NULL, ScreenDC);
445 if (!AddDialogData(dialog, &WordToPass, 2)) {
446 FreeDialogData(dialog);
451 WordToPass = (WORD)NCM.lfMessageFont.lfWeight;
452 if (!AddDialogData(dialog, &WordToPass, 2)) {
453 FreeDialogData(dialog);
458 ToPass = NCM.lfMessageFont.lfItalic;
459 if (!AddDialogData(dialog, &ToPass, 1)) {
460 FreeDialogData(dialog);
465 ToPass = NCM.lfMessageFont.lfCharSet;
466 if (!AddDialogData(dialog, &ToPass, 1)) {
467 FreeDialogData(dialog);
472 if (!AddDialogString(dialog, NCM.lfMessageFont.lfFaceName)) {
473 FreeDialogData(dialog);
490 static const char *EscapeAmpersands(
char **
dst,
size_t *dstlen,
const char *
src)
500 while (src[srclen]) {
501 if (src[srclen] ==
'&') {
512 if (SIZE_MAX - srclen < ampcount) {
515 if (*dst ==
NULL || *dstlen < srclen + ampcount) {
517 size_t extraspace = SIZE_MAX - (srclen + ampcount);
518 if (extraspace > 512) {
521 *dstlen = srclen + ampcount + extraspace;
525 if (newdst ==
NULL) {
548 WIN_DialogData *dialog;
558 char *ampescape =
NULL;
559 size_t ampescapesize = 0;
560 Uint16 defbuttoncount = 0;
563 HWND ParentWindow =
NULL;
565 const int ButtonWidth = 88;
566 const int ButtonHeight = 26;
567 const int TextMargin = 16;
568 const int ButtonMargin = 12;
569 const int IconWidth = GetSystemMetrics(SM_CXICON);
570 const int IconHeight = GetSystemMetrics(SM_CYICON);
571 const int IconMargin = 20;
573 if (messageboxdata->
numbuttons > MAX_BUTTONS) {
574 return SDL_SetError(
"Number of butons exceeds limit of %d", MAX_BUTTONS);
577 switch (messageboxdata->
flags) {
579 icon = (
Uint16)(
size_t)IDI_ERROR;
582 icon = (
Uint16)(
size_t)IDI_WARNING;
585 icon = (
Uint16)(
size_t)IDI_INFORMATION;
621 FontDC = CreateCompatibleDC(0);
626 NONCLIENTMETRICS NCM;
627 NCM.cbSize =
sizeof(NCM);
628 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
629 lf = NCM.lfMessageFont;
630 DialogFont = CreateFontIndirect(&lf);
634 SelectObject(FontDC, DialogFont);
638 GetTextMetrics(FontDC, &TM);
646 GetTextExtentPoint32A(FontDC,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &extent);
647 s_BaseUnitsX = (extent.cx / 26 + 1) / 2;
650 s_BaseUnitsY = TM.tmHeight;
656 DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT | DT_LEFT | DT_NOPREFIX | DT_EDITCONTROL);
659 TextSize.left += TextMargin;
660 TextSize.right += TextMargin + 2;
661 TextSize.top += TextMargin;
662 TextSize.bottom += TextMargin + 2;
669 Size.cx = TextSize.right - TextSize.left;
670 Size.cy = TextSize.bottom - TextSize.top;
671 Size.cx += TextMargin * 2;
672 Size.cy += TextMargin * 2;
676 Size.cx += IconMargin + IconWidth;
677 TextSize.left += IconMargin + IconWidth;
678 TextSize.right += IconMargin + IconWidth;
682 if (Size.cx < messageboxdata->
numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin)
683 Size.cx = messageboxdata->
numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin;
686 if (icon && Size.cy < IconMargin * 2 + IconHeight) {
687 Size.cy = IconMargin * 2 + IconHeight;
691 Size.cy += ButtonHeight + TextMargin;
693 dialog = CreateDialogData(Size.cx, Size.cy, messageboxdata->
title);
698 if (icon && ! AddDialogStaticIcon(dialog, IconMargin, IconMargin, IconWidth, IconHeight, icon)) {
699 FreeDialogData(dialog);
703 if (!AddDialogStaticText(dialog, TextSize.left, TextSize.top, TextSize.right - TextSize.left, TextSize.bottom - TextSize.top, messageboxdata->
message)) {
704 FreeDialogData(dialog);
709 x = Size.cx - (ButtonWidth + ButtonMargin) * messageboxdata->
numbuttons;
710 y = Size.cy - ButtonHeight - ButtonMargin;
711 for (i = messageboxdata->
numbuttons - 1; i >= 0; --i) {
713 const char *buttontext;
717 if (defbuttoncount == 1) {
722 buttontext = EscapeAmpersands(&escape, &escapesize, buttons[i].text);
723 if (buttontext ==
NULL || !AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttontext, buttons[i].buttonid, isdefault)) {
724 FreeDialogData(dialog);
728 x += ButtonWidth + ButtonMargin;
734 if (messageboxdata->
window) {
738 result = DialogBoxIndirectParam(
NULL, (DLGTEMPLATE*)dialog->lpDialog, ParentWindow, (DLGPROC)MessageBoxDialogProc, (LPARAM)messageboxdata);
739 if (result >= IDBUTTONINDEX0 && result - IDBUTTONINDEX0 < messageboxdata->numbuttons) {
742 }
else if (result == IDCLOSED) {
750 }
else if (result == -1) {
752 }
else if (result == IDINVALPTRINIT || result == IDINVALPTRSETFOCUS || result == IDINVALPTRCOMMAND) {
753 SDL_SetError(
"Invalid message box pointer in dialog procedure");
754 }
else if (result == IDINVALPTRDLGITEM) {
755 SDL_SetError(
"Couldn't find dialog control of the default enter-key button");
762 FreeDialogData(dialog);
769 typedef HRESULT(
FAR WINAPI *TASKDIALOGINDIRECTPROC)(
const TASKDIALOGCONFIG *pTaskConfig,
int *pnButton,
int *pnRadioButton, BOOL *pfVerificationFlagChecked);
774 HWND ParentWindow =
NULL;
781 TASKDIALOGINDIRECTPROC pfnTaskDialogIndirect;
783 char *ampescape =
NULL;
784 size_t ampescapesize = 0;
794 hComctl32 = LoadLibrary(TEXT(
"Comctl32.dll"));
795 if (hComctl32 ==
NULL) {
796 return WIN_ShowOldMessageBox(messageboxdata, buttonid);
806 pfnTaskDialogIndirect = (TASKDIALOGINDIRECTPROC) GetProcAddress(hComctl32,
"TaskDialogIndirect");
807 if (pfnTaskDialogIndirect ==
NULL) {
808 FreeLibrary(hComctl32);
809 return WIN_ShowOldMessageBox(messageboxdata, buttonid);
814 if (messageboxdata->
window) {
841 for (i = 0; i < messageboxdata->
numbuttons; i++)
843 const char *buttontext;
844 pButton = &pButtons[messageboxdata->
numbuttons-1-
i];
854 buttontext = EscapeAmpersands(&escape, &escapesize, messageboxdata->
buttons[i].
text);
855 if (buttontext ==
NULL) {
857 FreeLibrary(hComctl32);
861 for (j = 0; j <
i; j++) {
862 SDL_free((
wchar_t *) pButtons[j].pszButtonText);
868 if (messageboxdata->
buttons[i].
flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
875 hr = pfnTaskDialogIndirect(&TaskConfig, &nButton,
NULL,
NULL);
878 FreeLibrary(hComctl32);
882 for (i = 0; i < messageboxdata->
numbuttons; i++) {
883 SDL_free((
wchar_t *) pButtons[i].pszButtonText);
890 *buttonid = nCancelButton;
891 }
else if (nButton > 2) {
892 *buttonid = nButton-1-1;
894 *buttonid = nButton-1;
900 return WIN_ShowOldMessageBox(messageboxdata, buttonid);
#define WIN_UTF8ToString(S)
GLint GLint GLint GLint GLint x
GLuint GLuint GLsizei count
GLfloat GLfloat GLfloat GLfloat h
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 local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
#define TD_INFORMATION_ICON
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
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)
GLubyte GLubyte GLubyte GLubyte w
GLint GLint GLint GLint GLint GLint y
const SDL_MessageBoxButtonData * buttons
MessageBox structure containing title, text, window, etc.
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)
#define SDL_assert(condition)
#define SDL_OutOfMemory()
const TASKDIALOG_BUTTON * pButtons
static char text[MAX_TEXT_LENGTH]
GLuint GLuint GLsizei GLenum type