Updated treeview and listview functionality.
[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 <assert.h>
39 #define ASSERT assert
40 #include "main.h"
41 #include "listview.h"
42
43 #include "trace.h"
44
45
46 ////////////////////////////////////////////////////////////////////////////////
47 // Global Variables:
48 //
49
50 static WNDPROC g_orgListWndProc;
51
52
53 ////////////////////////////////////////////////////////////////////////////////
54 // Local module support methods
55 //
56
57 static void AddEntryToList(HWND hwndLV, int idx, Entry* entry)
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 = entry->data.cFileName;
67 item.pszText = LPSTR_TEXTCALLBACK;
68 // item.cchTextMax = strlen(entry->data.cFileName);
69 item.cchTextMax = 0;
70 item.iImage = 0;
71 // item.iImage = I_IMAGECALLBACK;
72 item.lParam = (LPARAM)entry;
73 #if (_WIN32_IE >= 0x0300)
74 item.iIndent = 0;
75 #endif
76 ListView_InsertItem(hwndLV, &item);
77 }
78
79 // insert listctrl entries after index idx
80 static void InsertListEntries(HWND hWnd, Entry* entry, int idx)
81 {
82 ShowWindow(hWnd, SW_HIDE);
83
84 if (idx == -1) {
85 }
86 idx = 0;
87
88 for (; entry; entry = entry->next) {
89 #ifndef _LEFT_FILES
90 // if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
91 // continue;
92 #endif
93 //ListBox_InsertItemData(hWnd, idx, entry);
94 AddEntryToList(hWnd, idx, entry);
95 ++idx;
96 }
97 ShowWindow(hWnd, SW_SHOW);
98 }
99
100 #define MAX_LIST_COLUMNS (IDS_LIST_COLUMN_LAST - IDS_LIST_COLUMN_FIRST + 1)
101 static int default_column_widths[MAX_LIST_COLUMNS] = { 200, 175, 400 };
102 static int column_alignment[MAX_LIST_COLUMNS] = { LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT };
103
104 static void CreateListColumns(HWND hWndListView)
105 {
106 TCHAR szText[50];
107 int index;
108 LV_COLUMN lvC;
109
110 // Create columns.
111 lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
112 lvC.pszText = szText;
113
114 // Load the column labels from the resource file.
115 for (index = 0; index < MAX_LIST_COLUMNS; index++) {
116 lvC.iSubItem = index;
117 lvC.cx = default_column_widths[index];
118 lvC.fmt = column_alignment[index];
119 LoadString(hInst, IDS_LIST_COLUMN_FIRST + index, szText, sizeof(szText));
120 if (ListView_InsertColumn(hWndListView, index, &lvC) == -1) {
121 // TODO: handle failure condition...
122 break;
123 }
124 }
125 }
126
127
128 // OnGetDispInfo - processes the LVN_GETDISPINFO
129 // notification message.
130
131 static void OnGetDispInfo(NMLVDISPINFO* plvdi)
132 {
133 static TCHAR buffer[200];
134
135 // FILETIME LastWriteTime;
136 // TCHAR Class[MAX_NAME_LEN];
137 // DWORD cClass = MAX_NAME_LEN;
138 // TCHAR Name[MAX_NAME_LEN];
139 // DWORD cName = MAX_NAME_LEN;
140 // DWORD dwIndex = 0L;
141
142 Entry* pEntry = (Entry*)plvdi->item.lParam;
143 ASSERT(pEntry);
144
145 plvdi->item.pszText = NULL;
146 plvdi->item.cchTextMax = 0;
147
148 switch (plvdi->item.iSubItem) {
149 case 0:
150 /*
151 plvdi->item.pszText = _T("(Default)");
152 plvdi->item.cchTextMax = _tcslen(plvdi->item.pszText);
153 if (pEntry->bKey == TRUE) {
154 DWORD nSubKeys;
155 DWORD MaxSubKeyLen;
156 DWORD MaxClassLen;
157 DWORD ValueCount;
158 DWORD MaxValueNameLen;
159 DWORD MaxValueLen;
160 DWORD SecurityDescriptorLen;
161
162 HKEY hKey = pEntry->hKey;
163 LONG result = RegQueryInfoKey(pEntry->hKey, Class, &cClass, 0,
164 &nSubKeys, &MaxSubKeyLen, &MaxClassLen, &ValueCount,
165 &MaxValueNameLen, &MaxValueLen, &SecurityDescriptorLen,
166 &LastWriteTime);
167 if (result == ERROR_SUCCESS) {
168 plvdi->item.pszText = Class;
169 plvdi->item.cchTextMax = cClass;
170 }
171 }
172 */
173 plvdi->item.pszText = pEntry->szName;
174 plvdi->item.cchTextMax = lstrlen(pEntry->szName);
175
176 break;
177 case 1:
178 plvdi->item.pszText = _T("REG_SZ");
179 break;
180 case 2:
181 plvdi->item.pszText = _T("(value not set)");
182 break;
183 case 3:
184 plvdi->item.pszText = _T("");
185 break;
186 default:
187 // _tcscpy(buffer, _T(" "));
188 // plvdi->item.pszText = buffer;
189 break;
190 }
191 }
192 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
193 {
194 switch (LOWORD(wParam)) {
195 // case ID_FILE_OPEN:
196 // break;
197 default:
198 return FALSE;
199 }
200 return TRUE;
201 }
202 ////////////////////////////////////////////////////////////////////////////////
203 void ListViewPopUpMenu(HWND hWnd, POINT pt)
204 {
205 }
206
207 static LRESULT CALLBACK ListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
208 {
209 // ChildWnd* child = (ChildWnd*)GetWindowLong(GetParent(hWnd), GWL_USERDATA);
210 // Pane* pane = (Pane*)GetWindowLong(hWnd, GWL_USERDATA);
211 // ASSERT(child);
212
213 switch (message) {
214 /*
215 case WM_CREATE:
216 //CreateListView(hWnd);
217 return 0;
218 */
219 case WM_COMMAND:
220 if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
221 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
222 }
223 break;
224 case WM_NOTIFY:
225 switch (((LPNMHDR)lParam)->code) {
226 case LVN_GETDISPINFO:
227 OnGetDispInfo((NMLVDISPINFO*)lParam);
228 break;
229 case NM_DBLCLK:
230 {
231 NMITEMACTIVATE* nmitem = (LPNMITEMACTIVATE)lParam;
232 LVHITTESTINFO info;
233
234 if (nmitem->hdr.hwndFrom != hWnd) break;
235 // if (nmitem->hdr.idFrom != IDW_LISTVIEW) break;
236 // if (nmitem->hdr.code != ???) break;
237 #ifdef _MSC_VER
238 switch (nmitem->uKeyFlags) {
239 case LVKF_ALT: // The ALT key is pressed.
240 // properties dialog box ?
241 break;
242 case LVKF_CONTROL: // The CTRL key is pressed.
243 // run dialog box for providing parameters...
244 break;
245 case LVKF_SHIFT: // The SHIFT key is pressed.
246 break;
247 }
248 #endif
249 info.pt.x = nmitem->ptAction.x;
250 info.pt.y = nmitem->ptAction.y;
251 if (ListView_HitTest(hWnd, &info) != -1) {
252 LVITEM item;
253 item.mask = LVIF_PARAM;
254 item.iItem = info.iItem;
255 if (ListView_GetItem(hWnd, &item)) {
256 // Entry* entry = (Entry*)item.lParam;
257 // OpenTarget(hWnd, entry->data.cFileName);
258 }
259 }
260 }
261 break;
262
263 case NM_RCLICK:
264 {
265 int idx;
266 LV_HITTESTINFO lvH;
267 NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
268 lvH.pt.x = pNm->ptAction.x;
269 lvH.pt.y = pNm->ptAction.y;
270 idx = ListView_HitTest(hWnd, &lvH);
271 if (idx != -1) {
272 POINT pt;
273 GetCursorPos(&pt);
274 ListViewPopUpMenu(hWnd, pt);
275 return idx;
276 }
277 }
278 break;
279
280 default:
281 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
282 }
283 break;
284 case WM_KEYDOWN:
285 if (wParam == VK_TAB) {
286 //TODO: SetFocus(Globals.hDriveBar)
287 //SetFocus(child->nFocusPanel? child->left.hWnd: child->right.hWnd);
288 }
289 break;
290 default:
291 return CallWindowProc(g_orgListWndProc, hWnd, message, wParam, lParam);
292 break;
293 }
294 return 0;
295 }
296
297
298 HWND CreateListView(HWND hwndParent/*, Pane* pane*/, int id, Root* pRoot/*Entry* pEntry*/)
299 {
300 RECT rcClient; // dimensions of client area
301 HWND hwndLV; // handle to list view control
302 // Entry* entry = pane->root;
303 // pane->treePane = 0;
304
305 // Get the dimensions of the parent window's client area, and create the list view control.
306 GetClientRect(hwndParent, &rcClient);
307 hwndLV = CreateWindowEx(0, WC_LISTVIEW, _T("List View"),
308 WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT,
309 0, 0, rcClient.right, rcClient.bottom,
310 hwndParent, (HMENU)id, hInst, NULL);
311
312 // Initialize the image list, and add items to the control.
313 /*
314 if (!InitListViewImageLists(hwndLV) ||
315 !InitListViewItems(hwndLV, lpszPathName)) {
316 DestroyWindow(hwndLV);
317 return FALSE;
318 }
319 */
320 ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
321 CreateListColumns(hwndLV);
322
323 SetWindowLong(hwndLV, GWL_USERDATA, (LPARAM)pRoot);
324 g_orgListWndProc = SubclassWindow(hwndLV, ListWndProc);
325 //SendMessage(hwndLV, WM_SETFONT, (WPARAM)Globals.hFont, FALSE);
326
327 // insert entries into listbox
328 // if (entry) {
329 // InsertListEntries(hwndLV, entry, -1);
330 // }
331
332 return hwndLV;
333 }
334
335 void RefreshList(HWND hWnd, Entry* entry)
336 {
337 if (hWnd != NULL) {
338 ListView_DeleteAllItems(hWnd);
339 if (entry != NULL) {
340 TRACE("RefreshList(...) entry name: %p\n", entry);
341 InsertListEntries(hWnd, entry, -1);
342 }
343 }
344 }
345