Implement BeginUpdateResource and UpdateResource.
[wine.git] / programs / winetest / gui.c
blob89a310825a3e36db4d20e4a3157920246c272475
1 /*
2 * GUI support
4 * Copyright 2004 Ferenc Wagner
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <windows.h>
22 #include <commctrl.h>
24 #include "resource.h"
25 #include "winetest.h"
27 /* Event object to signal successful window creation to main thread.
29 HANDLE initEvent;
31 /* Dialog handle
33 HWND dialog;
35 /* Progress data for the text* functions and for scaling.
37 unsigned int progressMax, progressCurr;
38 double progressScale;
40 /* Progress group counter for the gui* functions.
42 int progressGroup;
44 char *
45 renderString (va_list ap)
47 const char *fmt = va_arg (ap, char*);
48 static char buffer[128];
50 vsnprintf (buffer, sizeof buffer, fmt, ap);
51 return buffer;
54 int
55 MBdefault (int uType)
57 static const int matrix[][4] = {{IDOK, 0, 0, 0},
58 {IDOK, IDCANCEL, 0, 0},
59 {IDABORT, IDRETRY, IDIGNORE, 0},
60 {IDYES, IDNO, IDCANCEL, 0},
61 {IDYES, IDNO, 0, 0},
62 {IDRETRY, IDCANCEL, 0, 0}};
63 int type = uType & MB_TYPEMASK;
64 int def = (uType & MB_DEFMASK) / MB_DEFBUTTON2;
66 return matrix[type][def];
69 /* report (R_STATUS, fmt, ...) */
70 int
71 textStatus (va_list ap)
73 char *str = vstrmake (NULL, ap);
75 fputs (str, stderr);
76 fputc ('\n', stderr);
77 free (str);
78 return 0;
81 int
82 guiStatus (va_list ap)
84 size_t len;
85 char *str = vstrmake (&len, ap);
87 if (len > 128) str[129] = 0;
88 SetDlgItemText (dialog, IDC_SB, str);
89 free (str);
90 return 0;
93 /* report (R_PROGRESS, barnum, steps) */
94 int
95 textProgress (va_list ap)
97 progressGroup = va_arg (ap, int);
98 progressMax = va_arg (ap, int);
99 progressCurr = 0;
100 return 0;
104 guiProgress (va_list ap)
106 unsigned int max;
107 HWND pb;
109 progressGroup = va_arg (ap, int);
110 progressMax = max = va_arg (ap, int);
111 progressCurr = 0;
112 if (max > 0xffff) {
113 progressScale = (double)0xffff / max;
114 max = 0xffff;
116 else progressScale = 1;
117 pb = GetDlgItem (dialog, IDC_PB0 + progressGroup * 2);
118 SendMessage (pb, PBM_SETRANGE, 0, MAKELPARAM (0, max));
119 SendMessage (pb, PBM_SETSTEP, (WPARAM)1, 0);
120 return 0;
123 /* report (R_STEP, fmt, ...) */
125 textStep (va_list ap)
127 char *str = vstrmake (NULL, ap);
129 progressCurr++;
130 fputs (str, stderr);
131 fprintf (stderr, " (%d of %d)\n", progressCurr, progressMax);
132 free (str);
133 return 0;
137 guiStep (va_list ap)
139 const int pgID = IDC_ST0 + progressGroup * 2;
140 char *str = vstrmake (NULL, ap);
142 progressCurr++;
143 SetDlgItemText (dialog, pgID, str);
144 SendDlgItemMessage (dialog, pgID+1, PBM_SETPOS,
145 (WPARAM)(progressScale * progressCurr), 0);
146 free (str);
147 return 0;
150 /* report (R_DELTA, inc, fmt, ...) */
152 textDelta (va_list ap)
154 const int inc = va_arg (ap, int);
155 char *str = vstrmake (NULL, ap);
157 progressCurr += inc;
158 fputs (str, stderr);
159 fprintf (stderr, " (%d of %d)\n", progressCurr, progressMax);
160 free (str);
161 return 0;
165 guiDelta (va_list ap)
167 const int inc = va_arg (ap, int);
168 const int pgID = IDC_ST0 + progressGroup * 2;
169 char *str = vstrmake (NULL, ap);
171 progressCurr += inc;
172 SetDlgItemText (dialog, pgID, str);
173 SendDlgItemMessage (dialog, pgID+1, PBM_SETPOS,
174 (WPARAM)(progressScale * progressCurr), 0);
175 free (str);
176 return 0;
179 /* report (R_DIR, fmt, ...) */
181 textDir (va_list ap)
183 char *str = vstrmake (NULL, ap);
185 fputs ("Temporary directory: ", stderr);
186 fputs (str, stderr);
187 fputc ('\n', stderr);
188 free (str);
189 return 0;
193 guiDir (va_list ap)
195 char *str = vstrmake (NULL, ap);
197 SetDlgItemText (dialog, IDC_DIR, str);
198 free (str);
199 return 0;
202 /* report (R_OUT, fmt, ...) */
204 textOut (va_list ap)
206 char *str = vstrmake (NULL, ap);
208 fputs ("Log file: ", stderr);
209 fputs (str, stderr);
210 fputc ('\n', stderr);
211 free (str);
212 return 0;
216 guiOut (va_list ap)
218 char *str = vstrmake (NULL, ap);
220 SetDlgItemText (dialog, IDC_OUT, str);
221 free (str);
222 return 0;
225 /* report (R_WARNING, fmt, ...) */
227 textWarning (va_list ap)
229 fputs ("Warning: ", stderr);
230 textStatus (ap);
231 return 0;
235 guiWarning (va_list ap)
237 char *str = vstrmake (NULL, ap);
239 MessageBox (dialog, str, "Warning", MB_ICONWARNING | MB_OK);
240 free (str);
241 return 0;
244 /* report (R_ERROR, fmt, ...) */
246 textError (va_list ap)
248 fputs ("Error: ", stderr);
249 textStatus (ap);
250 return 0;
254 guiError (va_list ap)
256 char *str = vstrmake (NULL, ap);
258 MessageBox (dialog, str, "Error", MB_ICONERROR | MB_OK);
259 free (str);
260 return 0;
263 /* report (R_FATAL, fmt, ...) */
265 textFatal (va_list ap)
267 textError (ap);
268 exit (1);
272 guiFatal (va_list ap)
274 guiError (ap);
275 exit (1);
278 /* report (R_ASK, type, fmt, ...) */
280 textAsk (va_list ap)
282 int uType = va_arg (ap, int);
283 int ret = MBdefault (uType);
284 char *str = vstrmake (NULL, ap);
286 fprintf (stderr, "Question of type %d: %s\n"
287 "Returning default: %d\n", uType, str, ret);
288 free (str);
289 return ret;
293 guiAsk (va_list ap)
295 int uType = va_arg (ap, int);
296 char *str = vstrmake (NULL, ap);
297 int ret = MessageBox (dialog, str, "Question",
298 MB_ICONQUESTION | uType);
300 free (str);
301 return ret;
304 /* Quiet functions */
306 qNoOp (va_list ap)
308 return 0;
312 qFatal (va_list ap)
314 exit (1);
318 qAsk (va_list ap)
320 return MBdefault (va_arg (ap, int));
323 BOOL CALLBACK
324 AboutProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
326 switch (msg) {
327 case WM_COMMAND:
328 switch (LOWORD (wParam)) {
329 case IDCANCEL:
330 EndDialog (hwnd, IDCANCEL);
331 return TRUE;
334 return FALSE;
337 BOOL CALLBACK
338 DlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
340 switch (msg) {
341 case WM_INITDIALOG:
342 SendMessage (hwnd, WM_SETICON, ICON_SMALL,
343 (LPARAM)LoadIcon (GetModuleHandle (NULL),
344 MAKEINTRESOURCE (IDI_WINE)));
345 SendMessage (hwnd, WM_SETICON, ICON_BIG,
346 (LPARAM)LoadIcon (GetModuleHandle (NULL),
347 MAKEINTRESOURCE (IDI_WINE)));
348 dialog = hwnd;
349 if (!SetEvent (initEvent)) {
350 report (R_STATUS, "Can't signal main thread: %d",
351 GetLastError ());
352 EndDialog (hwnd, 2);
354 return TRUE;
355 case WM_CLOSE:
356 EndDialog (hwnd, 3);
357 return TRUE;
358 case WM_COMMAND:
359 switch (LOWORD (wParam)) {
360 case IDHELP:
361 DialogBox (GetModuleHandle (NULL),
362 MAKEINTRESOURCE (IDD_ABOUT), hwnd, AboutProc);
363 return TRUE;
364 case IDABORT:
365 report (R_WARNING, "Not implemented");
366 return TRUE;
369 return FALSE;
372 DWORD WINAPI
373 DlgThreadProc ()
375 int ret;
377 InitCommonControls ();
378 ret = DialogBox (GetModuleHandle (NULL),
379 MAKEINTRESOURCE (IDD_STATUS),
380 NULL, DlgProc);
381 switch (ret) {
382 case 0:
383 report (R_WARNING, "Invalid parent handle");
384 break;
385 case 1:
386 report (R_WARNING, "DialogBox failed: %d",
387 GetLastError ());
388 break;
389 case 3:
390 exit (0);
391 default:
392 report (R_STATUS, "Dialog exited: %d", ret);
394 return 0;
398 report (enum report_type t, ...)
400 typedef int r_fun_t (va_list);
402 va_list ap;
403 int ret = 0;
404 static r_fun_t * const text_funcs[] =
405 {textStatus, textProgress, textStep, textDelta,
406 textDir, textOut,
407 textWarning, textError, textFatal, textAsk};
408 static r_fun_t * const GUI_funcs[] =
409 {guiStatus, guiProgress, guiStep, guiDelta,
410 guiDir, guiOut,
411 guiWarning, guiError, guiFatal, guiAsk};
412 static r_fun_t * const quiet_funcs[] =
413 {qNoOp, qNoOp, qNoOp, qNoOp,
414 qNoOp, qNoOp,
415 qNoOp, qNoOp, qFatal, qAsk};
416 static r_fun_t * const * funcs = NULL;
418 switch (t) {
419 case R_TEXTMODE:
420 funcs = text_funcs;
421 return 0;
422 case R_QUIET:
423 funcs = quiet_funcs;
424 return 0;
425 default:
426 break;
429 if (!funcs) {
430 HANDLE DlgThread;
431 DWORD DlgThreadID;
433 funcs = text_funcs;
434 initEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
435 if (!initEvent)
436 report (R_STATUS, "Can't create event object: %d",
437 GetLastError ());
438 else {
439 DlgThread = CreateThread (NULL, 0, DlgThreadProc,
440 NULL, 0, &DlgThreadID);
441 if (!DlgThread)
442 report (R_STATUS, "Can't create GUI thread: %d",
443 GetLastError ());
444 else {
445 DWORD ret = WaitForSingleObject (initEvent, INFINITE);
446 switch (ret) {
447 case WAIT_OBJECT_0:
448 funcs = GUI_funcs;
449 break;
450 case WAIT_TIMEOUT:
451 report (R_STATUS, "GUI creation timed out");
452 break;
453 case WAIT_FAILED:
454 report (R_STATUS, "Wait for GUI failed: %d",
455 GetLastError ());
456 break;
457 default:
458 report (R_STATUS, "Wait returned %d",
459 ret);
460 break;
466 va_start (ap, t);
467 if (t < sizeof text_funcs / sizeof text_funcs[0] &&
468 t < sizeof GUI_funcs / sizeof GUI_funcs[0] &&
469 t >= 0) ret = funcs[t](ap);
470 else report (R_WARNING, "unimplemented report type: %d", t);
471 va_end (ap);
472 return ret;