winecfg: Dutch resources update.
[wine] / programs / regedit / childwnd.c
1 /*
2  * Regedit child 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 #include <windows.h>
23 #include <commctrl.h>
24 #include <tchar.h>
25 #include <stdio.h>
26
27 #include "main.h"
28
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
31                                                                                                                              
32 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
33                                                                                                                              
34 ChildWnd* g_pChildWnd;
35
36 /*******************************************************************************
37  * Local module support methods
38  */
39
40 LPCTSTR GetRootKeyName(HKEY hRootKey)
41 {
42     if (hRootKey == HKEY_CLASSES_ROOT) return _T("HKEY_CLASSES_ROOT");
43     if (hRootKey == HKEY_CURRENT_USER) return _T("HKEY_CURRENT_USER");
44     if (hRootKey == HKEY_LOCAL_MACHINE) return _T("HKEY_LOCAL_MACHINE");
45     if (hRootKey == HKEY_USERS) return _T("HKEY_USERS");
46     if (hRootKey == HKEY_CURRENT_CONFIG) return _T("HKEY_CURRENT_CONFIG");
47     if (hRootKey == HKEY_DYN_DATA) return _T("HKEY_DYN_DATA");
48     return _T("UNKNOWN HKEY, PLEASE REPORT");
49 }
50
51 static void draw_splitbar(HWND hWnd, int x)
52 {
53     RECT rt;
54     HDC hdc = GetDC(hWnd);
55
56     GetClientRect(hWnd, &rt);
57     rt.left = x - SPLIT_WIDTH/2;
58     rt.right = x + SPLIT_WIDTH/2+1;
59     InvertRect(hdc, &rt);
60     ReleaseDC(hWnd, hdc);
61 }
62
63 static void ResizeWnd(ChildWnd* pChildWnd, int cx, int cy)
64 {
65     HDWP hdwp = BeginDeferWindowPos(2);
66     RECT rt = {0, 0, cx, cy};
67
68     cx = pChildWnd->nSplitPos + SPLIT_WIDTH/2;
69     DeferWindowPos(hdwp, pChildWnd->hTreeWnd, 0, rt.left, rt.top, pChildWnd->nSplitPos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
70     DeferWindowPos(hdwp, pChildWnd->hListWnd, 0, rt.left+cx  , rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
71     EndDeferWindowPos(hdwp);
72 }
73
74 static void OnPaint(HWND hWnd)
75 {
76     PAINTSTRUCT ps;
77     RECT rt;
78     HDC hdc;
79
80     GetClientRect(hWnd, &rt);
81     hdc = BeginPaint(hWnd, &ps);
82     FillRect(ps.hdc, &rt, GetSysColorBrush(COLOR_BTNFACE));
83     EndPaint(hWnd, &ps);
84 }
85
86 static LPTSTR CombinePaths(LPCTSTR pPaths[], int nPaths) {
87     int i, len, pos;
88     LPTSTR combined;
89     for (i=0, len=0; i<nPaths; i++) {
90         if (pPaths[i] && *pPaths[i]) {
91             len += lstrlen(pPaths[i])+1;
92         }
93     }
94     combined = HeapAlloc(GetProcessHeap(), 0, len * sizeof(TCHAR));
95     *combined = '\0';
96     for (i=0, pos=0; i<nPaths; i++) {
97         if (pPaths[i] && *pPaths[i]) {
98             int llen = _tcslen(pPaths[i]);
99             if (!*combined)
100                 _tcscpy(combined, pPaths[i]);
101             else {
102                 combined[pos++] = (TCHAR)'\\';
103                 _tcscpy(combined+pos, pPaths[i]);
104             }
105             pos += llen;
106         }
107     }
108     return combined;
109 }
110
111 LPTSTR GetItemFullPath(HWND hwndTV, HTREEITEM hItem, BOOL bFull) {
112     LPCTSTR parts[3] = {_T(""), _T(""), _T("")};
113     TCHAR text[260];
114     HKEY hRootKey = NULL;
115     if (!hItem)
116         hItem = TreeView_GetSelection(hwndTV);
117     parts[2] = GetItemPath(hwndTV, hItem, &hRootKey);
118     if (!parts[2])
119         parts[2] = _T("");
120     if (!bFull && !hRootKey && !*parts[2])
121         return NULL;
122     if (hRootKey)
123         parts[1] = GetRootKeyName(hRootKey);
124     if (bFull) {
125         DWORD dwSize = sizeof(text)/sizeof(TCHAR);
126         GetComputerName(text, &dwSize);
127         parts[0] = text;
128     }
129     return CombinePaths(parts, 3);
130 }
131
132 static void OnTreeSelectionChanged(HWND hwndTV, HWND hwndLV, HTREEITEM hItem, BOOL bRefreshLV)
133 {
134     if (bRefreshLV) {
135         LPCTSTR keyPath;
136         HKEY hRootKey = NULL;
137         keyPath = GetItemPath(hwndTV, hItem, &hRootKey);
138         RefreshListView(hwndLV, hRootKey, keyPath, NULL);
139     }
140     UpdateStatusBar();
141 }
142
143 /*******************************************************************************
144  *
145  *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
146  *
147  *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
148  *
149  */
150
151 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
152 {
153     ChildWnd* pChildWnd = g_pChildWnd;
154     switch (LOWORD(wParam)) {
155         /* Parse the menu selections: */
156     case ID_REGISTRY_EXIT:
157         DestroyWindow(hWnd);
158         break;
159     case ID_VIEW_REFRESH:
160         WINE_TRACE("Is this ever called or is it just dead code?\n");
161         /* TODO */
162         break;
163     case ID_SWITCH_PANELS:
164         pChildWnd->nFocusPanel = !pChildWnd->nFocusPanel;
165         SetFocus(pChildWnd->nFocusPanel? pChildWnd->hListWnd: pChildWnd->hTreeWnd);
166         break;
167     default:
168         return FALSE;
169     }
170     return TRUE;
171 }
172
173 /*******************************************************************************
174  *
175  *  FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG)
176  *
177  *  PURPOSE:  Processes messages for the child windows.
178  *
179  *  WM_COMMAND  - process the application menu
180  *  WM_PAINT    - Paint the main window
181  *  WM_DESTROY  - post a quit message and return
182  *
183  */
184 LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
185 {
186     static int last_split;
187     ChildWnd* pChildWnd = g_pChildWnd;
188
189     switch (message) {
190     case WM_CREATE:
191         g_pChildWnd = pChildWnd = HeapAlloc(GetProcessHeap(), 0, sizeof(ChildWnd));
192         if (!pChildWnd) return 0;
193         _tcsncpy(pChildWnd->szPath, _T("My Computer"), MAX_PATH);
194         pChildWnd->nSplitPos = 250;
195         pChildWnd->hWnd = hWnd;
196         pChildWnd->hTreeWnd = CreateTreeView(hWnd, pChildWnd->szPath, TREE_WINDOW);
197         pChildWnd->hListWnd = CreateListView(hWnd, LIST_WINDOW/*, pChildWnd->szPath*/);
198         SetFocus(pChildWnd->hTreeWnd);
199         break;
200     case WM_COMMAND:
201         if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
202             goto def;
203         }
204         break;
205     case WM_PAINT:
206         OnPaint(hWnd);
207         return 0;
208     case WM_SETCURSOR:
209         if (LOWORD(lParam) == HTCLIENT) {
210             POINT pt;
211             GetCursorPos(&pt);
212             ScreenToClient(hWnd, &pt);
213             if (pt.x>=pChildWnd->nSplitPos-SPLIT_WIDTH/2 && pt.x<pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
214                 SetCursor(LoadCursor(0, IDC_SIZEWE));
215                 return TRUE;
216             }
217         }
218         goto def;
219     case WM_DESTROY:
220         HeapFree(GetProcessHeap(), 0, pChildWnd);
221         pChildWnd = NULL;
222         PostQuitMessage(0);
223         break;
224     case WM_LBUTTONDOWN: {
225             RECT rt;
226             int x = LOWORD(lParam);
227             GetClientRect(hWnd, &rt);
228             if (x>=pChildWnd->nSplitPos-SPLIT_WIDTH/2 && x<pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) {
229                 last_split = pChildWnd->nSplitPos;
230                 draw_splitbar(hWnd, last_split);
231                 SetCapture(hWnd);
232             }
233             break;
234         }
235
236     case WM_LBUTTONUP:
237         if (GetCapture() == hWnd) {
238             RECT rt;
239             int x = LOWORD(lParam);
240             draw_splitbar(hWnd, last_split);
241             last_split = -1;
242             GetClientRect(hWnd, &rt);
243             pChildWnd->nSplitPos = x;
244             ResizeWnd(pChildWnd, rt.right, rt.bottom);
245             ReleaseCapture();
246         }
247         break;
248
249     case WM_CAPTURECHANGED:
250         if (GetCapture()==hWnd && last_split>=0)
251             draw_splitbar(hWnd, last_split);
252         break;
253
254     case WM_KEYDOWN:
255         if (wParam == VK_ESCAPE)
256             if (GetCapture() == hWnd) {
257                 RECT rt;
258                 draw_splitbar(hWnd, last_split);
259                 GetClientRect(hWnd, &rt);
260                 ResizeWnd(pChildWnd, rt.right, rt.bottom);
261                 last_split = -1;
262                 ReleaseCapture();
263                 SetCursor(LoadCursor(0, IDC_ARROW));
264             }
265         break;
266
267     case WM_MOUSEMOVE:
268         if (GetCapture() == hWnd) {
269             RECT rt;
270             int x = LOWORD(lParam);
271             HDC hdc = GetDC(hWnd);
272             GetClientRect(hWnd, &rt);
273             rt.left = last_split-SPLIT_WIDTH/2;
274             rt.right = last_split+SPLIT_WIDTH/2+1;
275             InvertRect(hdc, &rt);
276             last_split = x;
277             rt.left = x-SPLIT_WIDTH/2;
278             rt.right = x+SPLIT_WIDTH/2+1;
279             InvertRect(hdc, &rt);
280             ReleaseDC(hWnd, hdc);
281         }
282         break;
283
284     case WM_SETFOCUS:
285         if (pChildWnd != NULL) {
286             SetFocus(pChildWnd->nFocusPanel? pChildWnd->hListWnd: pChildWnd->hTreeWnd);
287         }
288         break;
289
290     case WM_TIMER:
291         break;
292
293     case WM_NOTIFY:
294         if ((int)wParam == TREE_WINDOW) {
295             switch (((LPNMHDR)lParam)->code) {
296             case TVN_ITEMEXPANDING:
297                 return !OnTreeExpanding(pChildWnd->hTreeWnd, (NMTREEVIEW*)lParam);
298             case TVN_SELCHANGED:
299                 OnTreeSelectionChanged(pChildWnd->hTreeWnd, pChildWnd->hListWnd,
300                     ((NMTREEVIEW *)lParam)->itemNew.hItem, TRUE);
301                 break;
302             case NM_SETFOCUS:
303                 pChildWnd->nFocusPanel = 0;
304                 break;
305             case NM_RCLICK: {
306                 POINT pt;
307                 GetCursorPos(&pt);
308                 TrackPopupMenu(GetSubMenu(hPopupMenus, PM_NEW),
309                                TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL);
310                 break;
311             }
312             case TVN_ENDLABELEDIT: {
313                 HKEY hRootKey;
314                 LPNMTVDISPINFO dispInfo = (LPNMTVDISPINFO)lParam;
315                 LPCTSTR path = GetItemPath(pChildWnd->hTreeWnd, 0, &hRootKey);
316                 BOOL res = RenameKey(hWnd, hRootKey, path, dispInfo->item.pszText);
317                 if (res) {
318                     TVITEMEX item;
319                     item.mask = TVIF_HANDLE | TVIF_TEXT;
320                     item.hItem = TreeView_GetSelection(pChildWnd->hTreeWnd);
321                     item.pszText = dispInfo->item.pszText;
322                     TreeView_SetItem(pChildWnd->hTreeWnd, &item);
323                 }
324                 return res;
325             }
326             default:
327                 return 0; /* goto def; */
328             }
329         } else
330             if ((int)wParam == LIST_WINDOW) {
331                 if (((LPNMHDR)lParam)->code == NM_SETFOCUS) {
332                     pChildWnd->nFocusPanel = 1;
333                 } else if (!SendMessage(pChildWnd->hListWnd, WM_NOTIFY_REFLECT, wParam, lParam)) {
334                     goto def;
335                 }
336             }
337         break;
338
339     case WM_SIZE:
340         if (wParam != SIZE_MINIMIZED && pChildWnd != NULL) {
341             ResizeWnd(pChildWnd, LOWORD(lParam), HIWORD(lParam));
342         }
343         /* fall through */
344 default: def:
345         return DefWindowProc(hWnd, message, wParam, lParam);
346     }
347     return 0;
348 }