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