Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / WINNT / afsapplib / al_wizard.cpp
1 extern "C" {
2 #include <afs/param.h>
3 #include <afs/stds.h>
4 }
5
6 #include <WINNT/al_wizard.h>
7
8
9 /*
10  * DEFINITIONS ________________________________________________________________
11  *
12  */
13
14 #define REFRESH_LEFT_PANE   0x00000001
15 #define REFRESH_RIGHT_PANE  0x00000002
16
17 #define cxRECT(_r)  ((_r).right - (_r).left)
18 #define cyRECT(_r)  ((_r).bottom - (_r).top)
19
20 #define clrWASH_SOLID       RGB(0,0,128)
21 #define clrWASH_BRIGHTEST   RGB(0,0,252)
22 #define clrWASH_DARKEST     RGB(0,0,4)
23 #define clrWASH_INCREMENT   RGB(0,0,4)
24 #define clrWASH_TEXT_BG     RGB(0,0,0)
25 #define clrWASH_TEXT_FG     RGB(255,255,255)
26
27 #define ToPALETTERGB(_rgb)  PALETTERGB(GetRValue(_rgb),GetGValue(_rgb),GetBValue(_rgb))
28
29 #define cxLEFT_BACKGROUND    20
30 #define cxRIGHT_BACKGROUND   20
31 #define cyTOP_BACKGROUND     20
32 #define cyBOTTOM_BACKGROUND  20
33
34 #define xTEXT                30
35 #define yTEXT                30
36 #define cxSHADOW              2
37 #define cySHADOW              2
38
39 #define cptWASH_TEXT_SIZE    20
40
41
42 /*
43  * PROTOTYPES _________________________________________________________________
44  *
45  */
46
47 static void MoveRect (RECT *_pr, LONG _dx, LONG _dy);
48 static void GetRectInParent (HWND hWnd, RECT *pr);
49
50
51 /*
52  * ROUTINES ___________________________________________________________________
53  *
54  */
55
56
57 WIZARD::WIZARD (void)
58 {
59    m_iddTemplate = -1;
60    m_idcLeftPane = -1;
61    m_idcRightPane = -1;
62    m_idcBack = -1;
63    m_idcNext = -1;
64    m_idbGraphic16 = -1;
65    m_bmpGraphic16 = NULL;
66    m_idbGraphic256 = -1;
67    m_bmpGraphic256 = NULL;
68    m_palGraphic = NULL;
69    m_aStates = NULL;
70    m_cStates = 0;
71    m_stCurrent = -1;
72    m_fShowing = FALSE;
73    m_hWnd = NULL;
74
75    m_iddBackground = -1;
76    m_hBkg = NULL;
77    m_fBlue = TRUE;
78    m_fnBackground = NULL;
79    m_szBackground[0] = TEXT('\0');
80    m_bmpBackground = NULL;
81    m_pfnCallback = NULL;
82    m_bmpBuffer = NULL;
83    SetRectEmpty (&m_rBuffer);
84
85    HDC hdc = GetDC (NULL);
86    LOGFONT lf;
87    memset (&lf, 0x00, sizeof(lf));
88    GetObject (GetStockObject (DEFAULT_GUI_FONT), sizeof(lf), &lf);
89    lf.lfHeight = -MulDiv (cptWASH_TEXT_SIZE, GetDeviceCaps (hdc, LOGPIXELSY), 72);
90    lf.lfWidth = 0;
91    m_hfBackground = CreateFontIndirect (&lf);
92    ReleaseDC (NULL, hdc);
93
94    GeneratePalette();
95 }
96
97
98 WIZARD::~WIZARD (void)
99 {
100    if (m_hWnd && IsWindow (m_hWnd))
101       DestroyWindow (m_hWnd);
102    if (m_bmpGraphic16 != NULL)
103       DeleteObject (m_bmpGraphic16);
104    if (m_bmpGraphic256 != NULL)
105       DeleteObject (m_bmpGraphic256);
106    if (m_bmpBuffer != NULL)
107       DeleteObject (m_bmpBuffer);
108    if (m_palGraphic != NULL)
109       DeleteObject (m_palGraphic);
110    if (m_bmpBackground != NULL)
111       DeleteObject (m_bmpBackground);
112    if (m_hfBackground != NULL)
113       DeleteObject (m_hfBackground);
114 }
115
116
117 HWND WIZARD::GetWindow (void)
118 {
119    if (m_hWnd && IsWindow (m_hWnd))
120       return m_hWnd;
121    return NULL;
122 }
123
124
125 LPWIZARD WIZARD::GetWizard (HWND hWnd)
126 {
127    LPWIZARD pWiz = NULL;
128
129    try {
130       if ((pWiz = (LPWIZARD)GetWindowLong (hWnd, DWL_USER)) != NULL)
131          {
132          if ( (pWiz->m_hWnd != hWnd) && (pWiz->m_hBkg != hWnd) )
133             pWiz = NULL;
134          }
135    } catch(...) {
136       pWiz = NULL;
137    }
138
139    return pWiz;
140 }
141
142
143 void WIZARD::SetDialogTemplate (int iddTemplate, int idcLeftPane, int idcRightPane, int idcBack, int idcNext)
144 {
145    m_iddTemplate = iddTemplate;
146    m_idcLeftPane = idcLeftPane;
147    m_idcRightPane = idcRightPane;
148    m_idcBack = idcBack;
149    m_idcNext = idcNext;
150
151    if (m_fShowing)
152       {
153       Show (FALSE);
154       Show (TRUE);
155       }
156 }
157
158
159 void WIZARD::SetGraphic (int idbGraphic16, int idbGraphic256)
160 {
161    LPRGBQUAD pargb = NULL;
162
163    m_idbGraphic16 = idbGraphic16;
164    m_idbGraphic256 = idbGraphic256;
165
166    if (m_bmpGraphic16 != NULL)
167       {
168       DeleteObject (m_bmpGraphic16);
169       m_bmpGraphic16 = NULL;
170       }
171
172    if (m_bmpGraphic256 != NULL)
173       {
174       DeleteObject (m_bmpGraphic256);
175       m_bmpGraphic256 = NULL;
176       }
177
178    if (m_palGraphic != NULL)
179       {
180       DeleteObject (m_palGraphic);
181       m_palGraphic = NULL;
182       }
183
184    m_bmpGraphic16 = (HBITMAP)TaLocale_LoadImage (idbGraphic16, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
185
186    if ((m_bmpGraphic256 = (HBITMAP)TaLocale_LoadImage (idbGraphic256, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION)) != NULL)
187       {
188       BITMAP bm;
189       GetObject (m_bmpGraphic256, sizeof(BITMAP), &bm);
190
191       if ((bm.bmBitsPixel * bm.bmPlanes) == 8)
192          {
193          HDC hdc = CreateCompatibleDC (NULL);
194          HBITMAP bmpOld = (HBITMAP)SelectObject (hdc, m_bmpGraphic256);
195
196          RGBQUAD argb[256];
197          GetDIBColorTable (hdc, 0, 256, argb);
198          pargb = argb;
199
200          SelectObject (hdc, bmpOld);
201          DeleteDC (hdc);
202          }
203       }
204
205    GeneratePalette (pargb);
206
207    if (m_fShowing)
208       {
209       Refresh (REFRESH_LEFT_PANE);
210       }
211 }
212
213
214 void WIZARD::SetGraphicCallback (void (CALLBACK *pfnCallback)(LPWIZARD pWiz, HDC hdcTarget, LPRECT prTarget, HPALETTE hPal))
215 {
216    m_pfnCallback = pfnCallback;
217
218    if (m_fShowing)
219       {
220       Refresh (REFRESH_LEFT_PANE);
221       }
222 }
223
224
225 void WIZARD::SetStates (LPWIZARD_STATE aStates, size_t cStates)
226 {
227    m_aStates = aStates;
228    m_cStates = cStates;
229
230    if (m_fShowing)
231       {
232       Refresh (REFRESH_RIGHT_PANE);
233       }
234 }
235
236
237 int WIZARD::GetState (void)
238 {
239    return m_stCurrent;
240 }
241
242
243 void WIZARD::SetState (int stNew, BOOL fForce)
244 {
245    SendStateCommand (m_stCurrent, wcSTATE_LEAVE);
246
247    int stOriginal = m_stCurrent;
248    m_stCurrent = stNew;
249
250    if (!fForce && SendStateCommand (stNew, wcIS_STATE_DISABLED))
251       {
252       if (stOriginal <= stNew)
253          {
254          for (int st = stNew+1; st < (int)m_cStates; ++st)
255             {
256             LPWIZARD_STATE pState;
257             if ((pState = FindState (st)) != NULL)
258                {
259                m_stCurrent = st;
260                if (!SendStateCommand (st, wcIS_STATE_DISABLED))
261                   break;
262                m_stCurrent = stOriginal;
263                SendStateCommand (st, wcSTATE_ENTER);
264                SendStateCommand (st, wcSTATE_LEAVE);
265                }
266             }
267          stNew = (st < (int)m_cStates) ? st : m_stCurrent;
268          }
269       else // (moving backwards?)
270          {
271          for (int st = stNew-1; st >= 0; --st)
272             {
273             LPWIZARD_STATE pState;
274             if ((pState = FindState (st)) != NULL)
275                {
276                m_stCurrent = st;
277                if (!SendStateCommand (st, wcIS_STATE_DISABLED))
278                   break;
279                m_stCurrent = stOriginal;
280                SendStateCommand (st, wcSTATE_ENTER);
281                SendStateCommand (st, wcSTATE_LEAVE);
282                }
283             }
284          stNew = (st >= 0) ? st : m_stCurrent;
285          }
286       }
287
288    m_stCurrent = stNew;
289
290    SendStateCommand (m_stCurrent, wcSTATE_ENTER);
291
292    if (m_fShowing)
293       {
294       Refresh (REFRESH_RIGHT_PANE);
295       }
296 }
297
298
299 BOOL WIZARD::Show (BOOL fShowReq)
300 {
301    if (m_fShowing && !fShowReq)
302       {
303       m_fShowing = FALSE;
304       if (m_hWnd && IsWindow (m_hWnd))
305          DestroyWindow (m_hWnd);
306       m_hWnd = NULL;
307       }
308    else if (!m_fShowing && fShowReq)
309       {
310       if (m_iddTemplate == -1)
311          return FALSE;
312       if (m_idcLeftPane == -1)
313          return FALSE;
314       if (m_idcRightPane == -1)
315          return FALSE;
316       if (m_idcBack == -1)
317          return FALSE;
318       if (m_idcNext == -1)
319          return FALSE;
320
321       if ((m_hWnd = ModelessDialogParam (m_iddTemplate, m_hBkg, (DLGPROC)WIZARD::Template_DlgProc, (LPARAM)this)) == NULL)
322          return FALSE;
323       m_fShowing = TRUE;
324
325       MSG msg;
326       while (GetMessage (&msg, 0, 0, NULL))
327          {
328          if (!IsDialogMessage (m_hWnd, &msg))
329             {
330             TranslateMessage (&msg);
331             DispatchMessage (&msg);
332             }
333
334          if (!m_fShowing || !m_hWnd || !IsWindow (m_hWnd))
335             break;
336          }
337       }
338
339    return TRUE;
340 }
341
342
343 void WIZARD::EnableButton (int idcButton, BOOL fEnable)
344 {
345    EnableWindow (GetDlgItem (m_hWnd, idcButton), fEnable);
346 }
347
348
349 void WIZARD::EnableButtons (DWORD dwButtonFlags)
350 {
351    EnableWindow (GetDlgItem (m_hWnd, m_idcBack), (dwButtonFlags & BACK_BUTTON) ? TRUE : FALSE);
352    EnableWindow (GetDlgItem (m_hWnd, m_idcNext), (dwButtonFlags & NEXT_BUTTON) ? TRUE : FALSE);
353 }
354
355
356 void WIZARD::SetButtonText (int idcButton, int idsText)
357 {
358    HWND hButton;
359    if ((hButton = GetDlgItem (m_hWnd, idcButton)) != NULL)
360       {
361       TCHAR szText[ cchRESOURCE ];
362       GetString (szText, idsText);
363       SetWindowText (hButton, szText);
364       }
365 }
366
367
368 void WIZARD::SetDefaultControl (int idc)
369 {
370    HWND hControl;
371    if ((hControl = GetDlgItem (m_hWnd, idc)) == NULL)
372       {
373       HWND hRHS;
374       if ((hRHS = GetRightHandWindow()) != NULL)
375          hControl = GetDlgItem (hRHS, idc);
376       }
377
378    if (hControl)
379       {
380       PostMessage (m_hWnd, WM_NEXTDLGCTL, (WPARAM)hControl, TRUE);
381       }
382 }
383
384
385 void WIZARD::SetBackground (int iddBackground, BOOL fBlue, DLGPROC dlgproc)
386 {
387    m_iddBackground = iddBackground;
388    m_fBlue = fBlue;
389    m_fnBackground = dlgproc;
390
391    if (m_hBkg && IsWindow (m_hBkg))
392       {
393       ShowBackground (FALSE);
394       ShowBackground (TRUE);
395       }
396 }
397
398
399 void WIZARD::SetBackgroundText (int idsText, HFONT hf)
400 {
401    GetString (m_szBackground, idsText);
402
403    if ((hf != NULL) && (hf != m_hfBackground))
404       {
405       if (m_hfBackground != NULL)
406          DeleteObject (m_hfBackground);
407       m_hfBackground = hf;
408       }
409
410    if (m_hBkg && IsWindow (m_hBkg))
411       {
412       Background_OnSize();
413       }
414 }
415
416
417 void WIZARD::SetBackgroundText (LPTSTR pszText, HFONT hf)
418 {
419    if (!pszText)
420       m_szBackground[0] = TEXT('\0');
421    else
422       lstrcpy (m_szBackground, pszText);
423
424    if ((hf != NULL) && (hf != m_hfBackground))
425       {
426       if (m_hfBackground != NULL)
427          DeleteObject (m_hfBackground);
428       m_hfBackground = hf;
429       }
430
431    if (m_hBkg && IsWindow (m_hBkg))
432       {
433       Background_OnSize();
434       }
435 }
436
437
438 BOOL WIZARD::ShowBackground (BOOL fShow)
439 {
440    if (!fShow && m_hBkg && IsWindow (m_hBkg))
441       {
442       DestroyWindow (m_hBkg);
443       m_hBkg = NULL;
444       }
445    else if (fShow && !(m_hBkg && IsWindow (m_hBkg)))
446       {
447       if ((m_hBkg = ModelessDialogParam (m_iddBackground, NULL, (DLGPROC)WIZARD::Background_DlgProc, (LPARAM)this)) == NULL)
448          return FALSE;
449
450       RECT rDesktop;
451       SystemParametersInfo (SPI_GETWORKAREA, 0, &rDesktop, 0);
452
453       WINDOWPLACEMENT wpl;
454       wpl.length = sizeof(wpl);
455       wpl.flags = 0;
456       wpl.showCmd = (GetWindowLong (m_hBkg, GWL_STYLE) & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOW;
457       wpl.ptMinPosition.x = 0;
458       wpl.ptMinPosition.y = 0;
459       wpl.ptMaxPosition.x = 0;
460       wpl.ptMaxPosition.y = 0;
461       wpl.rcNormalPosition.left = rDesktop.left + cxLEFT_BACKGROUND;
462       wpl.rcNormalPosition.right = rDesktop.right - cxRIGHT_BACKGROUND;
463       wpl.rcNormalPosition.top = rDesktop.top + cyTOP_BACKGROUND;
464       wpl.rcNormalPosition.bottom = rDesktop.bottom - cyBOTTOM_BACKGROUND;
465       SetWindowPlacement (m_hBkg, &wpl);
466       }
467
468    return TRUE;
469 }
470
471
472 HWND WIZARD::GetBackgroundWindow (void)
473 {
474    return m_hBkg;
475 }
476
477
478 void WIZARD::Refresh (DWORD dwRefFlags)
479 {
480    if (dwRefFlags & REFRESH_LEFT_PANE)
481       {
482       HWND hLHS;
483       if ((hLHS = GetDlgItem (m_hWnd, m_idcLeftPane)) != NULL)
484          {
485          RECT rr;
486          GetClientRect (hLHS, &rr);
487          InvalidateRect (hLHS, &rr, TRUE);
488          UpdateWindow (hLHS);
489          }
490       }
491
492    if (dwRefFlags & REFRESH_RIGHT_PANE)
493       {
494       HWND hRHS;
495       if ((hRHS = GetDlgItem (m_hWnd, m_idcRightPane)) != NULL)
496          {
497          HWND hOld = GetRightHandWindow();
498
499          LPWIZARD_STATE pState;
500          if ((pState = FindState (m_stCurrent)) != NULL)
501             {
502             int stCurrent = m_stCurrent;
503
504             HWND hNew;
505             if ((hNew = ModelessDialogParam (pState->idd, m_hWnd, pState->dlgproc, pState->lp)) != NULL)
506                {
507                if (stCurrent != m_stCurrent)
508                   DestroyWindow (hNew);
509                else
510                   {
511                   RECT rRHS;
512                   GetRectInParent (hRHS, &rRHS);
513                   SetWindowPos (hNew, NULL, rRHS.left, rRHS.top, cxRECT(rRHS), cyRECT(rRHS), SWP_NOZORDER | SWP_NOACTIVATE);
514                   SetWindowLong (hNew, GWL_ID, pState->idd);
515
516                   ShowWindow (hNew, SW_SHOW);
517                   ShowWindow (hRHS, SW_HIDE);
518                   }
519                }
520             }
521
522          if (hOld != NULL)
523             DestroyWindow (hOld);
524          }
525       }
526 }
527
528
529 HWND WIZARD::GetRightHandWindow (void)
530 {
531    if (!m_fShowing || !m_hWnd || !IsWindow (m_hWnd))
532       return NULL;
533
534    HWND hRHS = NULL;
535
536    for (HWND hFound = ::GetWindow (m_hWnd, GW_CHILD);
537         hFound != NULL;
538         hFound = ::GetWindow (hFound, GW_HWNDNEXT))
539       {
540       TCHAR szClassName[ cchRESOURCE ];
541       if (GetClassName (hFound, szClassName, cchRESOURCE))
542          {
543          if (!lstrcmp (szClassName, TEXT("#32770"))) // WC_DIALOG
544             {
545             if (!hRHS || IsWindowVisible(hRHS))
546                hRHS = hFound;
547             }
548          }
549       }
550
551    return hRHS;
552 }
553
554
555 void WIZARD::GeneratePalette (LPRGBQUAD argb)
556 {
557    HDC hdc = GetDC (NULL);
558    WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
559    ReleaseDC (NULL, hdc);
560
561    if (wDepthDisplay == 8)
562       {
563       BYTE aPalBuffer[ sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY) ];
564       LPLOGPALETTE pPal = (LPLOGPALETTE)aPalBuffer;
565       pPal->palVersion = 0x300;
566       pPal->palNumEntries = 256;
567
568       for (size_t ii = 0; ii < 256; ++ii)
569          {
570          pPal->palPalEntry[ ii ].peRed   = (argb) ? argb[ ii ].rgbRed : 0;
571          pPal->palPalEntry[ ii ].peGreen = (argb) ? argb[ ii ].rgbGreen : 0;
572          pPal->palPalEntry[ ii ].peBlue  = (argb) ? argb[ ii ].rgbBlue : 0;
573          pPal->palPalEntry[ ii ].peFlags = 0;
574          }
575
576       for (COLORREF clr = clrWASH_DARKEST; clr <= clrWASH_BRIGHTEST; clr += clrWASH_INCREMENT)
577          {
578          for (size_t ii = 0; ii < 256; ++ii)
579             {
580             if ( (pPal->palPalEntry[ ii ].peRed   == GetRValue (clr)) &&
581                  (pPal->palPalEntry[ ii ].peGreen == GetGValue (clr)) &&
582                  (pPal->palPalEntry[ ii ].peBlue  == GetBValue (clr)) )
583                break;
584             }
585          if (ii == 256)
586             {
587             for (size_t ii = 10; ii < 246; ++ii)
588                {
589                if ( (pPal->palPalEntry[ ii ].peRed == 0) &&
590                     (pPal->palPalEntry[ ii ].peGreen == 0) &&
591                     (pPal->palPalEntry[ ii ].peBlue == 0) )
592                   break;
593                if ( (pPal->palPalEntry[ ii ].peRed == 255) &&
594                     (pPal->palPalEntry[ ii ].peGreen == 255) &&
595                     (pPal->palPalEntry[ ii ].peBlue == 255) )
596                   break;
597                }
598             if (ii == 246)
599                break;
600
601             pPal->palPalEntry[ ii ].peRed   = GetRValue (clr);
602             pPal->palPalEntry[ ii ].peGreen = GetGValue (clr);
603             pPal->palPalEntry[ ii ].peBlue  = GetBValue (clr);
604             }
605          }
606
607       m_palGraphic = CreatePalette (pPal);
608       }
609 }
610
611
612 LPWIZARD_STATE WIZARD::FindState (int stFind)
613 {
614    for (size_t ii = 0; ii < m_cStates; ++ii)
615       {
616       if (m_aStates[ ii ].st == stFind)
617          return &m_aStates[ ii ];
618       }
619    return NULL;
620 }
621
622
623 BOOL WIZARD::SendStateCommand (int st, WIZARD_COMMAND wc)
624 {
625    BOOL rc = FALSE;
626
627    LPWIZARD_STATE pState;
628    if ((pState = FindState (st)) != NULL)
629       {
630       rc = CallWindowProc ((WNDPROC)(pState->dlgproc), NULL, WM_COMMAND, MAKEWPARAM(IDC_WIZARD,(WORD)wc), (LPARAM)this);
631       }
632
633    return rc;
634 }
635
636
637 BOOL CALLBACK WIZARD::Template_DlgProc (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
638 {
639    if (msg == WM_INITDIALOG)
640       SetWindowLong (hWnd, DWL_USER, lp);
641
642    LPWIZARD pWiz = (LPWIZARD)GetWindowLong (hWnd, DWL_USER);
643
644    switch (msg)
645       {
646       case WM_INITDIALOG:
647          if (pWiz)
648             pWiz->Template_OnInitDialog (hWnd);
649          break;
650
651       case WM_DESTROY:
652          if (pWiz && (pWiz->m_hWnd == hWnd))
653             pWiz->Show (FALSE);
654          break;
655
656       case WM_COMMAND:
657          return pWiz->Template_ForwardMessage (hWnd, msg, wp, lp);
658       }
659
660    return FALSE;
661 }
662
663
664 BOOL CALLBACK WIZARD::Template_LeftPaneHook (HWND hLHS, UINT msg, WPARAM wp, LPARAM lp)
665 {
666    PVOID oldProc = Subclass_FindNextHook (hLHS, WIZARD::Template_LeftPaneHook);
667
668    switch (msg)
669       {
670       case WM_PAINT:
671          LPWIZARD pWiz;
672          if ((pWiz = WIZARD::GetWizard (GetParent (hLHS))) != NULL)
673             {
674             if (pWiz->Template_OnPaintLHS (hLHS))
675                return TRUE;
676             }
677          break;
678
679       case WM_DESTROY:
680          Subclass_RemoveHook (hLHS, WIZARD::Template_LeftPaneHook);
681          break;
682       }
683
684    if (oldProc)
685       return CallWindowProc ((WNDPROC)oldProc, hLHS, msg, wp, lp);
686    else
687       return DefWindowProc (hLHS, msg, wp, lp);
688 }
689
690
691 BOOL WIZARD::Template_ForwardMessage (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
692 {
693    HWND hRHS;
694    if ((hRHS = GetRightHandWindow()) != NULL)
695       return SendMessage (hRHS, msg, wp, lp);
696
697    LPWIZARD_STATE pState;
698    if ((pState = FindState (m_stCurrent)) != NULL)
699       return CallWindowProc ((WNDPROC)(pState->dlgproc), hWnd, msg, wp, lp);
700
701    return FALSE;
702 }
703
704
705 void WIZARD::Template_OnInitDialog (HWND hWnd)
706 {
707    m_hWnd = hWnd;
708    m_fShowing = TRUE;
709
710    HWND hLHS;
711    if ((hLHS = GetDlgItem (m_hWnd, m_idcLeftPane)) != NULL)
712       {
713       Subclass_AddHook (hLHS, WIZARD::Template_LeftPaneHook);
714       }
715
716    HWND hRHS;
717    if ((hRHS = GetDlgItem (m_hWnd, m_idcRightPane)) != NULL)
718       {
719       ShowWindow (hRHS, SW_HIDE);
720       }
721
722    Refresh (REFRESH_RIGHT_PANE);
723
724    ShowWindow (m_hWnd, SW_SHOW);
725 }
726
727
728 BOOL WIZARD::Template_OnPaintLHS (HWND hLHS)
729 {
730    BOOL fShow16 = FALSE;
731    BOOL fShow256 = FALSE;
732
733    HDC hdc = GetDC (NULL);
734    WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
735    ReleaseDC (NULL, hdc);
736
737    if ( (m_bmpGraphic256 != NULL) && (wDepthDisplay >= 8) )
738       fShow256 = TRUE;
739    else if (m_bmpGraphic16 != NULL)
740       fShow16 = TRUE;
741    else
742       return FALSE;
743
744    PAINTSTRUCT ps;
745    HDC hdcTarget;
746    if ((hdcTarget = BeginPaint (hLHS, &ps)) != NULL)
747       {
748       HBITMAP bmpSource = (fShow256) ? m_bmpGraphic256 : m_bmpGraphic16;
749
750       BITMAP bm;
751       GetObject (bmpSource, sizeof(BITMAP), &bm);
752
753       RECT rWindow;
754       GetClientRect (hLHS, &rWindow);
755
756       RECT rSource = { 0, 0, bm.bmWidth, bm.bmHeight };
757       RECT rTarget = rWindow;
758
759       if (cxRECT(rSource) > cxRECT(rTarget))
760          {
761          MoveRect (&rSource, (cxRECT(rSource) - cxRECT(rTarget)) / 2, 0);
762          rSource.right = rSource.left + cxRECT(rTarget);
763          }
764       else if (cxRECT(rSource) < cxRECT(rTarget))
765          {
766          MoveRect (&rTarget, (cxRECT(rTarget) - cxRECT(rSource)) / 2, 0);
767          }
768
769       if (cyRECT(rSource) > cyRECT(rTarget))
770          {
771          MoveRect (&rSource, 0, (cyRECT(rSource) - cyRECT(rTarget)) / 2);
772          rSource.bottom = rSource.top + cyRECT(rTarget);
773          }
774       else if (cyRECT(rSource) < cyRECT(rTarget))
775          {
776          MoveRect (&rTarget, 0, (cyRECT(rTarget) - cyRECT(rSource)) / 2);
777          }
778       rTarget.right = rTarget.left + cxRECT(rSource);
779       rTarget.bottom = rTarget.top + cyRECT(rSource);
780
781       // If the user has supplied a custom draw-proc, then we should
782       // do our rendering to an off-screen bitmap.
783       //
784       HDC hdcFinalTarget = NULL;
785       HBITMAP bmpTempTarget = NULL;
786       if (m_pfnCallback)
787          {
788          // First make sure our offscreen buffer is large enough
789          //
790          if (!m_bmpBuffer || (cxRECT(m_rBuffer) < cxRECT(rWindow)) || (cyRECT(m_rBuffer) < cyRECT(rWindow)))
791             {
792             if (m_bmpBuffer != NULL)
793                DeleteObject (m_bmpBuffer);
794             if ((m_bmpBuffer = CreateCompatibleBitmap (hdcTarget, cxRECT(rWindow), cyRECT(rWindow))) != NULL)
795                {
796                m_rBuffer.right = cxRECT(rWindow);  // m_rBuffer.left=already 0
797                m_rBuffer.bottom = cyRECT(rWindow); // m_rBuffer.top=already 0
798                }
799             }
800
801          // Then set up to double-buffer, if possible
802          //
803          if (m_bmpBuffer)
804             {
805             hdcFinalTarget = hdcTarget;
806             hdcTarget = CreateCompatibleDC (hdcFinalTarget);
807             bmpTempTarget = (HBITMAP)SelectObject (hdcTarget, m_bmpBuffer);
808             }
809          }
810
811       HDC hdcSource = CreateCompatibleDC (hdcTarget);
812       HBITMAP bmpOld = (HBITMAP)SelectObject (hdcSource, bmpSource);
813       HPALETTE palOld = NULL;
814       if ((wDepthDisplay == 8) && (m_palGraphic != NULL) && (fShow256))
815          {
816          palOld = SelectPalette (hdcTarget, m_palGraphic, FALSE);
817          RealizePalette (hdcTarget);
818          }
819
820       if ( (bm.bmWidth < cxRECT(rWindow)) || (bm.bmHeight < cyRECT(rWindow)) )
821          {
822          COLORREF clrFill = GetPixel (hdcSource, 0, rSource.bottom -1);
823          clrFill = ToPALETTERGB(clrFill);
824          HBRUSH hbrFill = CreateSolidBrush (clrFill);
825
826          if (bm.bmWidth < cxRECT(rWindow))
827             {
828             RECT rr;
829             rr = rWindow;
830             rr.right = rTarget.left;
831             FillRect (hdcTarget, &rr, hbrFill);
832
833             rr = rWindow;
834             rr.left = rTarget.right;
835             FillRect (hdcTarget, &rr, hbrFill);
836             }
837
838          if (bm.bmHeight < cyRECT(rWindow))
839             {
840             RECT rr;
841             rr = rWindow;
842             rr.bottom = rTarget.top;
843             FillRect (hdcTarget, &rr, hbrFill);
844
845             rr = rWindow;
846             rr.top = rTarget.bottom;
847             FillRect (hdcTarget, &rr, hbrFill);
848             }
849
850          DeleteObject (hbrFill);
851          }
852
853       BitBlt (hdcTarget, rTarget.left, rTarget.top, cxRECT(rTarget), cyRECT(rTarget), hdcSource, rSource.left, rSource.top, SRCCOPY);
854
855       // Call the user-supplied callback function (if there is one)
856       //
857       if (m_pfnCallback)
858          {
859          (*m_pfnCallback)(this, hdcTarget, &rWindow, (palOld) ? m_palGraphic : NULL);
860          }
861
862       if (palOld != NULL)
863          SelectPalette (hdcTarget, palOld, FALSE);
864
865       // If we've been drawing to an off-screen bitmap, blit the result to
866       // the display.
867       //
868       if (hdcFinalTarget)
869          {
870          BitBlt (hdcFinalTarget, rWindow.left, rWindow.top, cxRECT(rWindow), cyRECT(rWindow), hdcTarget, 0, 0, SRCCOPY);
871          SelectObject (hdcTarget, bmpTempTarget);
872          DeleteDC (hdcTarget);
873          hdcTarget = hdcFinalTarget;
874          }
875
876       SelectObject (hdcSource, bmpOld);
877       DeleteDC (hdcSource);
878
879       EndPaint (hLHS, &ps);
880       }
881
882    return TRUE;
883 }
884
885
886 void MoveRect (RECT *_pr, LONG _dx, LONG _dy)
887 {
888    _pr->left += _dx;
889    _pr->right += _dx;
890    _pr->top += _dy;
891    _pr->bottom += _dy;
892 }
893
894
895 void GetRectInParent (HWND hWnd, RECT *pr)
896 {
897    POINT pt;
898
899    GetWindowRect (hWnd, pr);
900
901    pr->right -= pr->left;
902    pr->bottom -= pr->top;       // right/bottom == width/height for now
903
904    pt.x = pr->left;
905    pt.y = pr->top;
906
907    ScreenToClient (GetParent (hWnd), &pt);
908
909    pr->left = pt.x;
910    pr->top = pt.y;
911    pr->right += pr->left;
912    pr->bottom += pr->top;
913 }
914
915
916 BOOL CALLBACK WIZARD::Background_DlgProc (HWND hBkg, UINT msg, WPARAM wp, LPARAM lp)
917 {
918    if (msg == WM_INITDIALOG)
919       SetWindowLong (hBkg, DWL_USER, lp);
920
921    LPWIZARD pWiz = (LPWIZARD)GetWindowLong (hBkg, DWL_USER);
922
923    switch (msg)
924       {
925       case WM_INITDIALOG:
926          if (pWiz)
927             pWiz->Background_OnInitDialog (hBkg);
928          break;
929
930       case WM_SIZE:
931          if (pWiz)
932             pWiz->Background_OnSize();
933          break;
934
935       case WM_DESTROY:
936          if (pWiz)
937             pWiz->Background_OnDestroy();
938          break;
939
940       case WM_COMMAND:
941          switch (LOWORD(wp))
942             {
943             case IDCANCEL:
944                if (pWiz)
945                   pWiz->Background_OnClose();
946                else
947                   DestroyWindow (hBkg);
948                break;
949             }
950          break;
951       }
952
953    if (pWiz && pWiz->m_fnBackground)
954       {
955       if (CallWindowProc ((WNDPROC)(pWiz->m_fnBackground), hBkg, msg, wp, lp))
956          return TRUE;
957       }
958
959    return FALSE;
960 }
961
962
963 BOOL CALLBACK WIZARD::Background_PaintHook (HWND hBkg, UINT msg, WPARAM wp, LPARAM lp)
964 {
965    PVOID oldProc = Subclass_FindNextHook (hBkg, WIZARD::Background_PaintHook);
966
967    switch (msg)
968       {
969       case WM_PAINT:
970          LPWIZARD pWiz;
971          if ((pWiz = WIZARD::GetWizard (hBkg)) != NULL)
972             {
973             if (pWiz->Background_OnPaint())
974                return TRUE;
975             }
976          break;
977
978       case WM_DESTROY:
979          Subclass_RemoveHook (hBkg, WIZARD::Background_PaintHook);
980          break;
981       }
982
983    if (oldProc)
984       return CallWindowProc ((WNDPROC)oldProc, hBkg, msg, wp, lp);
985    else
986       return DefWindowProc (hBkg, msg, wp, lp);
987 }
988
989
990
991 void WIZARD::Background_OnInitDialog (HWND hBkg)
992 {
993    m_hBkg = hBkg;
994    Background_OnSize();
995    Subclass_AddHook (m_hBkg, (DLGPROC)WIZARD::Background_PaintHook);
996 }
997
998
999 void WIZARD::Background_OnSize (void)
1000 {
1001    if (m_bmpBackground)
1002       {
1003       DeleteObject (m_bmpBackground);
1004       m_bmpBackground = NULL;
1005       }
1006
1007    RECT rr;
1008    GetClientRect (m_hBkg, &rr);
1009
1010    if (m_fBlue)
1011       {
1012       HDC hdc = GetDC (NULL);
1013       WORD wDepthDisplay = (WORD)GetDeviceCaps (hdc, BITSPIXEL);
1014       ReleaseDC (NULL, hdc);
1015
1016       hdc = GetDC (m_hBkg);
1017       HDC hdcTarget = CreateCompatibleDC (hdc);
1018
1019       if ((m_bmpBackground = CreateCompatibleBitmap (hdc, cxRECT(rr), cyRECT(rr))) != NULL)
1020          {
1021          HBITMAP bmpOld = (HBITMAP)SelectObject (hdcTarget, m_bmpBackground);
1022
1023          HPALETTE palOld = NULL;
1024          if (m_palGraphic)
1025             {
1026             palOld = SelectPalette (hdcTarget, m_palGraphic, FALSE);
1027             RealizePalette (hdcTarget);
1028             }
1029
1030          size_t yy = 0;
1031          size_t cy = cyRECT(rr) / ((clrWASH_BRIGHTEST - clrWASH_DARKEST) / clrWASH_INCREMENT);
1032          for (COLORREF clr = clrWASH_BRIGHTEST; clr >= clrWASH_DARKEST; clr -= clrWASH_INCREMENT)
1033             {
1034             RECT rSection = rr;
1035             rSection.top = yy;
1036             rSection.bottom = yy +cy;
1037             HBRUSH hbr = CreateSolidBrush (ToPALETTERGB(clr));
1038             FillRect (hdcTarget, &rSection, hbr);
1039             DeleteObject (hbr);
1040             yy += cy;
1041             }
1042
1043          if (m_szBackground[0] != TEXT('\0'))
1044             {
1045             HFONT hfOld = (HFONT)SelectObject (hdcTarget, m_hfBackground);
1046             COLORREF clrOld = SetTextColor (hdcTarget, clrWASH_TEXT_BG);
1047             SetBkMode (hdcTarget, TRANSPARENT);
1048
1049             RECT rText = rr;
1050             rText.left += xTEXT + cxSHADOW;
1051             rText.top += yTEXT + cySHADOW;
1052             DrawTextEx (hdcTarget, m_szBackground, lstrlen(m_szBackground), &rText, DT_NOPREFIX | DT_LEFT, NULL);
1053
1054             rText.left -= cxSHADOW;
1055             rText.top -= cySHADOW;
1056             SetTextColor (hdcTarget, clrWASH_TEXT_FG);
1057             DrawTextEx (hdcTarget, m_szBackground, lstrlen(m_szBackground), &rText, DT_NOPREFIX | DT_LEFT, NULL);
1058
1059             SetTextColor (hdcTarget, clrOld);
1060             SelectObject (hdcTarget, hfOld);
1061             }
1062
1063          if (palOld)
1064             SelectPalette (hdcTarget, palOld, FALSE);
1065
1066          SelectObject (hdcTarget, bmpOld);
1067          }
1068
1069       DeleteDC (hdcTarget);
1070       ReleaseDC (m_hBkg, hdc);
1071       }
1072
1073    InvalidateRect (m_hBkg, &rr, TRUE);
1074    UpdateWindow (m_hBkg);
1075 }
1076
1077
1078 void WIZARD::Background_OnDestroy (void)
1079 {
1080    if (m_bmpBackground)
1081       {
1082       DeleteObject (m_bmpBackground);
1083       m_bmpBackground = NULL;
1084       }
1085 }
1086
1087
1088 void WIZARD::Background_OnClose (void)
1089 {
1090    LPWIZARD_STATE pState;
1091
1092    if (m_hWnd && IsWindow (m_hWnd))
1093       {
1094       PostMessage (m_hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED), (LPARAM)GetDlgItem(m_hWnd,IDCANCEL));
1095       }
1096    else if ((pState = FindState (m_stCurrent)) != NULL)
1097       {
1098       CallWindowProc ((WNDPROC)(pState->dlgproc), m_hBkg, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED), 0);
1099       }
1100    else
1101       {
1102       ShowBackground (FALSE);
1103       }
1104 }
1105
1106
1107 BOOL WIZARD::Background_OnPaint (void)
1108 {
1109    if (!m_bmpBackground)
1110       return FALSE;
1111       
1112    PAINTSTRUCT ps;
1113    HDC hdcTarget;
1114    if ((hdcTarget = BeginPaint (m_hBkg, &ps)) != NULL)
1115       {
1116       BITMAP bm;
1117       GetObject (m_bmpBackground, sizeof(BITMAP), &bm);
1118
1119       HDC hdcSource = CreateCompatibleDC (hdcTarget);
1120       HBITMAP bmpOld = (HBITMAP)SelectObject (hdcSource, m_bmpBackground);
1121       HPALETTE palOld = NULL;
1122       if (m_palGraphic)
1123          {
1124          palOld = SelectPalette (hdcSource, m_palGraphic, FALSE);
1125          RealizePalette (hdcTarget);
1126          }
1127
1128       BitBlt (hdcTarget, 0, 0, bm.bmWidth, bm.bmHeight, hdcSource, 0, 0, SRCCOPY);
1129
1130       if (palOld != NULL)
1131          SelectPalette (hdcTarget, palOld, FALSE);
1132       SelectObject (hdcSource, bmpOld);
1133       DeleteDC (hdcSource);
1134
1135       EndPaint (m_hBkg, &ps);
1136       }
1137
1138    return TRUE;
1139 }
1140