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