Updated with latest progress. How does one read a default registry value???
[reactos.git] / rosapps / regedit / listview.c
1 /*
2 * ReactOS regedit
3 *
4 * listview.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #ifdef _MSC_VER
24 #include "stdafx.h"
25 #else
26 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <stdlib.h>
30 #include <malloc.h>
31 #include <memory.h>
32 #include <tchar.h>
33 #include <process.h>
34 #include <stdio.h>
35 #endif
36
37 #include <windowsx.h>
38 #include "main.h"
39 #include "listview.h"
40
41
42 ////////////////////////////////////////////////////////////////////////////////
43 // Global and Local Variables:
44 //
45
46 static WNDPROC g_orgListWndProc;
47
48 #define MAX_LIST_COLUMNS (IDS_LIST_COLUMN_LAST - IDS_LIST_COLUMN_FIRST + 1)
49 static int default_column_widths[MAX_LIST_COLUMNS] = { 200, 175, 400 };
50 static int column_alignment[MAX_LIST_COLUMNS] = { LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT };
51
52
53 ////////////////////////////////////////////////////////////////////////////////
54 // Local module support methods
55 //
56
57 static void AddEntryToList(HWND hwndLV, LPTSTR Name, DWORD dwValType, void* ValBuf, DWORD dwCount)
58 {
59 LVITEM item;
60
61 item.mask = LVIF_TEXT | LVIF_PARAM;
62 item.iItem = 0;//idx;
63 item.iSubItem = 0;
64 item.state = 0;
65 item.stateMask = 0;
66 item.pszText = Name;
67 item.cchTextMax = _tcslen(item.pszText);
68 item.cchTextMax = 0;
69 item.iImage = 0;
70 item.lParam = (LPARAM)dwValType;
71 // item.lParam = (LPARAM)ValBuf;
72 #if (_WIN32_IE >= 0x0300)
73 item.iIndent = 0;
74 #endif
75 ListView_InsertItem(hwndLV, &item);
76 }
77
78 static void CreateListColumns(HWND hWndListView)
79 {
80 TCHAR szText[50];
81 int index;
82 LV_COLUMN lvC;
83
84 // Create columns.
85 lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
86 lvC.pszText = szText;
87
88 // Load the column labels from the resource file.
89 for (index = 0; index < MAX_LIST_COLUMNS; index++) {
90 lvC.iSubItem = index;
91 lvC.cx = default_column_widths[index];
92 lvC.fmt = column_alignment[index];
93 LoadString(hInst, IDS_LIST_COLUMN_FIRST + index, szText, sizeof(szText));
94 if (ListView_InsertColumn(hWndListView, index, &lvC) == -1) {
95 // TODO: handle failure condition...
96 break;
97 }
98 }
99 }
100
101 // OnGetDispInfo - processes the LVN_GETDISPINFO notification message.
102
103 static void OnGetDispInfo(NMLVDISPINFO* plvdi)
104 {
105 static TCHAR buffer[200];
106
107 plvdi->item.pszText = NULL;
108 plvdi->item.cchTextMax = 0;
109
110 switch (plvdi->item.iSubItem) {
111 case 0:
112 plvdi->item.pszText = _T("(Default)");
113 break;
114 case 1:
115 switch (plvdi->item.lParam) {
116 case REG_SZ:
117 plvdi->item.pszText = _T("REG_SZ");
118 break;
119 case REG_EXPAND_SZ:
120 plvdi->item.pszText = _T("REG_EXPAND_SZ");
121 break;
122 case REG_BINARY:
123 plvdi->item.pszText = _T("REG_BINARY");
124 break;
125 case REG_DWORD:
126 plvdi->item.pszText = _T("REG_DWORD");
127 break;
128 // case REG_DWORD_LITTLE_ENDIAN:
129 // plvdi->item.pszText = _T("REG_DWORD_LITTLE_ENDIAN");
130 // break;
131 case REG_DWORD_BIG_ENDIAN:
132 plvdi->item.pszText = _T("REG_DWORD_BIG_ENDIAN");
133 break;
134 case REG_MULTI_SZ:
135 plvdi->item.pszText = _T("REG_MULTI_SZ");
136 break;
137 case REG_LINK:
138 plvdi->item.pszText = _T("REG_LINK");
139 break;
140 case REG_RESOURCE_LIST:
141 plvdi->item.pszText = _T("REG_RESOURCE_LIST");
142 break;
143 case REG_NONE:
144 plvdi->item.pszText = _T("REG_NONE");
145 break;
146 default:
147 wsprintf(buffer, _T("unknown(%d)"), plvdi->item.lParam);
148 plvdi->item.pszText = buffer;
149 break;
150 }
151 break;
152 case 2:
153 plvdi->item.pszText = _T("(value not set)");
154 break;
155 case 3:
156 plvdi->item.pszText = _T("");
157 break;
158 }
159 }
160
161 static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
162 {
163 TCHAR buf1[1000];
164 TCHAR buf2[1000];
165
166 ListView_GetItemText((HWND)lParamSort, lParam1, 0, buf1, sizeof(buf1));
167 ListView_GetItemText((HWND)lParamSort, lParam2, 0, buf2, sizeof(buf2));
168 return _tcscmp(buf1, buf2);
169 }
170
171 static void ListViewPopUpMenu(HWND hWnd, POINT pt)
172 {
173 }
174
175 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
176 {
177 switch (LOWORD(wParam)) {
178 // case ID_FILE_OPEN:
179 // break;
180 default:
181 return FALSE;
182 }
183 return TRUE;
184 }
185
186 static LRESULT CALLBACK ListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
187 {
188 switch (message) {
189 case WM_COMMAND:
190 if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
191 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
192 }
193 break;
194 case WM_NOTIFY:
195 switch (((LPNMHDR)lParam)->code) {
196 case LVN_GETDISPINFO:
197 OnGetDispInfo((NMLVDISPINFO*)lParam);
198 break;
199 case NM_DBLCLK:
200 {
201 NMITEMACTIVATE* nmitem = (LPNMITEMACTIVATE)lParam;
202 LVHITTESTINFO info;
203
204 if (nmitem->hdr.hwndFrom != hWnd) break;
205 // if (nmitem->hdr.idFrom != IDW_LISTVIEW) break;
206 // if (nmitem->hdr.code != ???) break;
207 #ifdef _MSC_VER
208 switch (nmitem->uKeyFlags) {
209 case LVKF_ALT: // The ALT key is pressed.
210 // properties dialog box ?
211 break;
212 case LVKF_CONTROL: // The CTRL key is pressed.
213 // run dialog box for providing parameters...
214 break;
215 case LVKF_SHIFT: // The SHIFT key is pressed.
216 break;
217 }
218 #endif
219 info.pt.x = nmitem->ptAction.x;
220 info.pt.y = nmitem->ptAction.y;
221 if (ListView_HitTest(hWnd, &info) != -1) {
222 LVITEM item;
223 item.mask = LVIF_PARAM;
224 item.iItem = info.iItem;
225 if (ListView_GetItem(hWnd, &item)) {
226 }
227 }
228 }
229 break;
230
231 case NM_RCLICK:
232 {
233 int idx;
234 LV_HITTESTINFO lvH;
235 NM_LISTVIEW* pNm = (NM_LISTVIEW*)lParam;
236 lvH.pt.x = pNm->ptAction.x;
237 lvH.pt.y = pNm->ptAction.y;
238 idx = ListView_HitTest(hWnd, &lvH);
239 if (idx != -1) {
240 POINT pt;
241 GetCursorPos(&pt);
242 ListViewPopUpMenu(hWnd, pt);
243 return idx;
244 }
245 }
246 break;
247
248 default:
249 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
250 }
251 break;
252 case WM_KEYDOWN:
253 if (wParam == VK_TAB) {
254 //TODO: SetFocus(Globals.hDriveBar)
255 //SetFocus(child->nFocusPanel? child->left.hWnd: child->right.hWnd);
256 }
257 // fall thru...
258 default:
259 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
260 break;
261 }
262 return 0;
263 }
264
265
266 HWND CreateListView(HWND hwndParent, int id)
267 {
268 RECT rcClient;
269 HWND hwndLV;
270
271 // Get the dimensions of the parent window's client area, and create the list view control.
272 GetClientRect(hwndParent, &rcClient);
273 hwndLV = CreateWindowEx(0, WC_LISTVIEW, _T("List View"),
274 WS_VISIBLE | WS_CHILD | WS_EX_CLIENTEDGE | LVS_REPORT,
275 0, 0, rcClient.right, rcClient.bottom,
276 hwndParent, (HMENU)id, hInst, NULL);
277 ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
278
279 // Initialize the image list, and add items to the control.
280 /*
281 if (!InitListViewImageLists(hwndLV) ||
282 !InitListViewItems(hwndLV, szName)) {
283 DestroyWindow(hwndLV);
284 return FALSE;
285 }
286 */
287 CreateListColumns(hwndLV);
288 g_orgListWndProc = SubclassWindow(hwndLV, ListWndProc);
289 return hwndLV;
290 }
291
292 BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPTSTR keyPath)
293 {
294 if (hwndLV != NULL) {
295 ListView_DeleteAllItems(hwndLV);
296 }
297
298 if (hKey != NULL) {
299 LONG errCode;
300 HKEY hNewKey;
301
302
303 DWORD max_sub_key_len;
304 DWORD max_val_name_len;
305 DWORD max_val_size;
306 DWORD val_count;
307 errCode = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
308 &max_sub_key_len, NULL, &val_count, &max_val_name_len, &max_val_size, NULL, NULL);
309 if (errCode == ERROR_SUCCESS) {
310 TCHAR* ValName = malloc(++max_val_name_len * sizeof(TCHAR));
311 DWORD dwValNameLen = max_val_name_len;
312 BYTE* ValBuf = malloc(++max_val_size);
313 DWORD dwValSize = max_val_size;
314 DWORD dwIndex = 0L;
315 DWORD dwValType;
316 while (RegEnumValue(hKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) {
317 AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwIndex);
318 dwValNameLen = max_val_name_len;
319 dwValSize = max_val_size;
320 dwValType = 0L;
321 ++dwIndex;
322 }
323 free(ValBuf);
324 free(ValName);
325 }
326
327
328 errCode = RegOpenKeyEx(hKey, keyPath, 0, KEY_READ, &hNewKey);
329 if (errCode == ERROR_SUCCESS) {
330 DWORD max_sub_key_len;
331 DWORD max_val_name_len;
332 DWORD max_val_size;
333 DWORD val_count;
334 ShowWindow(hwndLV, SW_HIDE);
335 /* get size information and resize the buffers if necessary */
336 errCode = RegQueryInfoKey(hNewKey, NULL, NULL, NULL, NULL,
337 &max_sub_key_len, NULL, &val_count, &max_val_name_len, &max_val_size, NULL, NULL);
338 if (errCode == ERROR_SUCCESS) {
339 TCHAR* ValName = malloc(++max_val_name_len * sizeof(TCHAR));
340 DWORD dwValNameLen = max_val_name_len;
341 BYTE* ValBuf = malloc(++max_val_size);
342 DWORD dwValSize = max_val_size;
343 DWORD dwIndex = 0L;
344 DWORD dwValType;
345 while (RegEnumValue(hNewKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) {
346 //while (RegEnumValue(hNewKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, NULL, NULL) == ERROR_SUCCESS) {
347 AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwIndex);
348 dwValNameLen = max_val_name_len;
349 dwValSize = max_val_size;
350 dwValType = 0L;
351 ++dwIndex;
352 }
353 free(ValBuf);
354 free(ValName);
355 }
356 //ListView_SortItemsEx(hwndLV, CompareFunc, hwndLV);
357 // SendMessage(hwndLV, LVM_SORTITEMSEX, (WPARAM)CompareFunc, (LPARAM)hwndLV);
358 ShowWindow(hwndLV, SW_SHOW);
359 RegCloseKey(hNewKey);
360 }
361 }
362 return TRUE;
363 }
364