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