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