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