Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xwin / windialogs.c
CommitLineData
a09e091a
JB
1/*
2 *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
3 *
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *Except as contained in this notice, the name of Harold L Hunt II
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from Harold L Hunt II.
27 *
28 * Authors: Harold L Hunt II
29 * Earle F. Philhower III
30 */
31
32#ifdef HAVE_XWIN_CONFIG_H
33#include <xwin-config.h>
34#endif
35#include "win.h"
36#include <shellapi.h>
37#include "winprefs.h"
38
39/*
40 * References to external globals
41 */
42
43#ifdef XWIN_CLIPBOARD
44extern Bool g_fClipboardStarted;
45#endif
46/*
47 * Local function prototypes
48 */
49
50static INT_PTR CALLBACK
51winExitDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam);
52
53static INT_PTR CALLBACK
54winChangeDepthDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam);
55
56static INT_PTR CALLBACK
57winAboutDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam);
58
59static void
60 winDrawURLWindow(LPARAM lParam);
61
62static LRESULT CALLBACK
63winURLWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
64
65static void
66 winOverrideURLButton(HWND hdlg, int id);
67
68static void
69 winUnoverrideURLButton(HWND hdlg, int id);
70
71/*
72 * Owner-draw a button as a URL
73 */
74
75static void
76winDrawURLWindow(LPARAM lParam)
77{
78 DRAWITEMSTRUCT *draw;
79 char str[256];
80 RECT rect;
81 HFONT font;
82 COLORREF crText;
83
84 draw = (DRAWITEMSTRUCT *) lParam;
85 GetWindowText(draw->hwndItem, str, sizeof(str));
86 str[255] = 0;
87 GetClientRect(draw->hwndItem, &rect);
88
89 /* Color the button depending upon its state */
90 if (draw->itemState & ODS_SELECTED)
91 crText = RGB(128 + 64, 0, 0);
92 else if (draw->itemState & ODS_FOCUS)
93 crText = RGB(0, 128 + 64, 0);
94 else
95 crText = RGB(0, 0, 128 + 64);
96 SetTextColor(draw->hDC, crText);
97
98 /* Create font 8 high, standard dialog font */
99 font = CreateFont(-8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
100 0, 0, 0, 0, 0, "MS Sans Serif");
101 if (!font) {
102 ErrorF("winDrawURLWindow: Unable to create URL font, bailing.\n");
103 return;
104 }
105 /* Draw it */
106 SetBkMode(draw->hDC, OPAQUE);
107 SelectObject(draw->hDC, font);
108 DrawText(draw->hDC, str, strlen(str), &rect, DT_LEFT | DT_VCENTER);
109 /* Delete the created font, replace it with stock font */
110 DeleteObject(SelectObject(draw->hDC, GetStockObject(ANSI_VAR_FONT)));
111}
112
113/*
114 * WndProc for overridden buttons
115 */
116
117static LRESULT CALLBACK
118winURLWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
119{
120 WNDPROC origCB = NULL;
121 HCURSOR cursor;
122
123 /* If it's a SetCursor message, tell it to the hand */
124 if (msg == WM_SETCURSOR) {
125 cursor = LoadCursor(NULL, IDC_HAND);
126 if (cursor)
127 SetCursor(cursor);
128 return TRUE;
129 }
130 origCB = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_USERDATA);
131 /* Otherwise fall through to original WndProc */
132 if (origCB)
133 return CallWindowProc(origCB, hwnd, msg, wParam, lParam);
134 else
135 return FALSE;
136}
137
138/*
139 * Register and unregister the custom WndProc
140 */
141
142static void
143winOverrideURLButton(HWND hwnd, int id)
144{
145 WNDPROC origCB;
146
147 origCB = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwnd, id),
148 GWLP_WNDPROC, (LONG_PTR) winURLWndProc);
149 SetWindowLongPtr(GetDlgItem(hwnd, id), GWLP_USERDATA, (LONG_PTR) origCB);
150}
151
152static void
153winUnoverrideURLButton(HWND hwnd, int id)
154{
155 WNDPROC origCB;
156
157 origCB = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwnd, id), GWLP_USERDATA, 0);
158 if (origCB)
159 SetWindowLongPtr(GetDlgItem(hwnd, id), GWLP_WNDPROC, (LONG_PTR) origCB);
160}
161
162/*
163 * Center a dialog window in the desktop window
164 * and set small and large icons to X icons.
165 */
166
167static void
168winInitDialog(HWND hwndDlg)
169{
170 HWND hwndDesk;
171 RECT rc, rcDlg, rcDesk;
172 HICON hIcon, hIconSmall;
173
174 hwndDesk = GetParent(hwndDlg);
175 if (!hwndDesk || IsIconic(hwndDesk))
176 hwndDesk = GetDesktopWindow();
177
178 /* Remove minimize and maximize buttons */
179 SetWindowLongPtr(hwndDlg, GWL_STYLE, GetWindowLongPtr(hwndDlg, GWL_STYLE)
180 & ~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX));
181
182 /* Set Window not to show in the task bar */
183 SetWindowLongPtr(hwndDlg, GWL_EXSTYLE,
184 GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_APPWINDOW);
185
186 /* Center dialog window in the screen. Not done for multi-monitor systems, where
187 * it is likely to end up split across the screens. In that case, it appears
188 * near the Tray icon.
189 */
190 if (GetSystemMetrics(SM_CMONITORS) > 1) {
191 /* Still need to refresh the frame change. */
192 SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0,
193 SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
194 }
195 else {
196 GetWindowRect(hwndDesk, &rcDesk);
197 GetWindowRect(hwndDlg, &rcDlg);
198 CopyRect(&rc, &rcDesk);
199
200 OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
201 OffsetRect(&rc, -rc.left, -rc.top);
202 OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
203
204 SetWindowPos(hwndDlg,
205 HWND_TOPMOST,
206 rcDesk.left + (rc.right / 2),
207 rcDesk.top + (rc.bottom / 2),
208 0, 0, SWP_NOSIZE | SWP_FRAMECHANGED);
209 }
210
211#ifdef XWIN_MULTIWINDOW
212 if (g_hIconX)
213 hIcon = g_hIconX;
214 else
215#endif
216 hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_XWIN));
217
218#ifdef XWIN_MULTIWINDOW
219 if (g_hSmallIconX)
220 hIconSmall = g_hSmallIconX;
221 else
222#endif
223 hIconSmall = LoadImage(g_hInstance,
224 MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON,
225 GetSystemMetrics(SM_CXSMICON),
226 GetSystemMetrics(SM_CYSMICON), LR_SHARED);
227
228 PostMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
229 PostMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
230}
231
232/*
233 * Display the Exit dialog box
234 */
235
236void
237winDisplayExitDialog(winPrivScreenPtr pScreenPriv)
238{
239 int i;
240 int liveClients = 0;
241
242 /* Count up running clients (clients[0] is serverClient) */
243 for (i = 1; i < currentMaxClients; i++)
244 if (clients[i] != NullClient)
245 liveClients++;
246#if defined(XWIN_MULTIWINDOW)
247 /* Count down server internal clients */
248 if (pScreenPriv->pScreenInfo->fMultiWindow)
249 liveClients -= 2; /* multiwindow window manager & XMsgProc */
250#endif
251#if defined(XWIN_CLIPBOARD)
252 if (g_fClipboardStarted)
253 liveClients--; /* clipboard manager */
254#endif
255
256 /* A user reported that this sometimes drops below zero. just eye-candy. */
257 if (liveClients < 0)
258 liveClients = 0;
259
260 /* Don't show the exit confirmation dialog if SilentExit & no clients,
261 or ForceExit, is enabled */
262 if ((pref.fSilentExit && liveClients <= 0) || pref.fForceExit) {
263 if (g_hDlgExit != NULL) {
264 DestroyWindow(g_hDlgExit);
265 g_hDlgExit = NULL;
266 }
267 PostMessage(pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
268 return;
269 }
270
271 pScreenPriv->iConnectedClients = liveClients;
272
273 /* Check if dialog already exists */
274 if (g_hDlgExit != NULL) {
275 /* Dialog box already exists, display it */
276 ShowWindow(g_hDlgExit, SW_SHOWDEFAULT);
277
278 /* User has lost the dialog. Show them where it is. */
279 SetForegroundWindow(g_hDlgExit);
280
281 return;
282 }
283
284 /* Create dialog box */
285 g_hDlgExit = CreateDialogParam(g_hInstance,
286 "EXIT_DIALOG",
287 pScreenPriv->hwndScreen,
288 winExitDlgProc, (LPARAM) pScreenPriv);
289
290 /* Show the dialog box */
291 ShowWindow(g_hDlgExit, SW_SHOW);
292
293 /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
294 SetForegroundWindow(g_hDlgExit);
295
296 /* Set focus to the Cancel button */
297 PostMessage(g_hDlgExit, WM_NEXTDLGCTL,
298 (WPARAM) GetDlgItem(g_hDlgExit, IDCANCEL), TRUE);
299}
300
301#define CONNECTED_CLIENTS_FORMAT "There %s currently %d client%s connected."
302
303/*
304 * Exit dialog window procedure
305 */
306
307static INT_PTR CALLBACK
308winExitDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
309{
310 static winPrivScreenPtr s_pScreenPriv = NULL;
311
312 /* Branch on message type */
313 switch (message) {
314 case WM_INITDIALOG:
315 {
316 char *pszConnectedClients;
317
318 /* Store pointers to private structures for future use */
319 s_pScreenPriv = (winPrivScreenPtr) lParam;
320
321 winInitDialog(hDialog);
322
323 /* Format the connected clients string */
324 if (asprintf(&pszConnectedClients, CONNECTED_CLIENTS_FORMAT,
325 (s_pScreenPriv->iConnectedClients == 1) ? "is" : "are",
326 s_pScreenPriv->iConnectedClients,
327 (s_pScreenPriv->iConnectedClients == 1) ? "" : "s") == -1)
328 return TRUE;
329
330 /* Set the number of connected clients */
331 SetWindowText(GetDlgItem(hDialog, IDC_CLIENTS_CONNECTED),
332 pszConnectedClients);
333 free(pszConnectedClients);
334 }
335 return TRUE;
336
337 case WM_COMMAND:
338 switch (LOWORD(wParam)) {
339 case IDOK:
340 /* Send message to call the GiveUp function */
341 PostMessage(s_pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
342 DestroyWindow(g_hDlgExit);
343 g_hDlgExit = NULL;
344
345 /* Fix to make sure keyboard focus isn't trapped */
346 PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
347 return TRUE;
348
349 case IDCANCEL:
350 DestroyWindow(g_hDlgExit);
351 g_hDlgExit = NULL;
352
353 /* Fix to make sure keyboard focus isn't trapped */
354 PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
355 return TRUE;
356 }
357 break;
358
359 case WM_MOUSEMOVE:
360 case WM_NCMOUSEMOVE:
361 /* Show the cursor if it is hidden */
362 if (g_fSoftwareCursor && !g_fCursor) {
363 g_fCursor = TRUE;
364 ShowCursor(TRUE);
365 }
366 return TRUE;
367
368 case WM_CLOSE:
369 DestroyWindow(g_hDlgExit);
370 g_hDlgExit = NULL;
371
372 /* Fix to make sure keyboard focus isn't trapped */
373 PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
374 return TRUE;
375 }
376
377 return FALSE;
378}
379
380/*
381 * Display the Depth Change dialog box
382 */
383
384void
385winDisplayDepthChangeDialog(winPrivScreenPtr pScreenPriv)
386{
387 /* Check if dialog already exists */
388 if (g_hDlgDepthChange != NULL) {
389 /* Dialog box already exists, display it */
390 ShowWindow(g_hDlgDepthChange, SW_SHOWDEFAULT);
391
392 /* User has lost the dialog. Show them where it is. */
393 SetForegroundWindow(g_hDlgDepthChange);
394
395 return;
396 }
397
398 /*
399 * Display a notification to the user that the visual
400 * will not be displayed until the Windows display depth
401 * is restored to the original value.
402 */
403 g_hDlgDepthChange = CreateDialogParam(g_hInstance,
404 "DEPTH_CHANGE_BOX",
405 pScreenPriv->hwndScreen,
406 winChangeDepthDlgProc,
407 (LPARAM) pScreenPriv);
408 /* Show the dialog box */
409 ShowWindow(g_hDlgDepthChange, SW_SHOW);
410
411 if (!g_hDlgDepthChange)
412 ErrorF("winDisplayDepthChangeDialog - GetLastError: %d\n",
413 (int) GetLastError());
414
415 /* Minimize the display window */
416 ShowWindow(pScreenPriv->hwndScreen, SW_MINIMIZE);
417}
418
419/*
420 * Process messages for the dialog that is displayed for
421 * disruptive screen depth changes.
422 */
423
424static INT_PTR CALLBACK
425winChangeDepthDlgProc(HWND hwndDialog, UINT message,
426 WPARAM wParam, LPARAM lParam)
427{
428 static winPrivScreenPtr s_pScreenPriv = NULL;
429 static winScreenInfo *s_pScreenInfo = NULL;
430
431#if CYGDEBUG
432 winDebug("winChangeDepthDlgProc\n");
433#endif
434
435 /* Branch on message type */
436 switch (message) {
437 case WM_INITDIALOG:
438#if CYGDEBUG
439 winDebug("winChangeDepthDlgProc - WM_INITDIALOG\n");
440#endif
441
442 /* Store pointers to private structures for future use */
443 s_pScreenPriv = (winPrivScreenPtr) lParam;
444 s_pScreenInfo = s_pScreenPriv->pScreenInfo;
445
446#if CYGDEBUG
447 winDebug("winChangeDepthDlgProc - WM_INITDIALOG - s_pScreenPriv: %08x, "
448 "s_pScreenInfo: %08x\n",
449 s_pScreenPriv, s_pScreenInfo);
450#endif
451
452#if CYGDEBUG
453 winDebug("winChangeDepthDlgProc - WM_INITDIALOG - orig bpp: %d, "
454 "current bpp: %d\n",
455 s_pScreenInfo->dwBPP,
456 GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL));
457#endif
458
459 winInitDialog(hwndDialog);
460
461 return TRUE;
462
463 case WM_DISPLAYCHANGE:
464#if CYGDEBUG
465 winDebug("winChangeDepthDlgProc - WM_DISPLAYCHANGE - orig bpp: %d, "
466 "new bpp: %d\n",
467 s_pScreenInfo->dwBPP,
468 GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL));
469#endif
470
471 /* Dismiss the dialog if the display returns to the original depth */
472 if (GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL) ==
473 s_pScreenInfo->dwBPP) {
474 ErrorF("winChangeDelthDlgProc - wParam == s_pScreenInfo->dwBPP\n");
475
476 /* Depth has been restored, dismiss dialog */
477 DestroyWindow(g_hDlgDepthChange);
478 g_hDlgDepthChange = NULL;
479
480 /* Flag that we have a valid screen depth */
481 s_pScreenPriv->fBadDepth = FALSE;
482 }
483 return TRUE;
484
485 case WM_COMMAND:
486 switch (LOWORD(wParam)) {
487 case IDOK:
488 case IDCANCEL:
489 winDebug("winChangeDepthDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
490
491 /*
492 * User dismissed the dialog, hide it until the
493 * display mode is restored.
494 */
495 ShowWindow(g_hDlgDepthChange, SW_HIDE);
496 return TRUE;
497 }
498 break;
499
500 case WM_CLOSE:
501 winDebug("winChangeDepthDlgProc - WM_CLOSE\n");
502
503 DestroyWindow(g_hDlgAbout);
504 g_hDlgAbout = NULL;
505
506 /* Fix to make sure keyboard focus isn't trapped */
507 PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
508 return TRUE;
509 }
510
511 return FALSE;
512}
513
514/*
515 * Display the About dialog box
516 */
517
518void
519winDisplayAboutDialog(winPrivScreenPtr pScreenPriv)
520{
521 /* Check if dialog already exists */
522 if (g_hDlgAbout != NULL) {
523 /* Dialog box already exists, display it */
524 ShowWindow(g_hDlgAbout, SW_SHOWDEFAULT);
525
526 /* User has lost the dialog. Show them where it is. */
527 SetForegroundWindow(g_hDlgAbout);
528
529 return;
530 }
531
532 /*
533 * Display the about box
534 */
535 g_hDlgAbout = CreateDialogParam(g_hInstance,
536 "ABOUT_BOX",
537 pScreenPriv->hwndScreen,
538 winAboutDlgProc, (LPARAM) pScreenPriv);
539
540 /* Show the dialog box */
541 ShowWindow(g_hDlgAbout, SW_SHOW);
542
543 /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
544 SetForegroundWindow(g_hDlgAbout);
545
546 /* Set focus to the OK button */
547 PostMessage(g_hDlgAbout, WM_NEXTDLGCTL,
548 (WPARAM) GetDlgItem(g_hDlgAbout, IDOK), TRUE);
549}
550
551/*
552 * Process messages for the about dialog.
553 */
554
555static INT_PTR CALLBACK
556winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
557{
558 static winPrivScreenPtr s_pScreenPriv = NULL;
559
560#if CYGDEBUG
561 winDebug("winAboutDlgProc\n");
562#endif
563
564 /* Branch on message type */
565 switch (message) {
566 case WM_INITDIALOG:
567#if CYGDEBUG
568 winDebug("winAboutDlgProc - WM_INITDIALOG\n");
569#endif
570
571 /* Store pointer to private structure for future use */
572 s_pScreenPriv = (winPrivScreenPtr) lParam;
573
574 winInitDialog(hwndDialog);
575
576 /* Override the URL buttons */
577 winOverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
578 winOverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
579 winOverrideURLButton(hwndDialog, ID_ABOUT_UG);
580 winOverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
581
582 return TRUE;
583
584 case WM_DRAWITEM:
585 /* Draw the URL buttons as needed */
586 winDrawURLWindow(lParam);
587 return TRUE;
588
589 case WM_MOUSEMOVE:
590 case WM_NCMOUSEMOVE:
591 /* Show the cursor if it is hidden */
592 if (g_fSoftwareCursor && !g_fCursor) {
593 g_fCursor = TRUE;
594 ShowCursor(TRUE);
595 }
596 return TRUE;
597
598 case WM_COMMAND:
599 switch (LOWORD(wParam)) {
600 case IDOK:
601 case IDCANCEL:
602 winDebug("winAboutDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
603
604 DestroyWindow(g_hDlgAbout);
605 g_hDlgAbout = NULL;
606
607 /* Fix to make sure keyboard focus isn't trapped */
608 PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
609
610 /* Restore window procedures for URL buttons */
611 winUnoverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
612 winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
613 winUnoverrideURLButton(hwndDialog, ID_ABOUT_UG);
614 winUnoverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
615
616 return TRUE;
617
618 case ID_ABOUT_CHANGELOG:
619 {
620 INT_PTR iReturn;
621
622 const char *pszWinPath = "http://x.cygwin.com/"
623 "devel/server/changelog.html";
624
625 iReturn = (INT_PTR) ShellExecute(NULL,
626 "open",
627 pszWinPath, NULL, NULL, SW_MAXIMIZE);
628 if (iReturn < 32) {
629 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_CHANGELOG - "
630 "ShellExecute failed: %d\n", (int)iReturn);
631 }
632 }
633 return TRUE;
634
635 case ID_ABOUT_WEBSITE:
636 {
637 const char *pszPath = __VENDORDWEBSUPPORT__;
638 INT_PTR iReturn;
639
640 iReturn = (INT_PTR) ShellExecute(NULL,
641 "open",
642 pszPath, NULL, NULL, SW_MAXIMIZE);
643 if (iReturn < 32) {
644 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_WEBSITE - "
645 "ShellExecute failed: %d\n", (int)iReturn);
646
647 }
648 }
649 return TRUE;
650
651 case ID_ABOUT_UG:
652 {
653 const char *pszPath = "http://x.cygwin.com/docs/ug/";
654 INT_PTR iReturn;
655
656 iReturn = (INT_PTR) ShellExecute(NULL,
657 "open",
658 pszPath, NULL, NULL, SW_MAXIMIZE);
659 if (iReturn < 32) {
660 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_UG - "
661 "ShellExecute failed: %d\n", (int)iReturn);
662 }
663 }
664 return TRUE;
665
666 case ID_ABOUT_FAQ:
667 {
668 const char *pszPath = "http://x.cygwin.com/docs/faq/";
669 INT_PTR iReturn;
670
671 iReturn = (INT_PTR) ShellExecute(NULL,
672 "open",
673 pszPath, NULL, NULL, SW_MAXIMIZE);
674 if (iReturn < 32) {
675 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_FAQ - "
676 "ShellExecute failed: %d\n", (int)iReturn);
677 }
678 }
679 return TRUE;
680 }
681 break;
682
683 case WM_CLOSE:
684 winDebug("winAboutDlgProc - WM_CLOSE\n");
685
686 DestroyWindow(g_hDlgAbout);
687 g_hDlgAbout = NULL;
688
689 /* Fix to make sure keyboard focus isn't trapped */
690 PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
691
692 /* Restore window procedures for URL buttons */
693 winUnoverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
694 winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
695 winUnoverrideURLButton(hwndDialog, ID_ABOUT_UG);
696 winUnoverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
697
698 return TRUE;
699 }
700
701 return FALSE;
702}