- Added Find functions
[wine] / programs / regedit / framewnd.c
1 /*
2  * Regedit frame window
3  *
4  * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define WIN32_LEAN_AND_MEAN     /* Exclude rarely-used stuff from Windows headers */
22
23 #include <windows.h>
24 #include <tchar.h>
25 #include <commctrl.h>
26 #include <commdlg.h>
27 #include <cderr.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <shellapi.h>
31
32 #include "main.h"
33 #include "regproc.h"
34
35 /********************************************************************************
36  * Global and Local Variables:
37  */
38
39 static TCHAR favoritesKey[] =  _T("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\RegEdit\\Favorites");
40 static BOOL bInMenuLoop = FALSE;        /* Tells us if we are in the menu loop */
41 static TCHAR favoriteName[128];
42 static TCHAR searchString[128];
43 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
44
45 /*******************************************************************************
46  * Local module support methods
47  */
48
49 static void resize_frame_rect(HWND hWnd, PRECT prect)
50 {
51     RECT rt;
52     /*
53         if (IsWindowVisible(hToolBar)) {
54                 SendMessage(hToolBar, WM_SIZE, 0, 0);
55                 GetClientRect(hToolBar, &rt);
56                 prect->top = rt.bottom+3;
57                 prect->bottom -= rt.bottom+3;
58         }
59      */
60     if (IsWindowVisible(hStatusBar)) {
61         SetupStatusBar(hWnd, TRUE);
62         GetClientRect(hStatusBar, &rt);
63         prect->bottom -= rt.bottom;
64     }
65     MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
66 }
67
68 static void resize_frame_client(HWND hWnd)
69 {
70     RECT rect;
71
72     GetClientRect(hWnd, &rect);
73     resize_frame_rect(hWnd, &rect);
74 }
75
76 /********************************************************************************/
77
78 static void OnEnterMenuLoop(HWND hWnd)
79 {
80     int nParts;
81
82     /* Update the status bar pane sizes */
83     nParts = -1;
84     SendMessage(hStatusBar, SB_SETPARTS, 1, (long)&nParts);
85     bInMenuLoop = TRUE;
86     SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
87 }
88
89 static void OnExitMenuLoop(HWND hWnd)
90 {
91     bInMenuLoop = FALSE;
92     /* Update the status bar pane sizes*/
93     SetupStatusBar(hWnd, TRUE);
94     UpdateStatusBar();
95 }
96
97 static void UpdateMenuItems(HMENU hMenu) {
98     HWND hwndTV = g_pChildWnd->hTreeWnd;
99     BOOL bIsKeySelected = FALSE;
100     HKEY hRootKey = NULL;
101     LPCTSTR keyName;
102     keyName = GetItemPath(hwndTV, TreeView_GetSelection(hwndTV), &hRootKey);
103     if (keyName && *keyName) { /* can't modify root keys */
104         bIsKeySelected = TRUE;
105     }
106     EnableMenuItem(hMenu, ID_EDIT_FIND, MF_ENABLED | MF_BYCOMMAND);
107     EnableMenuItem(hMenu, ID_EDIT_FINDNEXT, MF_ENABLED | MF_BYCOMMAND);
108     EnableMenuItem(hMenu, ID_EDIT_MODIFY, (bIsKeySelected ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
109     EnableMenuItem(hMenu, ID_EDIT_DELETE, (bIsKeySelected ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
110     EnableMenuItem(hMenu, ID_EDIT_RENAME, (bIsKeySelected ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
111     EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
112     EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE, 
113         (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
114 }
115
116 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu, short wItem)
117 {
118     if (wItem == 3) {
119         HKEY hKey;
120         while(GetMenuItemCount(hMenu)>2)
121             DeleteMenu(hMenu, 2, MF_BYPOSITION);
122         if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
123             0, KEY_READ, &hKey) == ERROR_SUCCESS) {
124             TCHAR namebuf[KEY_MAX_LEN];
125             BYTE valuebuf[4096];
126             int i = 0;
127             BOOL sep = FALSE;
128             DWORD ksize, vsize, type;
129             LONG error;
130             do {
131                 ksize = KEY_MAX_LEN;
132                 vsize = sizeof(valuebuf);
133                 error = RegEnumValue(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
134                 if (error != ERROR_SUCCESS)
135                     break;
136                 if (type == REG_SZ) {
137                     if (!sep) {
138                         AppendMenu(hMenu, MF_SEPARATOR, -1, NULL);
139                         sep = TRUE;
140                     }
141                     AppendMenu(hMenu, MF_STRING, ID_FAVORITE_FIRST+i, namebuf);
142                 }
143                 i++;
144             } while(error == ERROR_SUCCESS);
145             RegCloseKey(hKey);
146         }
147     }
148     UpdateMenuItems(hMenu);
149 }
150
151 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
152 {
153     TCHAR str[100];
154
155     _tcscpy(str, _T(""));
156     if (nFlags & MF_POPUP) {
157         if (hSysMenu != GetMenu(hWnd)) {
158             if (nItemID == 2) nItemID = 5;
159         }
160     }
161     if (LoadString(hInst, nItemID, str, 100)) {
162         /* load appropriate string*/
163         LPTSTR lpsz = str;
164         /* first newline terminates actual string*/
165         lpsz = _tcschr(lpsz, '\n');
166         if (lpsz != NULL)
167             *lpsz = '\0';
168     }
169     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
170 }
171
172 void SetupStatusBar(HWND hWnd, BOOL bResize)
173 {
174     RECT  rc;
175     int nParts;
176     GetClientRect(hWnd, &rc);
177     nParts = rc.right;
178     /*    nParts = -1;*/
179     if (bResize)
180         SendMessage(hStatusBar, WM_SIZE, 0, 0);
181     SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
182     UpdateStatusBar();
183 }
184
185 void UpdateStatusBar(void)
186 {
187     LPTSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
188     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)fullPath);
189     HeapFree(GetProcessHeap(), 0, fullPath);
190 }
191
192 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
193 {
194     BOOL vis = IsWindowVisible(hchild);
195     HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
196
197     CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
198     ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
199     resize_frame_client(hWnd);
200 }
201
202 static BOOL CheckCommDlgError(HWND hWnd)
203 {
204     DWORD dwErrorCode = CommDlgExtendedError();
205     switch (dwErrorCode) {
206     case CDERR_DIALOGFAILURE:
207         break;
208     case CDERR_FINDRESFAILURE:
209         break;
210     case CDERR_NOHINSTANCE:
211         break;
212     case CDERR_INITIALIZATION:
213         break;
214     case CDERR_NOHOOK:
215         break;
216     case CDERR_LOCKRESFAILURE:
217         break;
218     case CDERR_NOTEMPLATE:
219         break;
220     case CDERR_LOADRESFAILURE:
221         break;
222     case CDERR_STRUCTSIZE:
223         break;
224     case CDERR_LOADSTRFAILURE:
225         break;
226     case FNERR_BUFFERTOOSMALL:
227         break;
228     case CDERR_MEMALLOCFAILURE:
229         break;
230     case FNERR_INVALIDFILENAME:
231         break;
232     case CDERR_MEMLOCKFAILURE:
233         break;
234     case FNERR_SUBCLASSFAILURE:
235         break;
236     default:
237         break;
238     }
239     return TRUE;
240 }
241
242 static UINT_PTR CALLBACK ImportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
243 {
244     OPENFILENAME* pOpenFileName;
245     OFNOTIFY* pOfNotify;
246
247     switch (uiMsg) {
248     case WM_INITDIALOG:
249         pOpenFileName = (OPENFILENAME*)lParam;
250         break;
251     case WM_NOTIFY:
252         pOfNotify = (OFNOTIFY*)lParam;
253     if (pOfNotify->hdr.code == CDN_INITDONE) {}
254         break;
255     default:
256         break;
257     }
258     return 0L;
259 }
260
261 #define MAX_CUSTOM_FILTER_SIZE 50
262 TCHAR CustomFilterBuffer[MAX_CUSTOM_FILTER_SIZE];
263 TCHAR FileNameBuffer[_MAX_PATH];
264 TCHAR FileTitleBuffer[_MAX_PATH];
265
266 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
267 {
268     memset(pofn, 0, sizeof(OPENFILENAME));
269     pofn->lStructSize = sizeof(OPENFILENAME);
270     pofn->hwndOwner = hWnd;
271     pofn->hInstance = hInst;
272
273     pofn->lpstrFilter = _T("Registration Files\0*.reg\0Win9x/NT4 Registration Files (REGEDIT4)\0*.reg\0All Files (*.*)\0*.*\0\0");
274     pofn->lpstrCustomFilter = CustomFilterBuffer;
275     pofn->nMaxCustFilter = MAX_CUSTOM_FILTER_SIZE;
276     pofn->nFilterIndex = 0;
277     pofn->lpstrFile = FileNameBuffer;
278     pofn->nMaxFile = _MAX_PATH;
279     pofn->lpstrFileTitle = FileTitleBuffer;
280     pofn->nMaxFileTitle = _MAX_PATH;
281     /*    pofn->lpstrInitialDir = _T("");*/
282     /*    pofn->lpstrTitle = _T("Import Registry File");*/
283     /*    pofn->Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER + OFN_ENABLESIZING;*/
284     pofn->Flags = OFN_HIDEREADONLY;
285     /*    pofn->nFileOffset = ;*/
286     /*    pofn->nFileExtension = ;*/
287     /*    pofn->lpstrDefExt = _T("");*/
288     /*    pofn->lCustData = ;*/
289     /*    pofn->lpfnHook = ImportRegistryFile_OFNHookProc;*/
290     /*    pofn->lpTemplateName = _T("ID_DLG_IMPORT_REGFILE");*/
291     /*    pofn->lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);*/
292     /*    pofn->FlagsEx = ;*/
293     return TRUE;
294 }
295
296 static BOOL ImportRegistryFile(HWND hWnd)
297 {
298     OPENFILENAME ofn;
299
300     InitOpenFileName(hWnd, &ofn);
301     ofn.lpstrTitle = _T("Import Registry File");
302     /*    ofn.lCustData = ;*/
303     if (GetOpenFileName(&ofn)) {
304         if (!import_registry_file(ofn.lpstrFile)) {
305             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
306             return FALSE;
307         }
308 #if 0
309         get_file_name(&s, filename, MAX_PATH);
310         if (!filename[0]) {
311             printf("No file name is specified\n%s", usage);
312             return FALSE;
313             /*exit(1);*/
314         }
315         while (filename[0]) {
316             if (!import_registry_file(filename)) {
317                 perror("");
318                 printf("Can't open file \"%s\"\n", filename);
319                 return FALSE;
320                 /*exit(1);*/
321             }
322             get_file_name(&s, filename, MAX_PATH);
323         }
324 #endif
325
326     } else {
327         CheckCommDlgError(hWnd);
328     }
329     return TRUE;
330 }
331
332
333 static BOOL ExportRegistryFile(HWND hWnd)
334 {
335     OPENFILENAME ofn;
336     TCHAR ExportKeyPath[_MAX_PATH];
337
338     ExportKeyPath[0] = _T('\0');
339     InitOpenFileName(hWnd, &ofn);
340     ofn.lpstrTitle = _T("Export Registry File");
341     /*    ofn.lCustData = ;*/
342     ofn.Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER;
343     ofn.lpfnHook = ImportRegistryFile_OFNHookProc;
344     ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);
345     if (GetSaveFileName(&ofn)) {
346         BOOL result;
347         result = export_registry_key(ofn.lpstrFile, ExportKeyPath);
348         /*result = export_registry_key(ofn.lpstrFile, NULL);*/
349         /*if (!export_registry_key(ofn.lpstrFile, NULL)) {*/
350         if (!result) {
351             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
352             return FALSE;
353         }
354 #if 0
355         TCHAR filename[MAX_PATH];
356         filename[0] = '\0';
357         get_file_name(&s, filename, MAX_PATH);
358         if (!filename[0]) {
359             printf("No file name is specified\n%s", usage);
360             return FALSE;
361             /*exit(1);*/
362         }
363         if (s[0]) {
364             TCHAR reg_key_name[KEY_MAX_LEN];
365             get_file_name(&s, reg_key_name, KEY_MAX_LEN);
366             export_registry_key(filename, reg_key_name);
367         } else {
368             export_registry_key(filename, NULL);
369         }
370 #endif
371
372     } else {
373         CheckCommDlgError(hWnd);
374     }
375     return TRUE;
376 }
377
378 static BOOL PrintRegistryHive(HWND hWnd, LPCTSTR path)
379 {
380 #if 1
381     PRINTDLG pd;
382
383     ZeroMemory(&pd, sizeof(PRINTDLG));
384     pd.lStructSize = sizeof(PRINTDLG);
385     pd.hwndOwner   = hWnd;
386     pd.hDevMode    = NULL;     /* Don't forget to free or store hDevMode*/
387     pd.hDevNames   = NULL;     /* Don't forget to free or store hDevNames*/
388     pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
389     pd.nCopies     = 1;
390     pd.nFromPage   = 0xFFFF;
391     pd.nToPage     = 0xFFFF;
392     pd.nMinPage    = 1;
393     pd.nMaxPage    = 0xFFFF;
394     if (PrintDlg(&pd)) {
395         /* GDI calls to render output. */
396         DeleteDC(pd.hDC); /* Delete DC when done.*/
397     }
398 #else
399     HRESULT hResult;
400     PRINTDLGEX pd;
401
402     hResult = PrintDlgEx(&pd);
403     if (hResult == S_OK) {
404         switch (pd.dwResultAction) {
405         case PD_RESULT_APPLY:
406             /*The user clicked the Apply button and later clicked the Cancel button. This indicates that the user wants to apply the changes made in the property sheet, but does not yet want to print. The PRINTDLGEX structure contains the information specified by the user at the time the Apply button was clicked. */
407             break;
408         case PD_RESULT_CANCEL:
409             /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
410             break;
411         case PD_RESULT_PRINT:
412             /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
413             break;
414         default:
415             break;
416         }
417     } else {
418         switch (hResult) {
419         case E_OUTOFMEMORY:
420             /*Insufficient memory. */
421             break;
422         case E_INVALIDARG:
423             /* One or more arguments are invalid. */
424             break;
425         case E_POINTER:
426             /*Invalid pointer. */
427             break;
428         case E_HANDLE:
429             /*Invalid handle. */
430             break;
431         case E_FAIL:
432             /*Unspecified error. */
433             break;
434         default:
435             break;
436         }
437         return FALSE;
438     }
439 #endif
440     return TRUE;
441 }
442
443 static BOOL CopyKeyName(HWND hWnd, LPCTSTR keyName)
444 {
445     BOOL result;
446
447     result = OpenClipboard(hWnd);
448     if (result) {
449         result = EmptyClipboard();
450         if (result) {
451             int len = (_tcslen(keyName)+1)*sizeof(TCHAR);
452             HANDLE hClipData = GlobalAlloc(GHND, len);
453             LPVOID pLoc = GlobalLock(hClipData);
454             _tcscpy(pLoc, keyName);
455             GlobalUnlock(hClipData);
456             hClipData = SetClipboardData(CF_TEXT, hClipData);
457
458         } else {
459             /* error emptying clipboard*/
460             /* DWORD dwError = GetLastError(); */
461             ;
462         }
463         if (!CloseClipboard()) {
464             /* error closing clipboard*/
465             /* DWORD dwError = GetLastError(); */
466             ;
467         }
468     } else {
469         /* error opening clipboard*/
470         /* DWORD dwError = GetLastError(); */
471         ;
472     }
473     return result;
474 }
475
476 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
477 {
478     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
479             
480     switch(uMsg) {
481         case WM_INITDIALOG:
482             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
483             CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
484             CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
485             CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
486             CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
487             SendMessage(hwndValue, EM_SETLIMITTEXT, 127, 0);
488             SetWindowText(hwndValue, searchString);
489             return TRUE;
490         case WM_COMMAND:
491             switch(LOWORD(wParam)) {
492             case IDC_VALUE_NAME:
493                 if (HIWORD(wParam) == EN_UPDATE) {
494                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLength(hwndValue)>0);
495                     return TRUE;
496                 }
497                 break;
498             case IDOK:
499                 if (GetWindowTextLength(hwndValue)>0) {
500                     int mask = 0;
501                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
502                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
503                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
504                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
505                     searchMask = mask;
506                     GetWindowText(hwndValue, searchString, 128);
507                     EndDialog(hwndDlg, IDOK);
508                 }
509                 return TRUE;
510             case IDCANCEL:
511                 EndDialog(hwndDlg, IDCANCEL);
512                 return TRUE;
513             }
514             break;
515     }
516     return FALSE;
517 }
518                     
519 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
520 {
521     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
522             
523     switch(uMsg) {
524         case WM_INITDIALOG:
525             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
526             SendMessage(hwndValue, EM_SETLIMITTEXT, 127, 0);
527             return TRUE;
528         case WM_COMMAND:
529             switch(LOWORD(wParam)) {
530             case IDC_VALUE_NAME:
531                 if (HIWORD(wParam) == EN_UPDATE) {
532                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLength(hwndValue)>0);
533                     return TRUE;
534                 }
535                 break;
536             case IDOK:
537                 if (GetWindowTextLength(hwndValue)>0) {
538                     GetWindowText(hwndValue, favoriteName, 128);
539                     EndDialog(hwndDlg, IDOK);
540                 }
541                 return TRUE;
542             case IDCANCEL:
543                 EndDialog(hwndDlg, IDCANCEL);
544                 return TRUE;
545             }
546             break;
547     }
548     return FALSE;
549 }
550                     
551 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
552 {
553     HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
554             
555     switch(uMsg) {
556         case WM_INITDIALOG: {
557             HKEY hKey;
558             int i = 0;
559             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
560             if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
561                 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
562                 TCHAR namebuf[KEY_MAX_LEN];
563                 BYTE valuebuf[4096];
564                 DWORD ksize, vsize, type;
565                 LONG error;
566                 do {
567                     ksize = KEY_MAX_LEN;
568                     vsize = sizeof(valuebuf);
569                     error = RegEnumValue(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
570                     if (error != ERROR_SUCCESS)
571                         break;
572                     if (type == REG_SZ) {
573                         SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
574                     }
575                     i++;
576                 } while(error == ERROR_SUCCESS);
577                 RegCloseKey(hKey);
578             }
579             else
580                 return FALSE;
581             EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
582             SendMessage(hwndList, LB_SETCURSEL, 0, 0);
583             return TRUE;
584         }
585         case WM_COMMAND:
586             switch(LOWORD(wParam)) {
587             case IDC_NAME_LIST:
588                 if (HIWORD(wParam) == LBN_SELCHANGE) {
589                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  lParam != -1);
590                     return TRUE;
591                 }
592                 break;
593             case IDOK: {
594                 int pos = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
595                 int len = SendMessage(hwndList, LB_GETTEXTLEN, pos, 0);
596                 if (len>0) {
597                     LPTSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*(len+1));
598                     SendMessage(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
599                     if (len>127)
600                         lpName[127] = '\0';
601                     _tcscpy(favoriteName, lpName);
602                     EndDialog(hwndDlg, IDOK);
603                     HeapFree(GetProcessHeap(), 0, lpName);
604                 }
605                 return TRUE;
606             }
607             case IDCANCEL:
608                 EndDialog(hwndDlg, IDCANCEL);
609                 return TRUE;
610             }
611             break;
612     }
613     return FALSE;
614 }
615                     
616 /*******************************************************************************
617  *
618  *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
619  *
620  *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
621  *
622  */
623 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
624 {
625     HKEY hKeyRoot = 0;
626     LPCTSTR keyPath;
627     LPCTSTR valueName;
628     TCHAR newKey[MAX_NEW_KEY_LEN];
629     DWORD valueType;
630
631     keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
632     valueName = GetValueName(g_pChildWnd->hListWnd);
633
634     if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
635         HKEY hKey;
636         if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
637             0, KEY_READ, &hKey) == ERROR_SUCCESS) {
638             TCHAR namebuf[KEY_MAX_LEN];
639             BYTE valuebuf[4096];
640             DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
641             if (RegEnumValue(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL, 
642                 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
643                 TreeView_SelectItem(g_pChildWnd->hTreeWnd, 
644                                     FindPathInTree(g_pChildWnd->hTreeWnd, (TCHAR *)valuebuf));
645             }
646             RegCloseKey(hKey);
647         }
648         return TRUE;
649     }
650     switch (LOWORD(wParam)) {
651     case ID_REGISTRY_IMPORTREGISTRYFILE:
652         ImportRegistryFile(hWnd);
653         break;
654     case ID_REGISTRY_EXPORTREGISTRYFILE:
655         ExportRegistryFile(hWnd);
656         break;
657     case ID_REGISTRY_CONNECTNETWORKREGISTRY:
658         break;
659     case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
660         break;
661     case ID_REGISTRY_PRINT:
662         PrintRegistryHive(hWnd, _T(""));
663         break;
664     case ID_EDIT_DELETE:
665         if (GetFocus() == g_pChildWnd->hTreeWnd) {
666             if (keyPath == 0 || *keyPath == 0) {
667                 MessageBeep(MB_ICONHAND); 
668             } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
669                 DeleteNode(g_pChildWnd->hTreeWnd, 0);
670             }
671         } else if (GetFocus() == g_pChildWnd->hListWnd) {
672             if (DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
673                 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
674         }
675         break;
676     case ID_EDIT_MODIFY:
677         if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
678             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
679         break;
680     case ID_EDIT_FIND:
681     case ID_EDIT_FINDNEXT:
682     {
683         HTREEITEM hItem;
684         if (LOWORD(wParam) == ID_EDIT_FIND &&
685             DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
686             break;
687         if (!*searchString)
688             break;
689         hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
690         if (hItem) {
691             int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
692             HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
693             hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
694             SetCursor(hcursorOld);
695             if (hItem) {
696                 TreeView_SelectItem(g_pChildWnd->hTreeWnd, hItem);
697                 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
698                 UpdateWindow(g_pChildWnd->hTreeWnd);
699                 if (row != -1) {
700                     ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
701                     ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
702                     SetFocus(g_pChildWnd->hListWnd);
703                 } else {
704                     SetFocus(g_pChildWnd->hTreeWnd);
705                 }
706             } else {
707                 error(hWnd, IDS_NOTFOUND, searchString);
708             }
709         }
710         break;
711     }
712     case ID_EDIT_COPYKEYNAME:
713     {
714         LPTSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
715         if (fullPath) {
716             CopyKeyName(hWnd, fullPath);
717             HeapFree(GetProcessHeap(), 0, fullPath);
718         }
719         break;
720     }
721     case ID_EDIT_NEW_KEY:
722         if (CreateKey(hWnd, hKeyRoot, keyPath, newKey)) {
723             if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKey))
724                 StartKeyRename(g_pChildWnd->hTreeWnd);
725         }
726         break;
727     case ID_EDIT_NEW_STRINGVALUE:
728         valueType = REG_SZ;
729         goto create_value;
730     case ID_EDIT_NEW_BINARYVALUE:
731         valueType = REG_BINARY;
732         goto create_value;
733     case ID_EDIT_NEW_DWORDVALUE:
734         valueType = REG_DWORD;
735         /* fall through */
736     create_value:
737         if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
738             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
739             StartValueRename(g_pChildWnd->hListWnd);
740             /* FIXME: start rename */
741         }
742         break;
743     case ID_EDIT_RENAME:
744         if (keyPath == 0 || *keyPath == 0) {
745             MessageBeep(MB_ICONHAND); 
746         } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
747             StartKeyRename(g_pChildWnd->hTreeWnd);
748         } else if (GetFocus() == g_pChildWnd->hListWnd) {
749             StartValueRename(g_pChildWnd->hListWnd);
750         }
751         break;
752     break;
753     case ID_REGISTRY_PRINTERSETUP:
754         /*PRINTDLG pd;*/
755         /*PrintDlg(&pd);*/
756         /*PAGESETUPDLG psd;*/
757         /*PageSetupDlg(&psd);*/
758         break;
759     case ID_REGISTRY_OPENLOCAL:
760         break;
761     case ID_REGISTRY_EXIT:
762         DestroyWindow(hWnd);
763         break;
764     case ID_FAVORITES_ADDTOFAVORITES:
765     {
766         HKEY hKey;
767         LPTSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
768         if (lpKeyPath) {
769             if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
770                 if (RegCreateKeyEx(HKEY_CURRENT_USER, favoritesKey, 
771                     0, NULL, 0, 
772                     KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
773                     RegSetValueEx(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (_tcslen(lpKeyPath)+1)*sizeof(TCHAR));
774                     RegCloseKey(hKey);
775                 }
776             }
777             HeapFree(GetProcessHeap(), 0, lpKeyPath);
778         }
779         break;
780     }
781     case ID_FAVORITES_REMOVEFAVORITE:
782     {
783         if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
784             HKEY hKey;
785             if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
786                 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
787                 RegDeleteValue(hKey, favoriteName); 
788                 RegCloseKey(hKey);
789             }
790         }
791         break;
792     }
793     case ID_VIEW_REFRESH:
794         RefreshTreeView(g_pChildWnd->hTreeWnd);
795         /*RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL); */
796         break;
797    /*case ID_OPTIONS_TOOLBAR:*/
798    /*   toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
799    /*    break;*/
800     case ID_VIEW_STATUSBAR:
801         toggle_child(hWnd, LOWORD(wParam), hStatusBar);
802         break;
803     case ID_HELP_HELPTOPICS:
804         WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
805         break;
806     case ID_HELP_ABOUT:
807         ShowAboutBox(hWnd);
808         break;
809     case ID_VIEW_SPLIT: {
810         RECT rt;
811         POINT pt, pts;
812         GetClientRect(g_pChildWnd->hWnd, &rt);
813         pt.x = rt.left + g_pChildWnd->nSplitPos;
814         pt.y = (rt.bottom / 2);
815         pts = pt;
816         if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
817             SetCursorPos(pts.x, pts.y);
818             SetCursor(LoadCursor(0, IDC_SIZEWE));
819             SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
820         }
821         return TRUE;
822     }
823     default:
824         return FALSE;
825     }
826
827     return TRUE;
828 }
829
830 /********************************************************************************
831  *
832  *  FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
833  *
834  *  PURPOSE:  Processes messages for the main frame window.
835  *
836  *  WM_COMMAND  - process the application menu
837  *  WM_DESTROY  - post a quit message and return
838  *
839  */
840
841 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
842 {
843     switch (message) {
844     case WM_CREATE:
845         CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
846                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
847                        hWnd, NULL, hInst, 0);
848         break;
849     case WM_COMMAND:
850         if (!_CmdWndProc(hWnd, message, wParam, lParam))
851             return DefWindowProc(hWnd, message, wParam, lParam);
852         break;
853     case WM_ACTIVATE:
854         if (LOWORD(hWnd)) 
855             SetFocus(g_pChildWnd->hWnd);
856         break;
857     case WM_SIZE:
858         resize_frame_client(hWnd);
859         break;
860     case WM_TIMER:
861         break;
862     case WM_ENTERMENULOOP:
863         OnEnterMenuLoop(hWnd);
864         break;
865     case WM_EXITMENULOOP:
866         OnExitMenuLoop(hWnd);
867         break;
868     case WM_INITMENUPOPUP:
869         if (!HIWORD(lParam))
870             OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
871         break;
872     case WM_MENUSELECT:
873         OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
874         break;
875     case WM_DESTROY:
876         WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
877         PostQuitMessage(0);
878     default:
879         return DefWindowProc(hWnd, message, wParam, lParam);
880     }
881     return 0;
882 }