diff options
Diffstat (limited to 'CPP/7zip/UI/FileManager/SystemPage.cpp')
-rw-r--r-- | CPP/7zip/UI/FileManager/SystemPage.cpp | 464 |
1 files changed, 464 insertions, 0 deletions
diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp new file mode 100644 index 0000000..a95999f --- /dev/null +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp | |||
@@ -0,0 +1,464 @@ | |||
1 | // SystemPage.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | #include "../../../Common/MyWindows.h" | ||
6 | |||
7 | #include <ShlObj.h> | ||
8 | |||
9 | #include "../../../Common/Defs.h" | ||
10 | #include "../../../Common/StringConvert.h" | ||
11 | |||
12 | #include "../../../Windows/DLL.h" | ||
13 | #include "../../../Windows/ErrorMsg.h" | ||
14 | |||
15 | #include "HelpUtils.h" | ||
16 | #include "IFolder.h" | ||
17 | #include "LangUtils.h" | ||
18 | #include "PropertyNameRes.h" | ||
19 | #include "SystemPage.h" | ||
20 | #include "SystemPageRes.h" | ||
21 | |||
22 | using namespace NWindows; | ||
23 | |||
24 | #ifndef _UNICODE | ||
25 | extern bool g_IsNT; | ||
26 | #endif | ||
27 | |||
28 | static const UInt32 kLangIDs[] = | ||
29 | { | ||
30 | IDT_SYSTEM_ASSOCIATE | ||
31 | }; | ||
32 | |||
33 | #define kSystemTopic "FM/options.htm#system" | ||
34 | |||
35 | CSysString CModifiedExtInfo::GetString() const | ||
36 | { | ||
37 | const char *s; | ||
38 | if (State == kExtState_7Zip) | ||
39 | s = "7-Zip"; | ||
40 | else if (State == kExtState_Clear) | ||
41 | s = ""; | ||
42 | else if (Other7Zip) | ||
43 | s = "[7-Zip]"; | ||
44 | else | ||
45 | return ProgramKey; | ||
46 | return CSysString (s); | ||
47 | }; | ||
48 | |||
49 | |||
50 | int CSystemPage::AddIcon(const UString &iconPath, int iconIndex) | ||
51 | { | ||
52 | if (iconPath.IsEmpty()) | ||
53 | return -1; | ||
54 | if (iconIndex == -1) | ||
55 | iconIndex = 0; | ||
56 | |||
57 | HICON hicon; | ||
58 | |||
59 | #ifdef UNDER_CE | ||
60 | ExtractIconExW(iconPath, iconIndex, NULL, &hicon, 1); | ||
61 | if (!hicon) | ||
62 | #else | ||
63 | // we expand path from REG_EXPAND_SZ registry item. | ||
64 | UString path; | ||
65 | DWORD size = MAX_PATH + 10; | ||
66 | DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuf(size + 2), size); | ||
67 | path.ReleaseBuf_CalcLen(size); | ||
68 | if (needLen == 0 || needLen >= size) | ||
69 | path = iconPath; | ||
70 | int num = ExtractIconExW(path, iconIndex, NULL, &hicon, 1); | ||
71 | if (num != 1 || !hicon) | ||
72 | #endif | ||
73 | return -1; | ||
74 | |||
75 | _imageList.AddIcon(hicon); | ||
76 | DestroyIcon(hicon); | ||
77 | return _numIcons++; | ||
78 | } | ||
79 | |||
80 | |||
81 | void CSystemPage::RefreshListItem(unsigned group, unsigned listIndex) | ||
82 | { | ||
83 | const CAssoc &assoc = _items[GetRealIndex(listIndex)]; | ||
84 | _listView.SetSubItem(listIndex, group + 1, assoc.Pair[group].GetString()); | ||
85 | LVITEMW newItem; | ||
86 | memset(&newItem, 0, sizeof(newItem)); | ||
87 | newItem.iItem = listIndex; | ||
88 | newItem.mask = LVIF_IMAGE; | ||
89 | newItem.iImage = assoc.GetIconIndex(); | ||
90 | _listView.SetItem(&newItem); | ||
91 | } | ||
92 | |||
93 | |||
94 | void CSystemPage::ChangeState(unsigned group, const CUIntVector &indices) | ||
95 | { | ||
96 | if (indices.IsEmpty()) | ||
97 | return; | ||
98 | |||
99 | bool thereAreClearItems = false; | ||
100 | unsigned counters[3] = { 0, 0, 0 }; | ||
101 | |||
102 | unsigned i; | ||
103 | for (i = 0; i < indices.Size(); i++) | ||
104 | { | ||
105 | const CModifiedExtInfo &mi = _items[GetRealIndex(indices[i])].Pair[group]; | ||
106 | int state = kExtState_7Zip; | ||
107 | if (mi.State == kExtState_7Zip) | ||
108 | state = kExtState_Clear; | ||
109 | else if (mi.State == kExtState_Clear) | ||
110 | { | ||
111 | thereAreClearItems = true; | ||
112 | if (mi.Other) | ||
113 | state = kExtState_Other; | ||
114 | } | ||
115 | counters[state]++; | ||
116 | } | ||
117 | |||
118 | int state = kExtState_Clear; | ||
119 | if (counters[kExtState_Other] != 0) | ||
120 | state = kExtState_Other; | ||
121 | else if (counters[kExtState_7Zip] != 0) | ||
122 | state = kExtState_7Zip; | ||
123 | |||
124 | for (i = 0; i < indices.Size(); i++) | ||
125 | { | ||
126 | unsigned listIndex = indices[i]; | ||
127 | CAssoc &assoc = _items[GetRealIndex(listIndex)]; | ||
128 | CModifiedExtInfo &mi = assoc.Pair[group]; | ||
129 | bool change = false; | ||
130 | |||
131 | switch (state) | ||
132 | { | ||
133 | case kExtState_Clear: change = true; break; | ||
134 | case kExtState_Other: change = mi.Other; break; | ||
135 | default: change = !(mi.Other && thereAreClearItems); break; | ||
136 | } | ||
137 | |||
138 | if (change) | ||
139 | { | ||
140 | mi.State = state; | ||
141 | RefreshListItem(group, listIndex); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | _needSave = true; | ||
146 | Changed(); | ||
147 | } | ||
148 | |||
149 | |||
150 | bool CSystemPage::OnInit() | ||
151 | { | ||
152 | _needSave = false; | ||
153 | |||
154 | LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); | ||
155 | |||
156 | _listView.Attach(GetItem(IDL_SYSTEM_ASSOCIATE)); | ||
157 | _listView.SetUnicodeFormat(); | ||
158 | DWORD newFlags = LVS_EX_FULLROWSELECT; | ||
159 | _listView.SetExtendedListViewStyle(newFlags, newFlags); | ||
160 | |||
161 | _numIcons = 0; | ||
162 | _imageList.Create(16, 16, ILC_MASK | ILC_COLOR32, 0, 0); | ||
163 | |||
164 | _listView.SetImageList(_imageList, LVSIL_SMALL); | ||
165 | |||
166 | _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 72); | ||
167 | |||
168 | UString s; | ||
169 | |||
170 | #if NUM_EXT_GROUPS == 1 | ||
171 | s = "Program"; | ||
172 | #else | ||
173 | #ifndef UNDER_CE | ||
174 | const unsigned kSize = 256; | ||
175 | BOOL res; | ||
176 | |||
177 | DWORD size = kSize; | ||
178 | |||
179 | #ifndef _UNICODE | ||
180 | if (!g_IsNT) | ||
181 | { | ||
182 | AString s2; | ||
183 | res = GetUserNameA(s2.GetBuf(size), &size); | ||
184 | s2.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize)); | ||
185 | s = GetUnicodeString(s2); | ||
186 | } | ||
187 | else | ||
188 | #endif | ||
189 | { | ||
190 | res = GetUserNameW(s.GetBuf(size), &size); | ||
191 | s.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize)); | ||
192 | } | ||
193 | |||
194 | if (!res) | ||
195 | #endif | ||
196 | s = "Current User"; | ||
197 | #endif | ||
198 | |||
199 | LV_COLUMNW ci; | ||
200 | ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM; | ||
201 | ci.cx = 128; | ||
202 | ci.fmt = LVCFMT_CENTER; | ||
203 | ci.pszText = s.Ptr_non_const(); | ||
204 | ci.iSubItem = 1; | ||
205 | _listView.InsertColumn(1, &ci); | ||
206 | |||
207 | #if NUM_EXT_GROUPS > 1 | ||
208 | { | ||
209 | LangString(IDS_SYSTEM_ALL_USERS, s); | ||
210 | ci.pszText = s.Ptr_non_const(); | ||
211 | ci.iSubItem = 2; | ||
212 | _listView.InsertColumn(2, &ci); | ||
213 | } | ||
214 | #endif | ||
215 | |||
216 | _extDB.Read(); | ||
217 | _items.Clear(); | ||
218 | |||
219 | FOR_VECTOR (i, _extDB.Exts) | ||
220 | { | ||
221 | const CExtPlugins &extInfo = _extDB.Exts[i]; | ||
222 | |||
223 | LVITEMW item; | ||
224 | item.iItem = i; | ||
225 | item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; | ||
226 | item.lParam = i; | ||
227 | item.iSubItem = 0; | ||
228 | // ListView always uses internal iImage that is 0 by default? | ||
229 | // so we always use LVIF_IMAGE. | ||
230 | item.iImage = -1; | ||
231 | item.pszText = extInfo.Ext.Ptr_non_const(); | ||
232 | |||
233 | CAssoc assoc; | ||
234 | const CPluginToIcon &plug = extInfo.Plugins[0]; | ||
235 | assoc.SevenZipImageIndex = AddIcon(plug.IconPath, plug.IconIndex); | ||
236 | |||
237 | CSysString texts[NUM_EXT_GROUPS]; | ||
238 | unsigned g; | ||
239 | for (g = 0; g < NUM_EXT_GROUPS; g++) | ||
240 | { | ||
241 | CModifiedExtInfo &mi = assoc.Pair[g]; | ||
242 | mi.ReadFromRegistry(GetHKey(g), GetSystemString(extInfo.Ext)); | ||
243 | mi.SetState(plug.IconPath); | ||
244 | mi.ImageIndex = AddIcon(mi.IconPath, mi.IconIndex); | ||
245 | texts[g] = mi.GetString(); | ||
246 | } | ||
247 | item.iImage = assoc.GetIconIndex(); | ||
248 | int itemIndex = _listView.InsertItem(&item); | ||
249 | for (g = 0; g < NUM_EXT_GROUPS; g++) | ||
250 | _listView.SetSubItem(itemIndex, 1 + g, texts[g]); | ||
251 | _items.Add(assoc); | ||
252 | } | ||
253 | |||
254 | if (_listView.GetItemCount() > 0) | ||
255 | _listView.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED); | ||
256 | |||
257 | return CPropertyPage::OnInit(); | ||
258 | } | ||
259 | |||
260 | |||
261 | static UString GetProgramCommand() | ||
262 | { | ||
263 | UString s ('\"'); | ||
264 | s += fs2us(NDLL::GetModuleDirPrefix()); | ||
265 | s += "7zFM.exe\" \"%1\""; | ||
266 | return s; | ||
267 | } | ||
268 | |||
269 | |||
270 | LONG CSystemPage::OnApply() | ||
271 | { | ||
272 | if (!_needSave) | ||
273 | return PSNRET_NOERROR; | ||
274 | |||
275 | const UString command = GetProgramCommand(); | ||
276 | |||
277 | LONG res = 0; | ||
278 | |||
279 | FOR_VECTOR (listIndex, _extDB.Exts) | ||
280 | { | ||
281 | unsigned realIndex = GetRealIndex(listIndex); | ||
282 | const CExtPlugins &extInfo = _extDB.Exts[realIndex]; | ||
283 | CAssoc &assoc = _items[realIndex]; | ||
284 | |||
285 | for (unsigned g = 0; g < NUM_EXT_GROUPS; g++) | ||
286 | { | ||
287 | CModifiedExtInfo &mi = assoc.Pair[g]; | ||
288 | HKEY key = GetHKey(g); | ||
289 | |||
290 | if (mi.OldState != mi.State) | ||
291 | { | ||
292 | LONG res2 = 0; | ||
293 | |||
294 | if (mi.State == kExtState_7Zip) | ||
295 | { | ||
296 | UString title = extInfo.Ext; | ||
297 | title += " Archive"; | ||
298 | const CPluginToIcon &plug = extInfo.Plugins[0]; | ||
299 | res2 = NRegistryAssoc::AddShellExtensionInfo(key, GetSystemString(extInfo.Ext), | ||
300 | title, command, plug.IconPath, plug.IconIndex); | ||
301 | } | ||
302 | else if (mi.State == kExtState_Clear) | ||
303 | res2 = NRegistryAssoc::DeleteShellExtensionInfo(key, GetSystemString(extInfo.Ext)); | ||
304 | |||
305 | if (res == 0) | ||
306 | res = res2; | ||
307 | if (res2 == 0) | ||
308 | mi.OldState = mi.State; | ||
309 | |||
310 | mi.State = mi.OldState; | ||
311 | RefreshListItem(g, listIndex); | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | |||
316 | #ifndef UNDER_CE | ||
317 | SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | ||
318 | #endif | ||
319 | |||
320 | WasChanged = true; | ||
321 | |||
322 | _needSave = false; | ||
323 | |||
324 | if (res != 0) | ||
325 | MessageBoxW(*this, NError::MyFormatMessage(res), L"7-Zip", MB_ICONERROR); | ||
326 | |||
327 | return PSNRET_NOERROR; | ||
328 | } | ||
329 | |||
330 | |||
331 | void CSystemPage::OnNotifyHelp() | ||
332 | { | ||
333 | ShowHelpWindow(kSystemTopic); | ||
334 | } | ||
335 | |||
336 | |||
337 | bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND) | ||
338 | { | ||
339 | switch (buttonID) | ||
340 | { | ||
341 | /* | ||
342 | case IDC_SYSTEM_SELECT_ALL: | ||
343 | _listView.SelectAll(); | ||
344 | return true; | ||
345 | */ | ||
346 | case IDB_SYSTEM_CURRENT: | ||
347 | case IDB_SYSTEM_ALL: | ||
348 | ChangeState(buttonID == IDB_SYSTEM_CURRENT ? 0 : 1); | ||
349 | return true; | ||
350 | } | ||
351 | return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); | ||
352 | } | ||
353 | |||
354 | |||
355 | bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) | ||
356 | { | ||
357 | if (lParam->hwndFrom == HWND(_listView)) | ||
358 | { | ||
359 | switch (lParam->code) | ||
360 | { | ||
361 | case NM_RETURN: | ||
362 | { | ||
363 | ChangeState(0); | ||
364 | return true; | ||
365 | } | ||
366 | |||
367 | case NM_CLICK: | ||
368 | { | ||
369 | #ifdef UNDER_CE | ||
370 | NMLISTVIEW *item = (NMLISTVIEW *)lParam; | ||
371 | #else | ||
372 | NMITEMACTIVATE *item = (NMITEMACTIVATE *)lParam; | ||
373 | if (item->uKeyFlags == 0) | ||
374 | #endif | ||
375 | { | ||
376 | if (item->iItem >= 0) | ||
377 | { | ||
378 | // unsigned realIndex = GetRealIndex(item->iItem); | ||
379 | if (item->iSubItem >= 1 && item->iSubItem <= 2) | ||
380 | { | ||
381 | CUIntVector indices; | ||
382 | indices.Add(item->iItem); | ||
383 | ChangeState(item->iSubItem < 2 ? 0 : 1, indices); | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | break; | ||
388 | } | ||
389 | |||
390 | case LVN_KEYDOWN: | ||
391 | { | ||
392 | if (OnListKeyDown(LPNMLVKEYDOWN(lParam))) | ||
393 | return true; | ||
394 | break; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | case NM_RCLICK: | ||
399 | case NM_DBLCLK: | ||
400 | case LVN_BEGINRDRAG: | ||
401 | // PostMessage(kRefreshpluginsListMessage, 0); | ||
402 | PostMessage(kUpdateDatabase, 0); | ||
403 | break; | ||
404 | */ | ||
405 | } | ||
406 | } | ||
407 | return CPropertyPage::OnNotify(controlID, lParam); | ||
408 | } | ||
409 | |||
410 | |||
411 | void CSystemPage::ChangeState(unsigned group) | ||
412 | { | ||
413 | CUIntVector indices; | ||
414 | |||
415 | int itemIndex = -1; | ||
416 | while ((itemIndex = _listView.GetNextSelectedItem(itemIndex)) != -1) | ||
417 | indices.Add(itemIndex); | ||
418 | |||
419 | if (indices.IsEmpty()) | ||
420 | FOR_VECTOR (i, _items) | ||
421 | indices.Add(i); | ||
422 | |||
423 | ChangeState(group, indices); | ||
424 | } | ||
425 | |||
426 | |||
427 | bool CSystemPage::OnListKeyDown(LPNMLVKEYDOWN keyDownInfo) | ||
428 | { | ||
429 | bool ctrl = IsKeyDown(VK_CONTROL); | ||
430 | bool alt = IsKeyDown(VK_MENU); | ||
431 | |||
432 | if (alt) | ||
433 | return false; | ||
434 | |||
435 | if ((ctrl && keyDownInfo->wVKey == 'A') | ||
436 | || (!ctrl && keyDownInfo->wVKey == VK_MULTIPLY)) | ||
437 | { | ||
438 | _listView.SelectAll(); | ||
439 | return true; | ||
440 | } | ||
441 | |||
442 | switch (keyDownInfo->wVKey) | ||
443 | { | ||
444 | case VK_SPACE: | ||
445 | case VK_ADD: | ||
446 | case VK_SUBTRACT: | ||
447 | case VK_SEPARATOR: | ||
448 | case VK_DIVIDE: | ||
449 | |||
450 | #ifndef UNDER_CE | ||
451 | case VK_OEM_PLUS: | ||
452 | case VK_OEM_MINUS: | ||
453 | #endif | ||
454 | |||
455 | if (!ctrl) | ||
456 | { | ||
457 | ChangeState(keyDownInfo->wVKey == VK_SPACE ? 0 : 1); | ||
458 | return true; | ||
459 | } | ||
460 | break; | ||
461 | } | ||
462 | |||
463 | return false; | ||
464 | } | ||