c1a7e24de2b37607d573826c4f6fc7ffeeb32229
[reactos.git] / rosapps / regedt32 / 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 #define LVM_GETITEMTEXTA (LVM_FIRST + 45)
43 #define LVM_GETITEMTEXTW (LVM_FIRST + 115)
44
45 #ifdef UNICODE
46 #define LVM_GETITEMTEXT LVM_GETITEMTEXTW
47 #else
48 #define LVM_GETITEMTEXT LVM_GETITEMTEXTA
49 #endif
50
51 #define ListView_GetItemText(hwndLV, i, iSubItem_, pszText_, cchTextMax_) \
52 { LV_ITEM _ms_lvi;\
53 _ms_lvi.iSubItem = iSubItem_;\
54 _ms_lvi.cchTextMax = cchTextMax_;\
55 _ms_lvi.pszText = pszText_;\
56 SNDMSG((hwndLV), LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)(LV_ITEM FAR *)&_ms_lvi);\
57 }
58
59 ////////////////////////////////////////////////////////////////////////////////
60 // Global and Local Variables:
61 //
62
63 static WNDPROC g_orgListWndProc;
64
65 #define MAX_LIST_COLUMNS (IDS_LIST_COLUMN_LAST - IDS_LIST_COLUMN_FIRST + 1)
66 static int default_column_widths[MAX_LIST_COLUMNS] = { 200, 175, 400 };
67 static int column_alignment[MAX_LIST_COLUMNS] = { LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT };
68
69
70 ////////////////////////////////////////////////////////////////////////////////
71 // Local module support methods
72 //
73
74 static void AddEntryToList(HWND hwndLV, LPTSTR Name, DWORD dwValType, void* ValBuf, DWORD dwCount)
75 {
76 LVITEM item;
77
78 item.mask = LVIF_TEXT | LVIF_PARAM;
79 item.iItem = 0;//idx;
80 item.iSubItem = 0;
81 item.state = 0;
82 item.stateMask = 0;
83 item.pszText = Name;
84 item.cchTextMax = _tcslen(item.pszText);
85 item.iImage = 0;
86 item.lParam = (LPARAM)dwValType;
87 // item.lParam = (LPARAM)ValBuf;
88 #if (_WIN32_IE >= 0x0300)
89 item.iIndent = 0;
90 #endif
91 ListView_InsertItem(hwndLV, &item);
92 }
93
94 static void CreateListColumns(HWND hWndListView)
95 {
96 TCHAR szText[50];
97 int index;
98 LV_COLUMN lvC;
99
100 // Create columns.
101 lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
102 lvC.pszText = szText;
103
104 // Load the column labels from the resource file.
105 for (index = 0; index < MAX_LIST_COLUMNS; index++) {
106 lvC.iSubItem = index;
107 lvC.cx = default_column_widths[index];
108 lvC.fmt = column_alignment[index];
109 LoadString(hInst, IDS_LIST_COLUMN_FIRST + index, szText, sizeof(szText)/sizeof(TCHAR));
110 if (ListView_InsertColumn(hWndListView, index, &lvC) == -1) {
111 // TODO: handle failure condition...
112 break;
113 }
114 }
115 }
116
117 // OnGetDispInfo - processes the LVN_GETDISPINFO notification message.
118
119 static void OnGetDispInfo(NMLVDISPINFO* plvdi)
120 {
121 static TCHAR buffer[200];
122
123 plvdi->item.pszText = NULL;
124 plvdi->item.cchTextMax = 0;
125
126 switch (plvdi->item.iSubItem) {
127 case 0:
128 plvdi->item.pszText = _T("(Default)");
129 break;
130 case 1:
131 switch (plvdi->item.lParam) {
132 case REG_SZ:
133 plvdi->item.pszText = _T("REG_SZ");
134 break;
135 case REG_EXPAND_SZ:
136 plvdi->item.pszText = _T("REG_EXPAND_SZ");
137 break;
138 case REG_BINARY:
139 plvdi->item.pszText = _T("REG_BINARY");
140 break;
141 case REG_DWORD:
142 plvdi->item.pszText = _T("REG_DWORD");
143 break;
144 // case REG_DWORD_LITTLE_ENDIAN:
145 // plvdi->item.pszText = _T("REG_DWORD_LITTLE_ENDIAN");
146 // break;
147 case REG_DWORD_BIG_ENDIAN:
148 plvdi->item.pszText = _T("REG_DWORD_BIG_ENDIAN");
149 break;
150 case REG_MULTI_SZ:
151 plvdi->item.pszText = _T("REG_MULTI_SZ");
152 break;
153 case REG_LINK:
154 plvdi->item.pszText = _T("REG_LINK");
155 break;
156 case REG_RESOURCE_LIST:
157 plvdi->item.pszText = _T("REG_RESOURCE_LIST");
158 break;
159 case REG_NONE:
160 plvdi->item.pszText = _T("REG_NONE");
161 break;
162 default:
163 wsprintf(buffer, _T("unknown(%d)"), plvdi->item.lParam);
164 plvdi->item.pszText = buffer;
165 break;
166 }
167 break;
168 case 2:
169 plvdi->item.pszText = _T("(value not set)");
170 break;
171 case 3:
172 plvdi->item.pszText = _T("");
173 break;
174 }
175 }
176
177 static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
178 {
179 TCHAR buf1[1000];
180 TCHAR buf2[1000];
181
182 ListView_GetItemText((HWND)lParamSort, lParam1, 0, buf1, sizeof(buf1));
183 ListView_GetItemText((HWND)lParamSort, lParam2, 0, buf2, sizeof(buf2));
184 return _tcscmp(buf1, buf2);
185 }
186
187 static void ListViewPopUpMenu(HWND hWnd, POINT pt)
188 {
189 }
190
191 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
192 {
193 switch (LOWORD(wParam)) {
194 // case ID_FILE_OPEN:
195 // break;
196 default:
197 return FALSE;
198 }
199 return TRUE;
200 }
201
202 static LRESULT CALLBACK ListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
203 {
204 switch (message) {
205 case WM_COMMAND:
206 if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
207 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
208 }
209 break;
210 case WM_NOTIFY:
211 switch (((LPNMHDR)lParam)->code) {
212 case LVN_GETDISPINFO:
213 OnGetDispInfo((NMLVDISPINFO*)lParam);
214 break;
215 case NM_DBLCLK:
216 {
217 NMITEMACTIVATE* nmitem = (LPNMITEMACTIVATE)lParam;
218 LVHITTESTINFO info;
219
220 if (nmitem->hdr.hwndFrom != hWnd) break;
221 // if (nmitem->hdr.idFrom != IDW_LISTVIEW) break;
222 // if (nmitem->hdr.code != ???) break;
223 #ifdef _MSC_VER
224 switch (nmitem->uKeyFlags) {
225 case LVKF_ALT: // The ALT key is pressed.
226 // properties dialog box ?
227 break;
228 case LVKF_CONTROL: // The CTRL key is pressed.
229 // run dialog box for providing parameters...
230 break;
231 case LVKF_SHIFT: // The SHIFT key is pressed.
232 break;
233 }
234 #endif
235 info.pt.x = nmitem->ptAction.x;
236 info.pt.y = nmitem->ptAction.y;
237 if (ListView_HitTest(hWnd, &info) != -1) {
238 LVITEM item;
239 item.mask = LVIF_PARAM;
240 item.iItem = info.iItem;
241 if (ListView_GetItem(hWnd, &item)) {
242 }
243 }
244 }
245 break;
246
247 case NM_RCLICK:
248 {
249 int idx;
250 LV_HITTESTINFO lvH;
251 NM_LISTVIEW* pNm = (NM_LISTVIEW*)lParam;
252 lvH.pt.x = pNm->ptAction.x;
253 lvH.pt.y = pNm->ptAction.y;
254 idx = ListView_HitTest(hWnd, &lvH);
255 if (idx != -1) {
256 POINT pt;
257 GetCursorPos(&pt);
258 ListViewPopUpMenu(hWnd, pt);
259 return idx;
260 }
261 }
262 break;
263
264 default:
265 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
266 }
267 break;
268 case WM_KEYDOWN:
269 if (wParam == VK_TAB) {
270 //TODO: SetFocus(Globals.hDriveBar)
271 //SetFocus(child->nFocusPanel? child->left.hWnd: child->right.hWnd);
272 }
273 // fall thru...
274 default:
275 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
276 break;
277 }
278 return 0;
279 }
280
281
282 HWND CreateListView(HWND hwndParent)
283 {
284 RECT rcClient;
285 HWND hwndLV;
286
287 // Get the dimensions of the parent window's client area, and create the list view control.
288 GetClientRect(hwndParent, &rcClient);
289 hwndLV = CreateWindowEx(0, WC_LISTVIEW, _T("List View"),
290 WS_VISIBLE | WS_CHILD | WS_EX_CLIENTEDGE | LVS_REPORT,
291 0, 0, rcClient.right, rcClient.bottom,
292 hwndParent, (HMENU)LIST_WINDOW, hInst, NULL);
293 ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
294
295 // Initialize the image list, and add items to the control.
296 /*
297 if (!InitListViewImageLists(hwndLV) ||
298 !InitListViewItems(hwndLV, szName)) {
299 DestroyWindow(hwndLV);
300 return FALSE;
301 }
302 */
303 CreateListColumns(hwndLV);
304 g_orgListWndProc = SubclassWindow(hwndLV, ListWndProc);
305 return hwndLV;
306 }
307
308 BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPTSTR keyPath)
309 {
310 if (hwndLV != NULL) {
311 ListView_DeleteAllItems(hwndLV);
312 }
313
314 if (hKey != NULL) {
315 LONG errCode;
316 HKEY hNewKey;
317
318
319 DWORD max_sub_key_len;
320 DWORD max_val_name_len;
321 DWORD max_val_size;
322 DWORD val_count;
323 errCode = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
324 &max_sub_key_len, NULL, &val_count, &max_val_name_len, &max_val_size, NULL, NULL);
325 if (errCode == ERROR_SUCCESS) {
326 TCHAR* ValName = malloc(++max_val_name_len * sizeof(TCHAR));
327 DWORD dwValNameLen = max_val_name_len;
328 BYTE* ValBuf = malloc(++max_val_size);
329 DWORD dwValSize = max_val_size;
330 DWORD dwIndex = 0L;
331 DWORD dwValType;
332 while (RegEnumValue(hKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) {
333 AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwIndex);
334 dwValNameLen = max_val_name_len;
335 dwValSize = max_val_size;
336 dwValType = 0L;
337 ++dwIndex;
338 }
339 free(ValBuf);
340 free(ValName);
341 }
342
343
344 errCode = RegOpenKeyEx(hKey, keyPath, 0, KEY_READ, &hNewKey);
345 if (errCode == ERROR_SUCCESS) {
346 DWORD max_sub_key_len;
347 DWORD max_val_name_len;
348 DWORD max_val_size;
349 DWORD val_count;
350 ShowWindow(hwndLV, SW_HIDE);
351 /* get size information and resize the buffers if necessary */
352 errCode = RegQueryInfoKey(hNewKey, NULL, NULL, NULL, NULL,
353 &max_sub_key_len, NULL, &val_count, &max_val_name_len, &max_val_size, NULL, NULL);
354 if (errCode == ERROR_SUCCESS) {
355 TCHAR* ValName = malloc(++max_val_name_len * sizeof(TCHAR));
356 DWORD dwValNameLen = max_val_name_len;
357 BYTE* ValBuf = malloc(++max_val_size);
358 DWORD dwValSize = max_val_size;
359 DWORD dwIndex = 0L;
360 DWORD dwValType;
361 while (RegEnumValue(hNewKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) {
362 //while (RegEnumValue(hNewKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, NULL, NULL) == ERROR_SUCCESS) {
363 AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwIndex);
364 dwValNameLen = max_val_name_len;
365 dwValSize = max_val_size;
366 dwValType = 0L;
367 ++dwIndex;
368 }
369 free(ValBuf);
370 free(ValName);
371 }
372 //ListView_SortItemsEx(hwndLV, CompareFunc, hwndLV);
373 // SendMessage(hwndLV, LVM_SORTITEMSEX, (WPARAM)CompareFunc, (LPARAM)hwndLV);
374 ShowWindow(hwndLV, SW_SHOW);
375 RegCloseKey(hNewKey);
376 }
377 }
378 return TRUE;
379 }
380