aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/UI/FileManager/SystemPage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/UI/FileManager/SystemPage.cpp')
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.cpp464
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
22using namespace NWindows;
23
24#ifndef _UNICODE
25extern bool g_IsNT;
26#endif
27
28static const UInt32 kLangIDs[] =
29{
30 IDT_SYSTEM_ASSOCIATE
31};
32
33#define kSystemTopic "FM/options.htm#system"
34
35CSysString 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
50int 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
81void 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
94void 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
150bool 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
261static UString GetProgramCommand()
262{
263 UString s ('\"');
264 s += fs2us(NDLL::GetModuleDirPrefix());
265 s += "7zFM.exe\" \"%1\"";
266 return s;
267}
268
269
270LONG 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
331void CSystemPage::OnNotifyHelp()
332{
333 ShowHelpWindow(kSystemTopic);
334}
335
336
337bool 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
355bool 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
411void 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
427bool 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}