Added 24/32 bit sample size and 4/6 channel support.
[wine] / programs / regedit / framewnd.c
1 /*
2  * Regedit frame window
3  *
4  * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define WIN32_LEAN_AND_MEAN     /* Exclude rarely-used stuff from Windows headers */
22
23 #include <windows.h>
24 #include <tchar.h>
25 #include <commctrl.h>
26 #include <commdlg.h>
27 #include <cderr.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <shellapi.h>
31
32 #include "main.h"
33 #include "regproc.h"
34
35 /********************************************************************************
36  * Global and Local Variables:
37  */
38
39 static BOOL bInMenuLoop = FALSE;        /* Tells us if we are in the menu loop */
40
41 /*******************************************************************************
42  * Local module support methods
43  */
44
45 static void resize_frame_rect(HWND hWnd, PRECT prect)
46 {
47     RECT rt;
48     /*
49         if (IsWindowVisible(hToolBar)) {
50                 SendMessage(hToolBar, WM_SIZE, 0, 0);
51                 GetClientRect(hToolBar, &rt);
52                 prect->top = rt.bottom+3;
53                 prect->bottom -= rt.bottom+3;
54         }
55      */
56     if (IsWindowVisible(hStatusBar)) {
57         SetupStatusBar(hWnd, TRUE);
58         GetClientRect(hStatusBar, &rt);
59         prect->bottom -= rt.bottom;
60     }
61     MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
62 }
63
64 void resize_frame_client(HWND hWnd)
65 {
66     RECT rect;
67
68     GetClientRect(hWnd, &rect);
69     resize_frame_rect(hWnd, &rect);
70 }
71
72 /********************************************************************************/
73
74 static void OnEnterMenuLoop(HWND hWnd)
75 {
76     int nParts;
77
78     /* Update the status bar pane sizes */
79     nParts = -1;
80     SendMessage(hStatusBar, SB_SETPARTS, 1, (long)&nParts);
81     bInMenuLoop = TRUE;
82     SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
83 }
84
85 static void OnExitMenuLoop(HWND hWnd)
86 {
87     bInMenuLoop = FALSE;
88     /* Update the status bar pane sizes*/
89     SetupStatusBar(hWnd, TRUE);
90     UpdateStatusBar();
91 }
92
93 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
94 {
95     TCHAR str[100];
96
97     _tcscpy(str, _T(""));
98     if (nFlags & MF_POPUP) {
99         if (hSysMenu != GetMenu(hWnd)) {
100             if (nItemID == 2) nItemID = 5;
101         }
102     }
103     if (LoadString(hInst, nItemID, str, 100)) {
104         /* load appropriate string*/
105         LPTSTR lpsz = str;
106         /* first newline terminates actual string*/
107         lpsz = _tcschr(lpsz, '\n');
108         if (lpsz != NULL)
109             *lpsz = '\0';
110     }
111     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
112 }
113
114 void SetupStatusBar(HWND hWnd, BOOL bResize)
115 {
116     RECT  rc;
117     int nParts;
118     GetClientRect(hWnd, &rc);
119     nParts = rc.right;
120     /*    nParts = -1;*/
121     if (bResize)
122         SendMessage(hStatusBar, WM_SIZE, 0, 0);
123     SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
124 }
125
126 void UpdateStatusBar(void)
127 {
128     TCHAR text[260];
129     DWORD size;
130
131     size = sizeof(text)/sizeof(TCHAR);
132     GetComputerName(text, &size);
133     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
134 }
135
136 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
137 {
138     BOOL vis = IsWindowVisible(hchild);
139     HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
140
141     CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
142     ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
143     resize_frame_client(hWnd);
144 }
145
146 static BOOL CheckCommDlgError(HWND hWnd)
147 {
148     DWORD dwErrorCode = CommDlgExtendedError();
149     switch (dwErrorCode) {
150     case CDERR_DIALOGFAILURE:
151         break;
152     case CDERR_FINDRESFAILURE:
153         break;
154     case CDERR_NOHINSTANCE:
155         break;
156     case CDERR_INITIALIZATION:
157         break;
158     case CDERR_NOHOOK:
159         break;
160     case CDERR_LOCKRESFAILURE:
161         break;
162     case CDERR_NOTEMPLATE:
163         break;
164     case CDERR_LOADRESFAILURE:
165         break;
166     case CDERR_STRUCTSIZE:
167         break;
168     case CDERR_LOADSTRFAILURE:
169         break;
170     case FNERR_BUFFERTOOSMALL:
171         break;
172     case CDERR_MEMALLOCFAILURE:
173         break;
174     case FNERR_INVALIDFILENAME:
175         break;
176     case CDERR_MEMLOCKFAILURE:
177         break;
178     case FNERR_SUBCLASSFAILURE:
179         break;
180     default:
181         break;
182     }
183     return TRUE;
184 }
185
186 UINT_PTR CALLBACK ImportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
187 {
188     OPENFILENAME* pOpenFileName;
189     OFNOTIFY* pOfNotify;
190
191     switch (uiMsg) {
192     case WM_INITDIALOG:
193         pOpenFileName = (OPENFILENAME*)lParam;
194         break;
195     case WM_NOTIFY:
196         pOfNotify = (OFNOTIFY*)lParam;
197     if (pOfNotify->hdr.code == CDN_INITDONE) {}
198         break;
199     default:
200         break;
201     }
202     return 0L;
203 }
204
205 #define MAX_CUSTOM_FILTER_SIZE 50
206 TCHAR CustomFilterBuffer[MAX_CUSTOM_FILTER_SIZE];
207 TCHAR FileNameBuffer[_MAX_PATH];
208 TCHAR FileTitleBuffer[_MAX_PATH];
209
210 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
211 {
212     memset(pofn, 0, sizeof(OPENFILENAME));
213     pofn->lStructSize = sizeof(OPENFILENAME);
214     pofn->hwndOwner = hWnd;
215     pofn->hInstance = hInst;
216
217     pofn->lpstrFilter = _T("Registration Files\0*.reg\0Win9x/NT4 Registration Files (REGEDIT4)\0*.reg\0All Files (*.*)\0*.*\0\0");
218     pofn->lpstrCustomFilter = CustomFilterBuffer;
219     pofn->nMaxCustFilter = MAX_CUSTOM_FILTER_SIZE;
220     pofn->nFilterIndex = 0;
221     pofn->lpstrFile = FileNameBuffer;
222     pofn->nMaxFile = _MAX_PATH;
223     pofn->lpstrFileTitle = FileTitleBuffer;
224     pofn->nMaxFileTitle = _MAX_PATH;
225     /*    pofn->lpstrInitialDir = _T("");*/
226     /*    pofn->lpstrTitle = _T("Import Registry File");*/
227     /*    pofn->Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER + OFN_ENABLESIZING;*/
228     pofn->Flags = OFN_HIDEREADONLY;
229     /*    pofn->nFileOffset = ;*/
230     /*    pofn->nFileExtension = ;*/
231     /*    pofn->lpstrDefExt = _T("");*/
232     /*    pofn->lCustData = ;*/
233     /*    pofn->lpfnHook = ImportRegistryFile_OFNHookProc;*/
234     /*    pofn->lpTemplateName = _T("ID_DLG_IMPORT_REGFILE");*/
235     /*    pofn->lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);*/
236     /*    pofn->FlagsEx = ;*/
237     return TRUE;
238 }
239
240 static BOOL ImportRegistryFile(HWND hWnd)
241 {
242     OPENFILENAME ofn;
243
244     InitOpenFileName(hWnd, &ofn);
245     ofn.lpstrTitle = _T("Import Registry File");
246     /*    ofn.lCustData = ;*/
247     if (GetOpenFileName(&ofn)) {
248         if (!import_registry_file(ofn.lpstrFile)) {
249             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
250             return FALSE;
251         }
252 #if 0
253         get_file_name(&s, filename, MAX_PATH);
254         if (!filename[0]) {
255             printf("No file name is specified\n%s", usage);
256             return FALSE;
257             /*exit(1);*/
258         }
259         while (filename[0]) {
260             if (!import_registry_file(filename)) {
261                 perror("");
262                 printf("Can't open file \"%s\"\n", filename);
263                 return FALSE;
264                 /*exit(1);*/
265             }
266             get_file_name(&s, filename, MAX_PATH);
267         }
268 #endif
269
270     } else {
271         CheckCommDlgError(hWnd);
272     }
273     return TRUE;
274 }
275
276
277 static BOOL ExportRegistryFile(HWND hWnd)
278 {
279     OPENFILENAME ofn;
280     TCHAR ExportKeyPath[_MAX_PATH];
281
282     ExportKeyPath[0] = _T('\0');
283     InitOpenFileName(hWnd, &ofn);
284     ofn.lpstrTitle = _T("Export Registry File");
285     /*    ofn.lCustData = ;*/
286     ofn.Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER;
287     ofn.lpfnHook = ImportRegistryFile_OFNHookProc;
288     ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);
289     if (GetSaveFileName(&ofn)) {
290         BOOL result;
291         result = export_registry_key(ofn.lpstrFile, ExportKeyPath);
292         /*result = export_registry_key(ofn.lpstrFile, NULL);*/
293         /*if (!export_registry_key(ofn.lpstrFile, NULL)) {*/
294         if (!result) {
295             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
296             return FALSE;
297         }
298 #if 0
299         TCHAR filename[MAX_PATH];
300         filename[0] = '\0';
301         get_file_name(&s, filename, MAX_PATH);
302         if (!filename[0]) {
303             printf("No file name is specified\n%s", usage);
304             return FALSE;
305             /*exit(1);*/
306         }
307         if (s[0]) {
308             TCHAR reg_key_name[KEY_MAX_LEN];
309             get_file_name(&s, reg_key_name, KEY_MAX_LEN);
310             export_registry_key(filename, reg_key_name);
311         } else {
312             export_registry_key(filename, NULL);
313         }
314 #endif
315
316     } else {
317         CheckCommDlgError(hWnd);
318     }
319     return TRUE;
320 }
321
322 BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
323 {
324 #if 1
325     PRINTDLG pd;
326
327     ZeroMemory(&pd, sizeof(PRINTDLG));
328     pd.lStructSize = sizeof(PRINTDLG);
329     pd.hwndOwner   = hWnd;
330     pd.hDevMode    = NULL;     /* Don't forget to free or store hDevMode*/
331     pd.hDevNames   = NULL;     /* Don't forget to free or store hDevNames*/
332     pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
333     pd.nCopies     = 1;
334     pd.nFromPage   = 0xFFFF;
335     pd.nToPage     = 0xFFFF;
336     pd.nMinPage    = 1;
337     pd.nMaxPage    = 0xFFFF;
338     if (PrintDlg(&pd) == TRUE) {
339         /* GDI calls to render output. */
340         DeleteDC(pd.hDC); /* Delete DC when done.*/
341     }
342 #else
343     HRESULT hResult;
344     PRINTDLGEX pd;
345
346     hResult = PrintDlgEx(&pd);
347     if (hResult == S_OK) {
348         switch (pd.dwResultAction) {
349         case PD_RESULT_APPLY:
350             /*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. */
351             break;
352         case PD_RESULT_CANCEL:
353             /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
354             break;
355         case PD_RESULT_PRINT:
356             /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
357             break;
358         default:
359             break;
360         }
361     } else {
362         switch (hResult) {
363         case E_OUTOFMEMORY:
364             /*Insufficient memory. */
365             break;
366         case E_INVALIDARG:
367             /* One or more arguments are invalid. */
368             break;
369         case E_POINTER:
370             /*Invalid pointer. */
371             break;
372         case E_HANDLE:
373             /*Invalid handle. */
374             break;
375         case E_FAIL:
376             /*Unspecified error. */
377             break;
378         default:
379             break;
380         }
381         return FALSE;
382     }
383 #endif
384     return TRUE;
385 }
386
387 BOOL CopyKeyName(HWND hWnd, LPTSTR keyName)
388 {
389     BOOL result;
390
391     result = OpenClipboard(hWnd);
392     if (result) {
393         result = EmptyClipboard();
394         if (result) {
395
396             /*HANDLE hClipData;*/
397             /*hClipData = SetClipboardData(UINT uFormat, HANDLE hMem);*/
398
399         } else {
400             /* error emptying clipboard*/
401             /* DWORD dwError = GetLastError(); */
402             ;
403         }
404         if (!CloseClipboard()) {
405             /* error closing clipboard*/
406             /* DWORD dwError = GetLastError(); */
407             ;
408         }
409     } else {
410         /* error opening clipboard*/
411         /* DWORD dwError = GetLastError(); */
412         ;
413     }
414     return result;
415 }
416
417 BOOL RefreshView(HWND hWnd)
418 {
419     /* TODO:*/
420     MessageBeep(-1);
421     MessageBeep(MB_ICONASTERISK);
422     MessageBeep(MB_ICONEXCLAMATION);
423     MessageBeep(MB_ICONHAND);
424     MessageBeep(MB_ICONQUESTION);
425     MessageBeep(MB_OK);
426     return TRUE;
427 }
428
429 /*******************************************************************************
430  *
431  *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
432  *
433  *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
434  *
435  */
436 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
437 {
438     HKEY hKeyRoot = 0;
439     LPCTSTR keyPath;
440     LPCTSTR valueName;
441     TCHAR newKey[MAX_NEW_KEY_LEN];
442     DWORD valueType;
443
444     keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
445     valueName = GetValueName(g_pChildWnd->hListWnd);
446
447     switch (LOWORD(wParam)) {
448     case ID_REGISTRY_IMPORTREGISTRYFILE:
449         ImportRegistryFile(hWnd);
450         break;
451     case ID_REGISTRY_EXPORTREGISTRYFILE:
452         ExportRegistryFile(hWnd);
453         break;
454     case ID_REGISTRY_CONNECTNETWORKREGISTRY:
455         break;
456     case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
457         break;
458     case ID_REGISTRY_PRINT:
459         PrintRegistryHive(hWnd, _T(""));
460         break;
461     case ID_EDIT_DELETE:
462         if (GetFocus() == g_pChildWnd->hTreeWnd) {
463             if (keyPath == 0 || *keyPath == 0) {
464                 MessageBeep(MB_ICONHAND); 
465             } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
466                 DeleteNode(g_pChildWnd->hTreeWnd, 0);
467             }
468         } else if (GetFocus() == g_pChildWnd->hListWnd) {
469             if (DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
470                 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
471         }
472         break;
473     case ID_EDIT_MODIFY:
474         if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
475             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
476         break;
477     case ID_EDIT_COPYKEYNAME:
478         CopyKeyName(hWnd, _T(""));
479         break;
480     case ID_EDIT_NEW_KEY:
481         if (CreateKey(hWnd, hKeyRoot, keyPath, newKey)) {
482             if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKey))
483                 StartKeyRename(g_pChildWnd->hTreeWnd);
484         }
485         break;
486     case ID_EDIT_NEW_STRINGVALUE:
487         valueType = REG_SZ;
488         goto create_value;
489     case ID_EDIT_NEW_BINARYVALUE:
490         valueType = REG_BINARY;
491         goto create_value;
492     case ID_EDIT_NEW_DWORDVALUE:
493         valueType = REG_DWORD;
494         /* fall through */
495     create_value:
496         if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
497             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
498             StartValueRename(g_pChildWnd->hListWnd);
499             /* FIXME: start rename */
500         }
501         break;
502     case ID_EDIT_RENAME:
503         if (keyPath == 0 || *keyPath == 0) {
504             MessageBeep(MB_ICONHAND); 
505         } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
506             StartKeyRename(g_pChildWnd->hTreeWnd);
507         } else if (GetFocus() == g_pChildWnd->hListWnd) {
508             StartValueRename(g_pChildWnd->hListWnd);
509         }
510         break;
511     break;
512     case ID_REGISTRY_PRINTERSETUP:
513         /*PRINTDLG pd;*/
514         /*PrintDlg(&pd);*/
515         /*PAGESETUPDLG psd;*/
516         /*PageSetupDlg(&psd);*/
517         break;
518     case ID_REGISTRY_OPENLOCAL:
519         break;
520     case ID_REGISTRY_EXIT:
521         DestroyWindow(hWnd);
522         break;
523     case ID_VIEW_REFRESH:
524         RefreshView(hWnd);
525         break;
526    /*case ID_OPTIONS_TOOLBAR:*/
527    /*   toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
528    /*    break;*/
529     case ID_VIEW_STATUSBAR:
530         toggle_child(hWnd, LOWORD(wParam), hStatusBar);
531         break;
532     case ID_HELP_HELPTOPICS:
533         WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
534         break;
535     case ID_HELP_ABOUT:
536         ShowAboutBox(hWnd);
537         break;
538     case ID_VIEW_SPLIT: {
539         RECT rt;
540         POINT pt, pts;
541         GetClientRect(g_pChildWnd->hWnd, &rt);
542         pt.x = rt.left + g_pChildWnd->nSplitPos;
543         pt.y = (rt.bottom / 2);
544         pts = pt;
545         if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
546             SetCursorPos(pts.x, pts.y);
547             SetCursor(LoadCursor(0, IDC_SIZEWE));
548             SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
549         }
550         return TRUE;
551     }
552     default:
553         return FALSE;
554     }
555
556     return TRUE;
557 }
558
559 /********************************************************************************
560  *
561  *  FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
562  *
563  *  PURPOSE:  Processes messages for the main frame window.
564  *
565  *  WM_COMMAND  - process the application menu
566  *  WM_DESTROY  - post a quit message and return
567  *
568  */
569
570 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
571 {
572     switch (message) {
573     case WM_CREATE:
574         CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
575                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
576                        hWnd, (HMENU)0, hInst, 0);
577         break;
578     case WM_COMMAND:
579         if (!_CmdWndProc(hWnd, message, wParam, lParam))
580             return DefWindowProc(hWnd, message, wParam, lParam);
581         break;
582     case WM_ACTIVATE:
583         if (LOWORD(hWnd)) 
584             SetFocus(g_pChildWnd->hWnd);
585         break;
586     case WM_SIZE:
587         resize_frame_client(hWnd);
588         break;
589     case WM_TIMER:
590         break;
591     case WM_ENTERMENULOOP:
592         OnEnterMenuLoop(hWnd);
593         break;
594     case WM_EXITMENULOOP:
595         OnExitMenuLoop(hWnd);
596         break;
597     case WM_MENUSELECT:
598         OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
599         break;
600     case WM_DESTROY:
601         WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
602         PostQuitMessage(0);
603     default:
604         return DefWindowProc(hWnd, message, wParam, lParam);
605     }
606     return 0;
607 }