oleaut32/tests: Replace some macros by functions to reduce code size and compile...
[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 /*******************************************************************************
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 void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAME *pOpenFileName)
243 {
244     if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
245     {
246         INT len = SendDlgItemMessage(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
247         pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(TCHAR));
248         SendDlgItemMessage(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
249     }
250     else
251         pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR));
252 }
253
254 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
255 {
256     static OPENFILENAME* pOpenFileName;
257     OFNOTIFY *pOfNotify;
258     LPTSTR path;
259
260     switch (uiMsg) {
261     case WM_INITDIALOG:
262         pOpenFileName = (OPENFILENAME*)lParam;
263         break;
264     case WM_COMMAND:
265         if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
266             CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
267         break;
268     case WM_NOTIFY:
269         pOfNotify = (OFNOTIFY*)lParam;
270         switch (pOfNotify->hdr.code)
271         {
272             case CDN_INITDONE:
273                 path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
274                 SendDlgItemMessage(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
275                 HeapFree(GetProcessHeap(), 0, path);
276                 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_ALL);
277                 break;
278             case CDN_FILEOK:
279                 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
280                 break;
281         }
282         break;
283     default:
284         break;
285     }
286     return 0L;
287 }
288
289 TCHAR FileNameBuffer[_MAX_PATH];
290 TCHAR FileTitleBuffer[_MAX_PATH];
291 TCHAR FilterBuffer[_MAX_PATH];
292
293 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME *pofn)
294 {
295     memset(pofn, 0, sizeof(OPENFILENAME));
296     pofn->lStructSize = sizeof(OPENFILENAME);
297     pofn->hwndOwner = hWnd;
298     pofn->hInstance = hInst;
299
300     if (FilterBuffer[0] == 0)
301         LoadString(hInst, IDS_FILEDIALOG_FILTER, FilterBuffer, _MAX_PATH);
302     pofn->lpstrFilter = FilterBuffer;
303     pofn->nFilterIndex = 1;
304     pofn->lpstrFile = FileNameBuffer;
305     pofn->nMaxFile = _MAX_PATH;
306     pofn->lpstrFileTitle = FileTitleBuffer;
307     pofn->nMaxFileTitle = _MAX_PATH;
308     pofn->Flags = OFN_HIDEREADONLY;
309     /* some other fields may be set by the caller */
310     return TRUE;
311 }
312
313 static BOOL ImportRegistryFile(HWND hWnd)
314 {
315     OPENFILENAME ofn;
316     TCHAR title[128];
317
318     InitOpenFileName(hWnd, &ofn);
319     LoadString(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
320     ofn.lpstrTitle = title;
321     if (GetOpenFileName(&ofn)) {
322         if (!import_registry_file(ofn.lpstrFile)) {
323             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
324             return FALSE;
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     TCHAR title[128];
338
339     ExportKeyPath[0] = _T('\0');
340     InitOpenFileName(hWnd, &ofn);
341     LoadString(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
342     ofn.lpstrTitle = title;
343     ofn.lCustData = 0; 
344     ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
345     ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
346     ofn.lpTemplateName = MAKEINTRESOURCE(IDD_EXPORT_TEMPLATE);
347     if (GetSaveFileName(&ofn)) {
348         BOOL result;
349         result = export_registry_key(ofn.lpstrFile, (LPTSTR)ofn.lCustData);
350         if (!result) {
351             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
352             return FALSE;
353         }
354     } else {
355         CheckCommDlgError(hWnd);
356     }
357     return TRUE;
358 }
359
360 static BOOL PrintRegistryHive(HWND hWnd, LPCTSTR path)
361 {
362 #if 1
363     PRINTDLG pd;
364
365     ZeroMemory(&pd, sizeof(PRINTDLG));
366     pd.lStructSize = sizeof(PRINTDLG);
367     pd.hwndOwner   = hWnd;
368     pd.hDevMode    = NULL;     /* Don't forget to free or store hDevMode*/
369     pd.hDevNames   = NULL;     /* Don't forget to free or store hDevNames*/
370     pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
371     pd.nCopies     = 1;
372     pd.nFromPage   = 0xFFFF;
373     pd.nToPage     = 0xFFFF;
374     pd.nMinPage    = 1;
375     pd.nMaxPage    = 0xFFFF;
376     if (PrintDlg(&pd)) {
377         /* GDI calls to render output. */
378         DeleteDC(pd.hDC); /* Delete DC when done.*/
379     }
380 #else
381     HRESULT hResult;
382     PRINTDLGEX pd;
383
384     hResult = PrintDlgEx(&pd);
385     if (hResult == S_OK) {
386         switch (pd.dwResultAction) {
387         case PD_RESULT_APPLY:
388             /*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. */
389             break;
390         case PD_RESULT_CANCEL:
391             /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
392             break;
393         case PD_RESULT_PRINT:
394             /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
395             break;
396         default:
397             break;
398         }
399     } else {
400         switch (hResult) {
401         case E_OUTOFMEMORY:
402             /*Insufficient memory. */
403             break;
404         case E_INVALIDARG:
405             /* One or more arguments are invalid. */
406             break;
407         case E_POINTER:
408             /*Invalid pointer. */
409             break;
410         case E_HANDLE:
411             /*Invalid handle. */
412             break;
413         case E_FAIL:
414             /*Unspecified error. */
415             break;
416         default:
417             break;
418         }
419         return FALSE;
420     }
421 #endif
422     return TRUE;
423 }
424
425 static BOOL CopyKeyName(HWND hWnd, LPCTSTR keyName)
426 {
427     BOOL result;
428
429     result = OpenClipboard(hWnd);
430     if (result) {
431         result = EmptyClipboard();
432         if (result) {
433             int len = (_tcslen(keyName)+1)*sizeof(TCHAR);
434             HANDLE hClipData = GlobalAlloc(GHND, len);
435             LPVOID pLoc = GlobalLock(hClipData);
436             _tcscpy(pLoc, keyName);
437             GlobalUnlock(hClipData);
438             hClipData = SetClipboardData(CF_TEXT, hClipData);
439
440         } else {
441             /* error emptying clipboard*/
442             /* DWORD dwError = GetLastError(); */
443             ;
444         }
445         if (!CloseClipboard()) {
446             /* error closing clipboard*/
447             /* DWORD dwError = GetLastError(); */
448             ;
449         }
450     } else {
451         /* error opening clipboard*/
452         /* DWORD dwError = GetLastError(); */
453         ;
454     }
455     return result;
456 }
457
458 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
459 {
460     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
461             
462     switch(uMsg) {
463         case WM_INITDIALOG:
464             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
465             CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
466             CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
467             CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
468             CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
469             SendMessage(hwndValue, EM_SETLIMITTEXT, 127, 0);
470             SetWindowText(hwndValue, searchString);
471             return TRUE;
472         case WM_COMMAND:
473             switch(LOWORD(wParam)) {
474             case IDC_VALUE_NAME:
475                 if (HIWORD(wParam) == EN_UPDATE) {
476                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLength(hwndValue)>0);
477                     return TRUE;
478                 }
479                 break;
480             case IDOK:
481                 if (GetWindowTextLength(hwndValue)>0) {
482                     int mask = 0;
483                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
484                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
485                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
486                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
487                     searchMask = mask;
488                     GetWindowText(hwndValue, searchString, 128);
489                     EndDialog(hwndDlg, IDOK);
490                 }
491                 return TRUE;
492             case IDCANCEL:
493                 EndDialog(hwndDlg, IDCANCEL);
494                 return TRUE;
495             }
496             break;
497     }
498     return FALSE;
499 }
500                     
501 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
502 {
503     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
504             
505     switch(uMsg) {
506         case WM_INITDIALOG:
507             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
508             SendMessage(hwndValue, EM_SETLIMITTEXT, 127, 0);
509             return TRUE;
510         case WM_COMMAND:
511             switch(LOWORD(wParam)) {
512             case IDC_VALUE_NAME:
513                 if (HIWORD(wParam) == EN_UPDATE) {
514                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLength(hwndValue)>0);
515                     return TRUE;
516                 }
517                 break;
518             case IDOK:
519                 if (GetWindowTextLength(hwndValue)>0) {
520                     GetWindowText(hwndValue, favoriteName, 128);
521                     EndDialog(hwndDlg, IDOK);
522                 }
523                 return TRUE;
524             case IDCANCEL:
525                 EndDialog(hwndDlg, IDCANCEL);
526                 return TRUE;
527             }
528             break;
529     }
530     return FALSE;
531 }
532                     
533 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
534 {
535     HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
536             
537     switch(uMsg) {
538         case WM_INITDIALOG: {
539             HKEY hKey;
540             int i = 0;
541             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
542             if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
543                 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
544                 TCHAR namebuf[KEY_MAX_LEN];
545                 BYTE valuebuf[4096];
546                 DWORD ksize, vsize, type;
547                 LONG error;
548                 do {
549                     ksize = KEY_MAX_LEN;
550                     vsize = sizeof(valuebuf);
551                     error = RegEnumValue(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
552                     if (error != ERROR_SUCCESS)
553                         break;
554                     if (type == REG_SZ) {
555                         SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
556                     }
557                     i++;
558                 } while(error == ERROR_SUCCESS);
559                 RegCloseKey(hKey);
560             }
561             else
562                 return FALSE;
563             EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
564             SendMessage(hwndList, LB_SETCURSEL, 0, 0);
565             return TRUE;
566         }
567         case WM_COMMAND:
568             switch(LOWORD(wParam)) {
569             case IDC_NAME_LIST:
570                 if (HIWORD(wParam) == LBN_SELCHANGE) {
571                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  lParam != -1);
572                     return TRUE;
573                 }
574                 break;
575             case IDOK: {
576                 int pos = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
577                 int len = SendMessage(hwndList, LB_GETTEXTLEN, pos, 0);
578                 if (len>0) {
579                     LPTSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*(len+1));
580                     SendMessage(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
581                     if (len>127)
582                         lpName[127] = '\0';
583                     _tcscpy(favoriteName, lpName);
584                     EndDialog(hwndDlg, IDOK);
585                     HeapFree(GetProcessHeap(), 0, lpName);
586                 }
587                 return TRUE;
588             }
589             case IDCANCEL:
590                 EndDialog(hwndDlg, IDCANCEL);
591                 return TRUE;
592             }
593             break;
594     }
595     return FALSE;
596 }
597                     
598 /*******************************************************************************
599  *
600  *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
601  *
602  *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
603  *
604  */
605 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
606 {
607     HKEY hKeyRoot = 0;
608     LPCTSTR keyPath;
609     LPCTSTR valueName;
610     TCHAR newKey[MAX_NEW_KEY_LEN];
611     DWORD valueType;
612
613     keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
614     valueName = GetValueName(g_pChildWnd->hListWnd);
615
616     if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
617         HKEY hKey;
618         if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
619             0, KEY_READ, &hKey) == ERROR_SUCCESS) {
620             TCHAR namebuf[KEY_MAX_LEN];
621             BYTE valuebuf[4096];
622             DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
623             if (RegEnumValue(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL, 
624                 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
625                 SendMessage( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
626                              (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (TCHAR *)valuebuf) );
627             }
628             RegCloseKey(hKey);
629         }
630         return TRUE;
631     }
632     switch (LOWORD(wParam)) {
633     case ID_REGISTRY_IMPORTREGISTRYFILE:
634         ImportRegistryFile(hWnd);
635         break;
636     case ID_REGISTRY_EXPORTREGISTRYFILE:
637         ExportRegistryFile(hWnd);
638         break;
639     case ID_REGISTRY_CONNECTNETWORKREGISTRY:
640         break;
641     case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
642         break;
643     case ID_REGISTRY_PRINT:
644         PrintRegistryHive(hWnd, _T(""));
645         break;
646     case ID_EDIT_DELETE:
647         if (GetFocus() == g_pChildWnd->hTreeWnd) {
648             if (keyPath == 0 || *keyPath == 0) {
649                 MessageBeep(MB_ICONHAND); 
650             } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
651                 DeleteNode(g_pChildWnd->hTreeWnd, 0);
652             }
653         } else if (GetFocus() == g_pChildWnd->hListWnd) {
654             if (DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
655                 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
656         }
657         break;
658     case ID_EDIT_MODIFY:
659         if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
660             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
661         break;
662     case ID_EDIT_FIND:
663     case ID_EDIT_FINDNEXT:
664     {
665         HTREEITEM hItem;
666         if (LOWORD(wParam) == ID_EDIT_FIND &&
667             DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
668             break;
669         if (!*searchString)
670             break;
671         hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
672         if (hItem) {
673             int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
674             HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
675             hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
676             SetCursor(hcursorOld);
677             if (hItem) {
678                 SendMessage( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
679                 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
680                 UpdateWindow(g_pChildWnd->hTreeWnd);
681                 if (row != -1) {
682                     ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
683                     ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
684                     SetFocus(g_pChildWnd->hListWnd);
685                 } else {
686                     SetFocus(g_pChildWnd->hTreeWnd);
687                 }
688             } else {
689                 error(hWnd, IDS_NOTFOUND, searchString);
690             }
691         }
692         break;
693     }
694     case ID_EDIT_COPYKEYNAME:
695     {
696         LPTSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
697         if (fullPath) {
698             CopyKeyName(hWnd, fullPath);
699             HeapFree(GetProcessHeap(), 0, fullPath);
700         }
701         break;
702     }
703     case ID_EDIT_NEW_KEY:
704         if (CreateKey(hWnd, hKeyRoot, keyPath, newKey)) {
705             if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKey))
706                 StartKeyRename(g_pChildWnd->hTreeWnd);
707         }
708         break;
709     case ID_EDIT_NEW_STRINGVALUE:
710         valueType = REG_SZ;
711         goto create_value;
712     case ID_EDIT_NEW_BINARYVALUE:
713         valueType = REG_BINARY;
714         goto create_value;
715     case ID_EDIT_NEW_DWORDVALUE:
716         valueType = REG_DWORD;
717         /* fall through */
718     create_value:
719         if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
720             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
721             StartValueRename(g_pChildWnd->hListWnd);
722             /* FIXME: start rename */
723         }
724         break;
725     case ID_EDIT_RENAME:
726         if (keyPath == 0 || *keyPath == 0) {
727             MessageBeep(MB_ICONHAND); 
728         } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
729             StartKeyRename(g_pChildWnd->hTreeWnd);
730         } else if (GetFocus() == g_pChildWnd->hListWnd) {
731             StartValueRename(g_pChildWnd->hListWnd);
732         }
733         break;
734     break;
735     case ID_REGISTRY_PRINTERSETUP:
736         /*PRINTDLG pd;*/
737         /*PrintDlg(&pd);*/
738         /*PAGESETUPDLG psd;*/
739         /*PageSetupDlg(&psd);*/
740         break;
741     case ID_REGISTRY_OPENLOCAL:
742         break;
743     case ID_REGISTRY_EXIT:
744         DestroyWindow(hWnd);
745         break;
746     case ID_FAVORITES_ADDTOFAVORITES:
747     {
748         HKEY hKey;
749         LPTSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
750         if (lpKeyPath) {
751             if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
752                 if (RegCreateKeyEx(HKEY_CURRENT_USER, favoritesKey, 
753                     0, NULL, 0, 
754                     KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
755                     RegSetValueEx(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (_tcslen(lpKeyPath)+1)*sizeof(TCHAR));
756                     RegCloseKey(hKey);
757                 }
758             }
759             HeapFree(GetProcessHeap(), 0, lpKeyPath);
760         }
761         break;
762     }
763     case ID_FAVORITES_REMOVEFAVORITE:
764     {
765         if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
766             HKEY hKey;
767             if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
768                 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
769                 RegDeleteValue(hKey, favoriteName); 
770                 RegCloseKey(hKey);
771             }
772         }
773         break;
774     }
775     case ID_VIEW_REFRESH:
776         RefreshTreeView(g_pChildWnd->hTreeWnd);
777         RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
778         break;
779    /*case ID_OPTIONS_TOOLBAR:*/
780    /*   toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
781    /*    break;*/
782     case ID_VIEW_STATUSBAR:
783         toggle_child(hWnd, LOWORD(wParam), hStatusBar);
784         break;
785     case ID_HELP_HELPTOPICS:
786         WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
787         break;
788     case ID_HELP_ABOUT:
789         ShowAboutBox(hWnd);
790         break;
791     case ID_VIEW_SPLIT: {
792         RECT rt;
793         POINT pt, pts;
794         GetClientRect(g_pChildWnd->hWnd, &rt);
795         pt.x = rt.left + g_pChildWnd->nSplitPos;
796         pt.y = (rt.bottom / 2);
797         pts = pt;
798         if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
799             SetCursorPos(pts.x, pts.y);
800             SetCursor(LoadCursor(0, IDC_SIZEWE));
801             SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
802         }
803         return TRUE;
804     }
805     default:
806         return FALSE;
807     }
808
809     return TRUE;
810 }
811
812 /********************************************************************************
813  *
814  *  FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
815  *
816  *  PURPOSE:  Processes messages for the main frame window.
817  *
818  *  WM_COMMAND  - process the application menu
819  *  WM_DESTROY  - post a quit message and return
820  *
821  */
822
823 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
824 {
825     switch (message) {
826     case WM_CREATE:
827         CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
828                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
829                        hWnd, NULL, hInst, 0);
830         break;
831     case WM_COMMAND:
832         if (!_CmdWndProc(hWnd, message, wParam, lParam))
833             return DefWindowProc(hWnd, message, wParam, lParam);
834         break;
835     case WM_ACTIVATE:
836         if (LOWORD(hWnd)) 
837             SetFocus(g_pChildWnd->hWnd);
838         break;
839     case WM_SIZE:
840         resize_frame_client(hWnd);
841         break;
842     case WM_TIMER:
843         break;
844     case WM_ENTERMENULOOP:
845         OnEnterMenuLoop(hWnd);
846         break;
847     case WM_EXITMENULOOP:
848         OnExitMenuLoop(hWnd);
849         break;
850     case WM_INITMENUPOPUP:
851         if (!HIWORD(lParam))
852             OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
853         break;
854     case WM_MENUSELECT:
855         OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
856         break;
857     case WM_DESTROY:
858         WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
859         PostQuitMessage(0);
860     default:
861         return DefWindowProc(hWnd, message, wParam, lParam);
862     }
863     return 0;
864 }