ticket-2618-patches-20031207
[openafs.git] / src / WINNT / afssvrmgr / subset.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 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include "svrmgr.h"
16 #include "subset.h"
17 #include "propcache.h"
18
19
20 #define REGVAL_INCLUSIVE   TEXT("Inclusive List")
21
22 /*
23  * PROTOTYPES _________________________________________________________________
24  *
25  */
26
27 BOOL CALLBACK Subsets_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
28 void Subsets_OnInitDialog (HWND hDlg, LPSUBSET sub);
29 void Subsets_OnApply (HWND hDlg, LPSUBSET sub);
30 LPSUBSET Subsets_OnLoad (HWND hDlg, LPSUBSET sub);
31 void Subsets_OnSave (HWND hDlg, LPSUBSET sub);
32 void Subsets_SetName (HWND hDlg, LPSUBSET sub);
33 void Subsets_PutSubsetOnDialog (HWND hDlg, LPSUBSET sub);
34 void Subsets_GetSubsetFromDialog (HWND hDlg, LPSUBSET sub);
35 LPSUBSET Subsets_OnCheck (HWND hDlg, int iSel, LPSUBSET subOld);
36 LPSUBSET Subsets_OnCheckAll (HWND hDlg, LPSUBSET subOld, BOOL fCheck);
37
38 BOOL Subsets_GetLoadName (HWND hParent, LPTSTR pszSubset);
39 BOOL Subsets_GetSaveName (HWND hParent, LPTSTR pszSubset);
40
41
42 /*
43  * ROUTINES ___________________________________________________________________
44  *
45  */
46
47 BOOL Subsets_fMonitorServer (LPSUBSET sub, LPIDENT lpiServer)
48 {
49    BOOL fMonitor = TRUE;
50
51    TCHAR szLong[ cchNAME ];
52    TCHAR szShort[ cchNAME ];
53    lpiServer->GetLongServerName (szLong);
54    lpiServer->GetShortServerName (szShort);
55
56    if (sub)
57       {
58       if (sub->pszMonitored)
59          {
60          fMonitor = FALSE;  // unless it shows up here.
61
62          for (LPTSTR psz = sub->pszMonitored; !fMonitor && *psz; psz += 1+lstrlen(psz))
63             {
64             if (!lstrcmpi (psz, szLong))
65                fMonitor = TRUE;
66             else if (!lstrcmpi (psz, szShort))
67                fMonitor = TRUE;
68             }
69          }
70       else if (sub->pszUnmonitored)
71          {
72          for (LPTSTR psz = sub->pszUnmonitored; fMonitor && *psz; psz += 1+lstrlen(psz))
73             {
74             if (!lstrcmpi (psz, szLong))
75                fMonitor = FALSE;
76             else if (!lstrcmpi (psz, szShort))
77                fMonitor = FALSE;
78             }
79          }
80       }
81
82    return fMonitor;
83 }
84
85
86 LPSUBSET Subsets_SetMonitor (LPSUBSET sub, LPIDENT lpiServer, BOOL fMonitor)
87 {
88    if (sub == NULL)
89       {
90       sub = New (SUBSET);
91       memset (sub, 0x00, sizeof(SUBSET));
92       }
93
94    if (fMonitor != Subsets_fMonitorServer (sub, lpiServer))
95       {
96       sub->fModified = TRUE;
97
98       TCHAR szLong[ cchNAME ];
99       TCHAR szShort[ cchNAME ];
100       lpiServer->GetShortServerName (szShort);
101       lpiServer->GetLongServerName (szLong);
102
103       // First ensure that the server name doesn't appear anywhere
104       // in the subset.
105       //
106       LPTSTR pszMonitoredNew = NULL;
107       LPTSTR pszUnmonitoredNew = NULL;
108
109       if (sub->pszMonitored)
110          {
111          for (LPTSTR psz = sub->pszMonitored; *psz; psz += 1+lstrlen(psz))
112             {
113             if (lstrcmpi (psz, szLong) && lstrcmpi (psz, szShort))
114                {
115                FormatMultiString (&pszMonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), psz);
116                }
117             }
118          }
119       else if (sub->pszUnmonitored)
120          {
121          for (LPTSTR psz = sub->pszUnmonitored; *psz; psz += 1+lstrlen(psz))
122             {
123             if (lstrcmpi (psz, szLong) && lstrcmpi (psz, szShort))
124                {
125                FormatMultiString (&pszUnmonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), psz);
126                }
127             }
128          }
129
130       // Then ensure it shows up only where necessary.
131       //
132       if (sub->pszMonitored && fMonitor)
133          {
134          FormatMultiString (&pszMonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), szLong);
135          }
136       else if (!sub->pszMonitored && !fMonitor)
137          {
138          FormatMultiString (&pszUnmonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), szLong);
139          }
140
141       if (sub->pszMonitored && !pszMonitoredNew)
142          {
143          pszMonitoredNew = AllocateString (2);
144          pszMonitoredNew[0] = TEXT('\0');
145          pszMonitoredNew[1] = TEXT('\0');
146          }
147       if (sub->pszUnmonitored && !pszUnmonitoredNew)
148          {
149          pszUnmonitoredNew = AllocateString (2);
150          pszUnmonitoredNew[0] = TEXT('\0');
151          pszUnmonitoredNew[1] = TEXT('\0');
152          }
153
154       // Finally, update the subset's members.
155       //
156       if (sub->pszMonitored)
157          FreeString (sub->pszMonitored);
158       if (sub->pszUnmonitored)
159          FreeString (sub->pszUnmonitored);
160
161       sub->pszMonitored = pszMonitoredNew;
162       sub->pszUnmonitored = pszUnmonitoredNew;
163       }
164
165    return sub;
166 }
167
168
169 void ShowSubsetsDialog (void)
170 {
171    LPPROPSHEET psh = PropSheet_Create (IDS_SUBSET_TAB, FALSE);
172    psh->sh.hwndParent = g.hMain;
173
174    LPSUBSET sub = Subsets_CopySubset (g.sub);
175    PropSheet_AddTab (psh, 0, IDD_SUBSETS, (DLGPROC)Subsets_DlgProc, (LPARAM)sub, TRUE);
176    PropSheet_ShowModal (psh, PumpMessage);
177 }
178
179
180 BOOL CALLBACK Subsets_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
181 {
182    if (AfsAppLib_HandleHelp (IDD_SUBSETS, hDlg, msg, wp, lp))
183       return TRUE;
184
185    if (msg == WM_INITDIALOG)
186       SetWindowLong (hDlg, DWL_USER, ((LPPROPSHEETPAGE)lp)->lParam);
187
188    LPSUBSET sub = (LPSUBSET)GetWindowLong (hDlg, DWL_USER);
189
190    switch (msg)
191       {
192       case WM_INITDIALOG_SHEET:
193          PropCache_Add (pcGENERAL, NULL, hDlg);
194          break;
195
196       case WM_DESTROY_SHEET:
197          PropCache_Delete (hDlg);
198          break;
199
200       case WM_INITDIALOG:
201          Subsets_OnInitDialog (hDlg, sub);
202          break;
203
204       case WM_COMMAND:
205          switch (LOWORD(wp))
206             {
207             case IDAPPLY:
208                Subsets_OnApply (hDlg, sub);
209                break;
210
211             case IDOK:
212             case IDCANCEL:
213                EndDialog (hDlg, LOWORD(wp));
214                break;
215
216             case IDC_SUBSET_LOAD:
217                LPSUBSET subNew;
218                subNew = Subsets_OnLoad (hDlg, sub);
219                if (subNew != NULL)
220                   {
221                   if (sub)
222                      Subsets_FreeSubset (sub);
223                   SetWindowLong (hDlg, DWL_USER, (LONG)subNew);
224                   }
225                break;
226
227             case IDC_SUBSET_LIST:
228                if (HIWORD(wp) == LBN_CLICKED)  // checked or unchecked?
229                   {
230                   int iSel = LB_GetSelected (GetDlgItem (hDlg, IDC_SUBSET_LIST));
231                   subNew = Subsets_OnCheck (hDlg, iSel, sub);
232                   if (subNew && (subNew != sub))
233                      {
234                      if (sub)
235                         Subsets_FreeSubset (sub);
236                      SetWindowLong (hDlg, DWL_USER, (LONG)subNew);
237                      }
238                   }
239                break;
240
241             case IDC_SUBSET_SAVE:
242                Subsets_OnSave (hDlg, sub);
243                break;
244
245             case IDC_SUBSET_ALL:
246             case IDC_SUBSET_NONE:
247                subNew = Subsets_OnCheckAll (hDlg, sub, (LOWORD(wp) == IDC_SUBSET_ALL) ? TRUE : FALSE);
248                if (subNew && (subNew != sub))
249                   {
250                   if (sub)
251                      Subsets_FreeSubset (sub);
252                   SetWindowLong (hDlg, DWL_USER, (LONG)subNew);
253                   }
254                break;
255             }
256          break;
257       }
258
259    return FALSE;
260 }
261
262
263 void Subsets_OnInitDialog (HWND hDlg, LPSUBSET sub)
264 {
265    Subsets_SetName (hDlg, sub);
266    Subsets_PutSubsetOnDialog (hDlg, sub);
267 }
268
269
270 void Subsets_SetName (HWND hDlg, LPSUBSET sub)
271 {
272    LPTSTR pszText;
273
274    BOOL fIsOneServer = FALSE;
275    if (sub && sub->pszMonitored && *(sub->pszMonitored))
276       {
277       LPTSTR pszNext = &sub->pszMonitored[ 1+lstrlen(sub->pszMonitored) ];
278       if (!*pszNext)
279          fIsOneServer = TRUE;
280       }
281
282    if (sub && sub->szSubset[0])
283       {
284       if (sub->fModified)
285          pszText = FormatString (IDS_SUBSET_CHANGED, TEXT("%s"), sub->szSubset);
286       else
287          pszText = FormatString (TEXT("%1"), TEXT("%s"), sub->szSubset);
288       }
289    else if (fIsOneServer)
290       {
291       pszText = FormatString (IDS_SUBSET_SERVERSUBSET, TEXT("%s"), sub->pszMonitored);
292       }
293    else if (sub) // && !sub->szSubset[0]
294       {
295       if (sub->fModified)
296          pszText = FormatString (IDS_SUBSET_CHANGED, TEXT("%m"), IDS_SUBSET_NONAME);
297       else
298          pszText = FormatString (TEXT("%1"), TEXT("%m"), IDS_SUBSET_NONAME);
299       }
300    else // no current subset specified
301       {
302       pszText = FormatString (TEXT("%1"), TEXT("%m"), IDS_SUBSET_NOSUBSET);
303       }
304
305    SetDlgItemText (hDlg, IDC_SUBSET_NAME, pszText);
306    FreeString (pszText);
307 }
308
309
310 void Subsets_PutSubsetOnDialog (HWND hDlg, LPSUBSET sub)
311 {
312    LPSUBSET_TO_LIST_PACKET lpp = New (SUBSET_TO_LIST_PACKET);
313    memset (lpp, 0x00, sizeof(SUBSET_TO_LIST_PACKET));
314
315    lpp->hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
316    lpp->sub = Subsets_CopySubset (sub);
317
318    StartTask (taskSUBSET_TO_LIST, NULL, lpp);
319 }
320
321
322 void Subsets_GetSubsetFromDialog (HWND hDlg, LPSUBSET sub)
323 {
324    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
325
326    if (sub->pszMonitored)
327       {
328       FreeString (sub->pszMonitored);
329       sub->pszMonitored = NULL;
330       }
331    if (sub->pszUnmonitored)
332       {
333       FreeString (sub->pszUnmonitored);
334       sub->pszUnmonitored = NULL;
335       }
336
337    // Is there only one server box checked?
338    //
339    int iiMax = SendMessage (hList, LB_GETCOUNT, 0, 0);
340
341    size_t cChecked = 0;
342    int iiChecked;
343    for (int ii = 0; ii < iiMax; ++ii)
344       {
345       if (LB_GetCheck (hList, ii))
346          {
347          iiChecked = ii;
348          if ((++cChecked) > 1)
349             break;
350          }
351       }
352    if (cChecked == 1)  // Only one is checked--use pszMonitored.
353       {
354       TCHAR szServer[ cchNAME ];
355       SendMessage (hList, LB_GETTEXT, iiChecked, (LPARAM)szServer); 
356       FormatMultiString (&sub->pszMonitored, TRUE, TEXT("%1"), TEXT("%s"), szServer);
357       }
358    else // Use pszUnmonitored.
359       {
360       for (int ii = 0; ii < iiMax; ++ii)
361          {
362          if (!LB_GetCheck (hList, ii))
363             {
364             TCHAR szServer[ cchNAME ];
365             SendMessage (hList, LB_GETTEXT, ii, (LPARAM)szServer); 
366             FormatMultiString (&sub->pszUnmonitored, TRUE, TEXT("%1"), TEXT("%s"), szServer);
367             }
368          }
369       }
370 }
371
372
373 LPSUBSET Subsets_OnCheck (HWND hDlg, int iSel, LPSUBSET subOld)
374 {
375    LPSUBSET sub = subOld;
376    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
377
378    if (!LB_GetCheck (hList, iSel))  // unchecked?
379       {
380       if (!sub)
381          {
382          sub = New (SUBSET);
383          memset (sub, 0x00, sizeof(SUBSET));
384          }
385       }
386
387    if (sub)
388       {
389       sub->fModified = TRUE;
390       Subsets_GetSubsetFromDialog (hDlg, sub);
391       Subsets_SetName (hDlg, sub);
392       PropSheetChanged (hDlg);
393       }
394
395    return sub;
396 }
397
398
399 LPSUBSET Subsets_OnCheckAll (HWND hDlg, LPSUBSET subOld, BOOL fCheck)
400 {
401    LPSUBSET sub = subOld;
402    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
403
404    if (!fCheck)  // unchecking things?
405       {
406       if (!sub)
407          {
408          sub = New (SUBSET);
409          memset (sub, 0x00, sizeof(SUBSET));
410          }
411       }
412
413    int iiMax = SendMessage (hList, LB_GETCOUNT, 0, 0);
414
415    for (int ii = 0; ii < iiMax; ++ii)
416       {
417       if (LB_GetCheck (hList, ii) != fCheck)
418          {
419          LB_SetCheck (hList, ii, fCheck);
420          }
421       }
422
423    if (sub)
424       {
425       sub->fModified = TRUE;
426       Subsets_GetSubsetFromDialog (hDlg, sub);
427       Subsets_SetName (hDlg, sub);
428       PropSheetChanged (hDlg);
429       }
430
431    return sub;
432 }
433
434
435 LPSUBSET Subsets_OnLoad (HWND hDlg, LPSUBSET subOld)
436 {
437    LPSUBSET subNew = NULL;
438
439    TCHAR szSubset[ cchNAME ] = TEXT("");
440    if (subOld)
441       lstrcpy (szSubset, subOld->szSubset);
442
443    if (Subsets_GetLoadName (hDlg, szSubset))
444       {
445       if ((subNew = Subsets_LoadSubset (NULL, szSubset)) != NULL)
446          {
447          Subsets_SetName (hDlg, subNew);
448          Subsets_PutSubsetOnDialog (hDlg, subNew);
449          PropSheetChanged (hDlg);
450          }
451       }
452
453    return subNew;
454 }
455
456
457 void Subsets_OnSave (HWND hDlg, LPSUBSET sub)
458 {
459    if (sub)
460       {
461       TCHAR szSubset[ cchNAME ];
462       lstrcpy (szSubset, sub->szSubset);
463
464       if (Subsets_GetSaveName (hDlg, szSubset))
465          {
466          Subsets_GetSubsetFromDialog (hDlg, sub);
467
468          if (Subsets_SaveSubset (NULL, szSubset, sub))
469             {
470             lstrcpy (sub->szSubset, szSubset);
471             sub->fModified = FALSE;
472
473             Subsets_SetName (hDlg, sub);
474             }
475          }
476       }
477 }
478
479
480 void Subsets_OnApply (HWND hDlg, LPSUBSET sub)
481 {
482    LPSUBSET subCopy;
483    if ((subCopy = Subsets_CopySubset (sub, TRUE)) != NULL)
484       {
485       Subsets_GetSubsetFromDialog (hDlg, subCopy);
486       }
487
488    LPSUBSET subOld = g.sub;
489    g.sub = subCopy;
490    if (subOld)
491       Subsets_FreeSubset (subOld);
492
493    StartTask (taskAPPLY_SUBSET, NULL, sub);
494 }
495
496
497 BOOL Subsets_SaveIfDirty (LPSUBSET sub)
498 {
499    if (!sub || !sub->fModified)
500       return TRUE;
501
502    int rc;
503    rc = Message (MB_YESNOCANCEL | MB_ICONQUESTION, IDS_SUBSET_DISCARD_TITLE, IDS_SUBSET_DISCARD_DESC);
504
505    if (rc == IDNO)
506       {
507       sub->fModified = FALSE;
508       sub->szSubset[0] = TEXT('\0');
509       }
510    else if (rc == IDYES)
511       {
512       TCHAR szSubset[ cchNAME ];
513       lstrcpy (szSubset, sub->szSubset);
514
515       if (!Subsets_GetSaveName (g.hMain, szSubset))
516          return FALSE;
517
518       if (!Subsets_SaveSubset (NULL, szSubset, sub))
519          return FALSE;
520
521       sub->fModified = FALSE;
522       lstrcpy (sub->szSubset, szSubset);
523       }
524    else // (rc == IDCANCEL)
525       {
526       return FALSE;
527       }
528
529    return TRUE;
530 }
531
532
533 BOOL Subsets_EnumSubsets (LPTSTR pszCell, size_t iIndex, LPTSTR pszSubset)
534 {
535    BOOL rc = FALSE;
536
537    HKEY hk;
538    if ((hk = OpenSubsetsKey (pszCell, FALSE)) != NULL)
539       {
540       if (RegEnumKey (hk, iIndex, pszSubset, cchNAME) == 0)
541          rc = TRUE;
542
543       RegCloseKey (hk);
544       }
545
546    return rc;
547 }
548
549
550 BOOL Subsets_SaveSubset (LPTSTR pszCell, LPTSTR pszSubset, LPSUBSET sub)
551 {
552    BOOL rc = FALSE;
553
554    if (sub && pszSubset && *pszSubset)
555       {
556       HKEY hk;
557       if ((hk = OpenSubsetsSubKey (pszCell, pszSubset, TRUE)) != NULL)
558          {
559          DWORD dwMonitored = (sub->pszMonitored) ? 1 : 0;
560          RegSetValueEx (hk, REGVAL_INCLUSIVE, 0, REG_DWORD, (LPBYTE)&dwMonitored, sizeof(DWORD));
561
562          for (LPTSTR psz = (sub->pszMonitored) ? sub->pszMonitored : sub->pszUnmonitored;
563               psz && *psz;
564               psz += 1+lstrlen(psz))
565             {
566             RegSetValueEx (hk, psz, 0, REG_SZ, (PBYTE)TEXT("X"), sizeof(TCHAR)*2);
567             }
568
569          rc = TRUE;
570
571          RegCloseKey (hk);
572          }
573       }
574
575    return rc;
576 }
577
578
579 LPSUBSET Subsets_LoadSubset (LPTSTR pszCell, LPTSTR pszSubset)
580 {
581    LPSUBSET sub = NULL;
582
583    HKEY hk;
584    if ((hk = OpenSubsetsSubKey (pszCell, pszSubset, FALSE)) != NULL)
585       {
586       DWORD dwMonitored;
587       DWORD dwSize;
588       DWORD dwType;
589       dwSize = sizeof(dwMonitored);
590       if (RegQueryValueEx (hk, REGVAL_INCLUSIVE, 0, &dwType, (LPBYTE)&dwMonitored, &dwSize) == 0)
591          {
592          sub = New (SUBSET);
593          memset (sub, 0x00, sizeof(SUBSET));
594          lstrcpy (sub->szSubset, pszSubset);
595          sub->fModified = FALSE;
596
597          LPTSTR *ppsz;
598          ppsz = (dwMonitored) ? &sub->pszMonitored : &sub->pszUnmonitored;
599
600          for (size_t iIndex = 0; ; ++iIndex)
601             {
602             TCHAR szServer[ cchNAME ];
603             dwSize = sizeof(szServer);
604
605             if (RegEnumValue (hk, iIndex, szServer, &dwSize, 0, NULL, NULL, NULL) != 0)
606                break;
607
608             if (szServer[0] && lstrcmpi (szServer, REGVAL_INCLUSIVE))
609                FormatMultiString (ppsz, FALSE, TEXT("%1"), TEXT("%s"), szServer);
610             }
611
612          if (dwMonitored && !sub->pszMonitored)
613             {
614             sub->pszMonitored = AllocateString(2);
615             sub->pszMonitored[0] = TEXT('\0');
616             sub->pszMonitored[1] = TEXT('\0');
617             }
618          }
619
620       RegCloseKey (hk);
621       }
622
623    return sub;
624 }
625
626
627 LPSUBSET Subsets_CopySubset (LPSUBSET sub, BOOL fCreateIfNULL)
628 {
629    LPSUBSET subCopy = NULL;
630
631    if (sub != NULL)
632       {
633       subCopy = New (SUBSET);
634       memset (subCopy, 0x00, sizeof(SUBSET));
635       lstrcpy (subCopy->szSubset, sub->szSubset);
636       subCopy->fModified = sub->fModified;
637
638       size_t cch;
639       if (sub->pszMonitored)
640          {
641          cch = 1;
642          for (LPTSTR psz = sub->pszMonitored; *psz; psz += 1+lstrlen(psz))
643             cch += 1+lstrlen(psz);
644          subCopy->pszMonitored = AllocateString (cch);
645          memcpy (subCopy->pszMonitored, sub->pszMonitored, sizeof(TCHAR)*cch);
646          }
647
648       if (sub->pszUnmonitored)
649          {
650          cch = 1;
651          for (LPTSTR psz = sub->pszUnmonitored; *psz; psz += 1+lstrlen(psz))
652             cch += 1+lstrlen(psz);
653          subCopy->pszUnmonitored = AllocateString (cch);
654          memcpy (subCopy->pszUnmonitored, sub->pszUnmonitored, sizeof(TCHAR)*cch);
655          }
656       }
657    else if (fCreateIfNULL)
658       {
659       subCopy = New (SUBSET);
660       memset (subCopy, 0x00, sizeof(SUBSET));
661       }
662
663    return subCopy;
664 }
665
666
667 void Subsets_FreeSubset (LPSUBSET sub)
668 {
669    if (sub != NULL)
670       {
671       if (sub->pszMonitored)
672          FreeString (sub->pszMonitored);
673       if (sub->pszUnmonitored)
674          FreeString (sub->pszUnmonitored);
675
676       Delete (sub);
677       }
678 }
679
680
681 /*
682  * SUBSET OPEN/SAVE DIALOG ____________________________________________________
683  *
684  */
685
686 typedef struct
687    {
688    BOOL fOpen;
689    TCHAR szCell[ cchNAME ];
690    TCHAR szSubset[ cchNAME ];
691    } SUBSET_OPENSAVE_PARAMS, *LPSUBSET_OPENSAVE_PARAMS;
692
693 BOOL CALLBACK Subsets_OpenSave_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
694 void Subsets_OpenSave_OnInitDialog (HWND hDlg, LPSUBSET_OPENSAVE_PARAMS lpp);
695 void Subsets_OpenSave_OnSelect (HWND hDlg);
696 void Subsets_OpenSave_Populate (HWND hDlg);
697 void Subsets_OpenSave_OnDelete (HWND hDlg);
698 void Subsets_OpenSave_OnRename (HWND hDlg);
699
700
701 BOOL Subsets_GetLoadName (HWND hParent, LPTSTR pszSubset)
702 {
703    SUBSET_OPENSAVE_PARAMS lpp;
704    lpp.fOpen = TRUE;
705    lpp.szCell[0] = TEXT('\0');
706    lstrcpy (lpp.szSubset, pszSubset);
707
708    if (g.lpiCell)
709       g.lpiCell->GetCellName (lpp.szCell);
710
711    int rc;
712    rc = ModalDialogParam (IDD_SUBSET_LOADSAVE,
713                           hParent, (DLGPROC)Subsets_OpenSave_DlgProc,
714                           (LPARAM)&lpp);
715
716    if (rc == IDOK)
717       {
718       lstrcpy (pszSubset, lpp.szSubset);
719       }
720
721    return (rc == IDOK) ? TRUE : FALSE;
722 }
723
724
725 BOOL Subsets_GetSaveName (HWND hParent, LPTSTR pszSubset)
726 {
727    SUBSET_OPENSAVE_PARAMS lpp;
728    lpp.fOpen = FALSE;
729    lpp.szCell[0] = TEXT('\0');
730    lstrcpy (lpp.szSubset, pszSubset);
731
732    if (g.lpiCell)
733       g.lpiCell->GetCellName (lpp.szCell);
734
735    int rc;
736    rc = ModalDialogParam (IDD_SUBSET_LOADSAVE,
737                           hParent, (DLGPROC)Subsets_OpenSave_DlgProc,
738                           (LPARAM)&lpp);
739
740    if (rc == IDOK)
741       {
742       lstrcpy (pszSubset, lpp.szSubset);
743       }
744
745    return (rc == IDOK) ? TRUE : FALSE;
746 }
747
748
749 BOOL CALLBACK Subsets_OpenSave_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
750 {
751    static BOOL fEditing = FALSE;
752
753    if (msg == WM_INITDIALOG)
754       SetWindowLong (hDlg, DWL_USER, lp);
755
756    LPSUBSET_OPENSAVE_PARAMS lpp;
757    if ((lpp = (LPSUBSET_OPENSAVE_PARAMS)GetWindowLong (hDlg, DWL_USER)) != NULL)
758       {
759       switch (msg)
760          {
761          case WM_INITDIALOG:
762             fEditing = FALSE;
763             Subsets_OpenSave_OnInitDialog (hDlg, lpp);
764             break;
765
766          case WM_COMMAND:
767             if (!fEditing)
768                {
769                switch (LOWORD(wp))
770                   {
771                   case IDCANCEL:
772                      EndDialog (hDlg, IDCANCEL);
773                      break;
774
775                   case IDOK:
776                      GetDlgItemText (hDlg, IDC_SUBSET_NAME, lpp->szSubset, cchNAME);
777                      if (lpp->szSubset[0] != TEXT('\0'))
778                         {
779                         BOOL fClose = TRUE;
780
781                         if (!lpp->fOpen)
782                            {
783                            HKEY hk;
784                            if ((hk = OpenSubsetsSubKey (NULL, lpp->szSubset, FALSE)) != NULL)
785                               {
786                               RegCloseKey (hk);
787
788                               int rc = Message (MB_YESNO | MB_ICONASTERISK, IDS_SUBSET_SAVE_TITLE, IDS_SUBSET_SAVE_DESC, TEXT("%s"), lpp->szSubset);
789                               if (rc != IDYES)
790                                  fClose = FALSE;
791                               }
792                            }
793
794                         if (fClose)
795                            EndDialog (hDlg, IDOK);
796                         }
797                      break;
798
799                   case IDC_SUBSET_DELETE:
800                      Subsets_OpenSave_OnDelete (hDlg);
801                      break;
802
803                   case IDC_SUBSET_RENAME:
804                      Subsets_OpenSave_OnRename (hDlg);
805                      break;
806                   }
807                }
808             break;
809
810          case WM_NOTIFY:
811             switch (((LPNMHDR)lp)->code)
812                {
813                case LVN_ITEMCHANGED:
814                   if (!fEditing)
815                      {
816                      if ( ((LPNM_LISTVIEW)lp)->uNewState & LVIS_SELECTED )
817                         Subsets_OpenSave_OnSelect (hDlg);
818                      }
819                   break;
820
821                case NM_DBLCLK:
822                   if (!fEditing)
823                      {
824                      if (((LPNMHDR)lp)->hwndFrom == GetDlgItem (hDlg, IDC_SUBSET_LIST))
825                         {
826                         Subsets_OpenSave_OnSelect (hDlg);
827                         PostMessage (hDlg, WM_COMMAND, IDOK, 0);
828                         }
829                      }
830                   break;
831
832                case LVN_BEGINLABELEDIT:
833                   fEditing = TRUE;
834                   return FALSE;  // okay to edit label
835
836                case LVN_ENDLABELEDIT:
837                   LV_DISPINFO *plvdi;
838                   if ((plvdi = (LV_DISPINFO*)lp) != NULL)
839                      {
840                      if ((plvdi->item.iItem != -1) &&
841                          (plvdi->item.pszText != NULL))
842                         {
843                         HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
844                         TCHAR szOldName[ cchNAME ];
845                         LV_GetItemText (hList, plvdi->item.iItem, 0, szOldName);
846
847                         if (lstrcmpi (szOldName, plvdi->item.pszText))
848                            {
849                            BOOL fRename = TRUE;
850                            BOOL fRepopulate = FALSE;
851
852                            HKEY hk;
853                            if ((hk = OpenSubsetsSubKey (NULL, plvdi->item.pszText, FALSE)) != NULL)
854                               {
855                               RegCloseKey (hk);
856
857                               int rc = Message (MB_YESNO | MB_ICONASTERISK, IDS_SUBSET_SAVE_TITLE, IDS_SUBSET_SAVE_DESC, TEXT("%s"), lpp->szSubset);
858                               if (rc != IDYES)
859                                  fRename = FALSE;
860                               else
861                                  fRepopulate = TRUE;
862                               }
863
864                            if (fRename)
865                               {
866                               LPSUBSET subRename;
867                               if ((subRename = Subsets_LoadSubset (NULL, szOldName)) != NULL)
868                                  {
869                                  if (Subsets_SaveSubset (NULL, plvdi->item.pszText, subRename))
870                                     {
871                                     (void)OpenSubsetsSubKey (NULL, szOldName, 2); // 0=open,1=create,2=delete
872
873                                     if (fRepopulate)
874                                        Subsets_OpenSave_Populate (hDlg);
875                                     else
876                                        {
877                                        LV_SetItemText (hList, plvdi->item.iItem, 0, plvdi->item.pszText);
878                                        Subsets_OpenSave_OnSelect (hDlg);
879                                        }
880
881                                     Subsets_FreeSubset (subRename);
882                                     }
883                                  }
884                               }
885                            }
886                         }
887                      }
888
889                   fEditing = FALSE;
890                   break;
891                }
892             break;
893          }
894       }
895
896    return FALSE;
897 }
898
899
900 void Subsets_OpenSave_OnInitDialog (HWND hDlg, LPSUBSET_OPENSAVE_PARAMS lpp)
901 {
902    // Fix the buttons in the toolbar, so that they looks pretty
903    //
904    HWND hButton = GetDlgItem (hDlg, IDC_SUBSET_DELETE);
905    HICON hi = TaLocale_LoadIcon (IDI_BTN_DELETE);
906    SendMessage (hButton, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hi);
907
908    hButton = GetDlgItem (hDlg, IDC_SUBSET_RENAME);
909    hi = TaLocale_LoadIcon (IDI_BTN_RENAME);
910    SendMessage (hButton, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hi);
911
912    // Set up an ImageList so we'll have icons in the ListView
913    //
914    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
915    HIMAGELIST hil = ImageList_Create (16, 16, ILC_COLOR4 | ILC_MASK, 1, 1);
916
917    hi = TaLocale_LoadIcon (IDI_SUBSET);
918    ImageList_AddIcon (hil, hi);
919
920    ListView_SetImageList (hList, hil, LVSIL_SMALL);
921
922    // Then populate the ListView with the names of the subsets
923    // defined for this cell
924    //
925    Subsets_OpenSave_Populate (hDlg);
926    // Finally, fill in the rest of the dialog.
927    //
928    SetDlgItemText (hDlg, IDC_SUBSET_NAME, lpp->szSubset);
929
930    TCHAR szText[ cchRESOURCE ];
931    GetString (szText, (lpp->fOpen) ? IDS_SUBSET_TITLE_LOAD : IDS_SUBSET_TITLE_SAVE);
932    SetWindowText (hDlg, szText);
933
934    GetString (szText, (lpp->fOpen) ? IDS_BUTTON_OPEN : IDS_BUTTON_SAVE);
935    SetDlgItemText (hDlg, IDOK, szText);
936 }
937
938
939 void Subsets_OpenSave_Populate (HWND hDlg)
940 {
941    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
942    LV_StartChange (hList, TRUE);
943
944    TCHAR szSubset[ cchNAME ];
945    for (size_t iIndex = 0; Subsets_EnumSubsets (NULL, iIndex, szSubset); ++iIndex)
946       {
947       LV_AddItem (hList, 1, 0, 0, 0, szSubset);
948       }
949
950    LV_EndChange (hList);
951 }
952
953
954 void Subsets_OpenSave_OnSelect (HWND hDlg)
955 {
956    TCHAR szSubset[ cchNAME ];
957
958    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
959    short idxSelected = LV_GetSelected (hList);
960
961    if (idxSelected == -1)
962       szSubset[0] = TEXT('\0');
963    else
964       LV_GetItemText (hList, idxSelected, 0, szSubset);
965
966    SetDlgItemText (hDlg, IDC_SUBSET_NAME, szSubset);
967 }
968
969
970 void Subsets_OpenSave_OnDelete (HWND hDlg)
971 {
972    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
973    short idxSelected = LV_GetSelected (hList);
974
975    if (idxSelected != -1)
976       {
977       TCHAR szSubset[ cchNAME ];
978       LV_GetItemText (hList, idxSelected, 0, szSubset);
979
980       if (Message (MB_ICONASTERISK | MB_YESNO, IDS_SUBSET_DELETE_TITLE, IDS_SUBSET_DELETE_DESC, TEXT("%s"), szSubset) == IDYES)
981          {
982          (void)OpenSubsetsSubKey (NULL, szSubset, 2); // 0=open,1=create,2=delete
983          Subsets_OpenSave_Populate (hDlg);
984          }
985       }
986 }
987
988
989 void Subsets_OpenSave_OnRename (HWND hDlg)
990 {
991    HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST);
992    short idxSelected = LV_GetSelected (hList);
993
994    if (idxSelected != -1)
995       {
996       SetFocus (hList);
997       ListView_EditLabel (hList, idxSelected);
998       }
999 }
1000