Windows: roken.h ordering
[openafs.git] / src / WINNT / afssvrmgr / svr_window.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <winsock2.h>
11 #include <ws2tcpip.h>
12
13 extern "C" {
14 #include <afsconfig.h>
15 #include <afs/param.h>
16 #include <roken.h>
17 }
18
19 #include "svrmgr.h"
20 #include "svr_window.h"
21 #include "propcache.h"
22 #include "set_tab.h"
23 #include "agg_tab.h"
24 #include "svc_tab.h"
25 #include "display.h"
26 #include "command.h"
27
28
29 /*
30  * RESIZING WINDOWS ___________________________________________________________
31  *
32  */
33
34 #define cxMIN_SERVER 100
35 #define cyMIN_SERVER 100
36
37 static rwWindowData awdServer[] = {
38     { IDC_TABS,  raSizeX | raSizeY,     MAKELONG(cxMIN_SERVER,cyMIN_SERVER),    0 },
39     { idENDLIST, 0,                     0,                                      0 }
40  };
41
42 static rwWindowData awdTabChild[] = {
43     { 0,         raSizeX | raSizeY,     0,      0 },
44     { idENDLIST, 0,                     0,      0  }
45  };
46
47
48 /*
49  * CHILD TABS _________________________________________________________________
50  *
51  */
52
53 static struct // CHILDTABINFO
54    {
55    CHILDTAB tab;
56    int idsTabTitle;
57    int iImage;
58    }
59 CHILDTABINFO[] =
60    {
61       { tabFILESETS,   IDS_TAB_FILESETS,   imageFILESET   },
62       { tabAGGREGATES, IDS_TAB_AGGREGATES, imageAGGREGATE },
63       { tabSERVICES,   IDS_TAB_SERVICES,   imageSERVICE   },
64    };
65
66 #define nCHILDTABS (sizeof(CHILDTABINFO)/sizeof(CHILDTABINFO[0]))
67
68
69
70 /*
71  * PROTOTYPES _________________________________________________________________
72  *
73  */
74
75 BOOL CALLBACK Server_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
76
77 void Server_SaveRect (HWND hDlg, BOOL fOpen);
78
79 BOOL Server_HandleDialogKeys (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
80
81
82 /*
83  * ROUTINES ___________________________________________________________________
84  *
85  */
86
87 void Server_Open (LPIDENT lpiServer, LPRECT prWindow)
88 {
89    HWND hServer;
90
91    if ((hServer = PropCache_Search (pcSERVER, lpiServer)) != NULL)
92       {
93       SetFocus (hServer);
94       }
95    else
96       {
97       // First off, if this server isn't being monitored, we have
98       // to start monitoring it or we can't open a window (nothing to
99       // show otherwise).
100       //
101       LPSERVER_PREF lpsp;
102       if ((lpsp = (LPSERVER_PREF)lpiServer->GetUserParam()) != NULL)
103          {
104          BOOL fCanShowWindow = (gr.fOpenMonitors || lpsp->fIsMonitored);
105
106          if (gr.fOpenMonitors && !lpsp->fIsMonitored)
107             {
108             StartTask (taskSVR_MONITOR_ONOFF, NULL, lpiServer);
109             }
110
111          if (fCanShowWindow)
112             {
113             hServer = ModelessDialogParam (IDD_SERVER, NULL, (DLGPROC)Server_DlgProc, (LPARAM)lpiServer);
114             Server_SelectServer (hServer, lpiServer);
115
116             if (prWindow->right != 0)
117                {
118                SetWindowPos (hServer, NULL, prWindow->left, prWindow->top,
119                              cxRECT(*prWindow), cyRECT(*prWindow),
120                              SWP_NOZORDER | SWP_NOACTIVATE);
121                }
122
123             ShowWindow (hServer, SW_NORMAL);
124             }
125          }
126       }
127 }
128
129
130 void Server_Close (LPIDENT lpiServer)
131 {
132    HWND hWnd;
133
134    if ((hWnd = PropCache_Search (pcSERVER, lpiServer)) != NULL)
135       {
136       Server_SaveRect (hWnd, FALSE);
137       DestroyWindow (hWnd);
138
139       // If there's a subset active, the user may want us to stop
140       // monitoring this server once its window is closed.
141       //
142       LPSERVER_PREF lpsp;
143       if ((lpsp = (LPSERVER_PREF)lpiServer->GetUserParam()) != NULL)
144          {
145          if (g.sub && gr.fCloseUnmonitors && lpsp->fIsMonitored && !gr.fPreview)
146             {
147             StartTask (taskSVR_MONITOR_ONOFF, NULL, lpiServer);
148             }
149          }
150       }
151 }
152
153
154 void Server_CloseAll (BOOL fUserRequested)
155 {
156    HWND hWnd;
157
158    while ((hWnd = PropCache_Search (pcSERVER, ANYVALUE)) != NULL)
159       {
160       LPIDENT lpiServer = Server_GetServer (hWnd);
161
162       Server_SaveRect (hWnd, !fUserRequested);
163       DestroyWindow (hWnd);
164
165       if (lpiServer && fUserRequested)
166          {
167          // If there's a subset active, the user may want us to stop
168          // monitoring this server once its window is closed.
169          //
170          LPSERVER_PREF lpsp;
171          if ((lpsp = (LPSERVER_PREF)lpiServer->GetUserParam()) != NULL)
172             {
173             if (g.sub && gr.fCloseUnmonitors && lpsp->fIsMonitored)
174                {
175                StartTask (taskSVR_MONITOR_ONOFF, NULL, lpiServer);
176                }
177             }
178          }
179       }
180 }
181
182
183 HWND Server_GetCurrentTab (HWND hWnd)
184 {
185    return GetTabChild (GetDlgItem (hWnd, IDC_TABS));
186 }
187
188 CHILDTAB Server_GetDisplayedTab (HWND hWnd)
189 {
190    HWND hTabs = GetDlgItem (hWnd, IDC_TABS);
191    return (hTabs) ? (CHILDTAB)TabCtrl_GetCurSel(hTabs) : tabINVALID;
192 }
193
194 HWND Server_GetWindowForChild (HWND hChild)
195 {
196    // hChild is the Filesets_DlgProc dialog (or whatever)
197    // Its parent is the tab control on the server window
198    // Its grandparent is the Popup HWND (may be g.hMain) that we want.
199    //
200    return GetParent (GetParent (hChild));
201 }
202
203 void Server_SelectServer (HWND hDlg, LPIDENT lpiNew, BOOL fForceRedraw)
204 {
205    LPIDENT lpiOld = Server_GetServer (hDlg);
206    if (lpiNew != lpiOld)
207       {
208       SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR)lpiNew);
209
210       if (hDlg != g.hMain)
211          {
212          if (lpiOld)
213             PropCache_Delete (pcSERVER, lpiOld);
214
215          if (lpiNew)
216             {
217             PropCache_Add (pcSERVER, lpiNew, hDlg);
218
219             TCHAR szName[ cchNAME ];
220             lpiNew->GetServerName (szName);
221             LPTSTR pszTitle = FormatString (IDS_SERVER_TITLE, TEXT("%s"), szName);
222             SetWindowText (hDlg, pszTitle);
223             FreeString (pszTitle);
224             }
225          }
226
227       fForceRedraw = TRUE;
228       }
229
230    if (fForceRedraw)
231       {
232       Server_ForceRedraw (hDlg);
233       }
234 }
235
236 LPIDENT Server_GetServer (HWND hDlg)
237 {
238    return (LPIDENT)GetWindowLongPtr (hDlg, DWLP_USER);
239 }
240
241 LPIDENT Server_GetServerForChild (HWND hChild)
242 {
243    if (GetParent(hChild) == NULL)
244       return Server_GetServer (hChild);
245    else
246       return Server_GetServer (GetParent(GetParent(hChild)));
247 }
248
249
250 void Server_ForceRedraw (HWND hDlg)
251 {
252    HWND hChild = Server_GetCurrentTab (hDlg);
253
254    if (hChild && IsWindow (hChild))
255       {
256       PostMessage (hChild, WM_SERVER_CHANGED, 0, 0);
257       }
258 }
259
260
261 /*
262  * SERVER DIALOG ______________________________________________________________
263  *
264  */
265
266 BOOL CALLBACK Server_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
267 {
268    LPIDENT lpiServer = Server_GetServer (hDlg);
269
270    if (Server_HandleDialogKeys (hDlg, msg, wp, lp))
271       return TRUE;
272
273    switch (msg)
274       {
275       case WM_INITDIALOG:
276          RECT rWindow;
277          Server_PrepareTabControl (GetDlgItem (hDlg, IDC_TABS));
278          GetWindowRect (hDlg, &rWindow);
279          ResizeWindow (hDlg, awdServer, rwaMoveToHere, &rWindow);
280          break;
281
282       case WM_HELP:
283          WinHelp (hDlg, cszHELPFILENAME, HELP_FINDER, 0);
284          break;
285
286       case WM_DESTROY:
287          GetWindowRect (hDlg, &gr.rServerLast);
288
289          if (lpiServer)
290             PropCache_Delete (pcSERVER, lpiServer);
291          break;
292
293       case WM_SIZE:
294          // if (lp==0), we're minimizing--don't call ResizeWindow().
295          //
296          if (lp != 0)
297             {
298             ResizeWindow (hDlg, awdServer, rwaFixupGuts);
299             Server_SaveRect (hDlg, TRUE);
300             }
301          break;
302
303       case WM_MOVE:
304          Server_SaveRect (hDlg, TRUE);
305          break;
306
307       case WM_SETFOCUS:
308          gr.tabLast = Server_GetDisplayedTab (hDlg);
309          break;
310
311       case WM_COMMAND:
312          switch (LOWORD(wp))
313             {
314             case IDCANCEL:
315                LPIDENT lpi;
316                if ((lpi = Server_GetServer (hDlg)) != NULL)
317                   Server_Close (lpi);
318                else
319                   DestroyWindow (hDlg);
320                break;
321             }
322          break;
323
324       case WM_NOTIFY:
325          switch (((LPNMHDR)lp)->code)
326             {
327             case TCN_SELCHANGE:
328                {
329                HWND hTab = GetDlgItem (hDlg, IDC_TABS);
330                int iPage = TabCtrl_GetCurSel (hTab);
331
332                Server_DisplayTab (hDlg, (CHILDTAB)iPage);
333                gr.tabLast = (CHILDTAB)iPage;
334                }
335                break;
336             }
337          break;
338       }
339
340    return FALSE;
341 }
342
343
344 static LONG_PTR procTabControl = 0;
345
346 LRESULT CALLBACK Server_SubclassTabControlProc (HWND hTab, UINT msg, WPARAM wp, LPARAM lp)
347 {
348    LRESULT rc;
349
350    if (procTabControl == 0)
351       rc = DefWindowProc (hTab, msg, wp, lp);
352    else
353       rc = (LRESULT) CallWindowProc ((WNDPROC)procTabControl, hTab, msg, wp, lp);
354
355    switch (msg)
356       {
357       // Since this is a subclass proc, it's not around when the window
358       // is created.  Any WM_CREATE processing we'd ordinarily do here
359       // must therefore be done at the point where the tab control is
360       // subclassed.
361       //
362       // case WM_CREATE:
363
364       case WM_SIZE:
365          if (lp != 0)
366             ResizeWindow (hTab, awdTabChild, rwaFixupGuts);
367          break;
368
369       case WM_DESTROY:
370          if (procTabControl != 0)
371             SetWindowLongPtr (hTab, GWLP_WNDPROC, procTabControl);
372          break;
373       }
374
375    return rc;
376 }
377
378
379 void Server_PrepareTabControl (HWND hTab)
380 {
381    TabCtrl_SetImageList (hTab, AfsAppLib_CreateImageList (FALSE));
382
383    TCHAR szText[ cchRESOURCE ];
384    TC_ITEM tci;
385    tci.mask = TCIF_TEXT | TCIF_PARAM | TCIF_IMAGE;
386    tci.pszText = szText;
387
388    for (int iTab = 0; iTab < nCHILDTABS; ++iTab)
389       {
390       tci.iImage = CHILDTABINFO[ iTab ].iImage;
391       tci.lParam = (LPARAM)CHILDTABINFO[ iTab ].tab;
392       GetString (tci.pszText, CHILDTABINFO[ iTab ].idsTabTitle);
393       TabCtrl_InsertItem (hTab, iTab, &tci);
394       }
395
396    // subclass the TCN_ window, so that it will start sending WM_SIZE
397    // messages to its child window.
398    //
399    procTabControl = GetWindowLongPtr (hTab, GWLP_WNDPROC);
400    SetWindowLongPtr (hTab, GWLP_WNDPROC, (LONG_PTR)Server_SubclassTabControlProc);
401
402    // Since we just subclassed this control, our new wndproc wasn't around
403    // when the window was created.  Any WM_CREATE processing we'd ordinarily
404    // in that wndproc must therefore be done here.
405
406    // WM_CREATE:
407    RECT rWindow;
408    GetRectInParent (hTab, &rWindow);
409    ResizeWindow (hTab, awdTabChild, rwaMoveToHere, &rWindow);
410
411    // Finally, select an appropriate tab and display it.
412    //
413    Server_DisplayTab (GetParent (hTab), gr.tabLast);
414 }
415
416
417 void Server_DisplayTab (HWND hDlg, CHILDTAB iTab)
418 {
419    HWND hTab = GetDlgItem (hDlg, IDC_TABS);
420    int idd = -1;
421    DLGPROC dlgproc = NULL;
422
423    switch (iTab)
424       {
425       case tabSERVICES:
426          idd = IDD_SERVICES;
427          dlgproc = (DLGPROC)Services_DlgProc;
428          break;
429       case tabAGGREGATES:
430          idd = IDD_AGGREGATES;
431          dlgproc = (DLGPROC)Aggregates_DlgProc;
432          break;
433       case tabFILESETS:
434          idd = IDD_FILESETS;
435          dlgproc = (DLGPROC)Filesets_DlgProc;
436          break;
437       }
438
439    if (idd != -1)
440       {
441       HWND hDialogOld = GetTabChild (hTab);
442       HWND hDialogNew = ModelessDialog (idd, hTab, dlgproc);
443
444       if (hDialogNew != NULL)
445          {
446          TabCtrl_SetCurSel (hTab, iTab);
447          ShowWindow (hDialogNew, SW_SHOW);
448
449          if (hDialogOld != NULL)
450             {
451             DestroyWindow (hDialogOld);
452             }
453
454          Server_ForceRedraw (hDlg);
455          }
456       }
457 }
458
459
460 void Server_Uncover (HWND hWnd)
461 {
462    if (hWnd == g.hMain) // uncover the preview pane?
463       {
464       AfsAppLib_Uncover (GetDlgItem (g.hMain, IDC_TABS));
465       }
466    else // uncover a standalone server window?
467       {
468       AfsAppLib_Uncover (hWnd);
469       }
470 }
471
472
473 void Server_SaveRect (HWND hDlg, BOOL fOpen)
474 {
475    LPSVR_SETWINDOWPOS_PARAMS lpp = New (SVR_SETWINDOWPOS_PARAMS);
476    GetWindowRect (hDlg, &lpp->rWindow);
477    lpp->lpi = Server_GetServer (hDlg);
478    lpp->fOpen = fOpen;
479
480    StartTask (taskSVR_SETWINDOWPOS, NULL, lpp);
481 }
482
483
484 BOOL Server_HandleDialogKeys (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
485 {
486    if (msg == WM_COMMAND)
487       {
488       switch (LOWORD(wp))
489          {
490          case M_KEY_RETURN:
491             Server_OnKey_Return();
492             return TRUE;
493
494          case M_KEY_CTRLTAB:
495             Server_OnKey_CtrlTab (hDlg, TRUE);
496             return TRUE;
497
498          case M_KEY_CTRLBACKTAB:
499             Server_OnKey_CtrlTab (hDlg, FALSE);
500             return TRUE;
501
502          case M_KEY_TAB:
503             Server_OnKey_Tab (hDlg, TRUE);
504             return TRUE;
505
506          case M_KEY_BACKTAB:
507             Server_OnKey_Tab (hDlg, FALSE);
508             return TRUE;
509
510          case M_KEY_MENU:
511             Server_OnKey_Menu();
512             return TRUE;
513
514          case M_KEY_ESC:
515             Server_OnKey_Esc();
516             return TRUE;
517
518          case M_KEY_PROPERTIES:
519             Server_OnKey_Properties();
520             return TRUE;
521          }
522       }
523
524    return FALSE;
525 }
526
527
528 void Server_OnKey_Return (void)
529 {
530    static NMHDR hdr;
531    hdr.hwndFrom = GetFocus();
532    hdr.idFrom = GetWindowLong (GetFocus(), GWL_ID);
533    hdr.code = FLN_LDBLCLICK;
534    PostMessage (GetParent (GetFocus()), WM_NOTIFY, 0, (LPARAM)&hdr);
535 }
536
537
538 void Server_OnKey_Menu (void)
539 {
540    HWND hFocus = GetFocus();
541    if (fIsFastList (hFocus))
542       {
543       POINT ptScreen = { 0, 0 };
544
545       HLISTITEM hItem;
546       if ((hItem = FastList_FindFirstSelected (hFocus)) != NULL)
547          {
548          FASTLISTITEMREGIONS reg;
549          FastList_GetItemRegions (hFocus, hItem, &reg);
550
551          ptScreen.x = reg.rItem.left + (reg.rItem.right -reg.rItem.left) /2;
552          ptScreen.y = reg.rItem.top + (reg.rItem.bottom -reg.rItem.top) /2;
553          ClientToScreen (GetFocus(), &ptScreen);
554          }
555
556       PostMessage (GetParent (GetFocus()), WM_CONTEXTMENU, (WPARAM)GetFocus(), MAKELONG(ptScreen.x,ptScreen.y));
557       }
558 }
559
560
561 void Server_OnKey_Esc (void)
562 {
563    HWND hFocus = GetFocus();
564    if (fIsFastList (hFocus))
565       {
566       FastList_SelectNone (hFocus);
567       }
568 }
569
570
571 void Server_OnKey_Properties (void)
572 {
573    HWND hFocus = GetFocus();
574    if (fIsFastList (hFocus))
575       {
576       LPIDENT lpi;
577       if ((lpi = (LPIDENT)FL_GetSelectedData (hFocus)) != NULL)
578          {
579          StartContextCommand (GetParent(hFocus), NULL, lpi, M_PROPERTIES);
580          }
581       }
582 }
583
584
585 void Server_OnKey_Tab (HWND hDlg, BOOL fForward)
586 {
587    // The tab-cycle should go:
588    //    TabControl <-> TabChildControls
589    //
590    HWND hFocus = GetFocus();
591    HWND hTabChild = GetTabChild (GetDlgItem (hDlg, IDC_TABS));
592
593    if (fForward)
594       {
595       if (hFocus == GetDlgItem (hDlg, IDC_TABS))
596          {
597          PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetNextDlgTabItem (hTabChild, NULL, FALSE), TRUE);
598          }
599       else
600          {
601          if (GetNextDlgTabItem (hTabChild, hFocus, FALSE) == GetNextDlgTabItem (hTabChild, NULL, FALSE))
602             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem (hDlg, IDC_TABS), TRUE);
603          else
604             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetNextDlgTabItem (hTabChild, hFocus, FALSE), TRUE);
605          }
606       }
607    else // (!fForward)
608       {
609       if (hFocus == GetDlgItem (hDlg, IDC_TABS))
610          {
611          PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetLastDlgTabItem (hTabChild), TRUE);
612          }
613       else
614          {
615          if (hFocus == GetNextDlgTabItem (hTabChild, NULL, FALSE))
616             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem (hDlg, IDC_TABS), TRUE);
617          else
618             PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetNextDlgTabItem (hTabChild, hFocus, TRUE), TRUE);
619          }
620       }
621 }
622
623
624 void Server_OnKey_CtrlTab (HWND hDlg, BOOL fForward)
625 {
626    HWND hTabs = GetDlgItem (hDlg, IDC_TABS);
627    int iTab = TabCtrl_GetCurSel(hTabs);
628
629    if (fForward)
630       iTab = (iTab == nCHILDTABS-1) ? (0) : (iTab+1);
631    else
632       iTab = (iTab == 0) ? (nCHILDTABS-1) : (iTab-1);
633
634    TabCtrl_SetCurSel (hTabs, iTab);
635    Server_DisplayTab (hDlg, (CHILDTAB)iTab);
636    gr.tabLast = (CHILDTAB)iTab;
637
638    PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)hTabs, TRUE);
639 }
640