xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/MyLoadMenu.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // MyLoadMenu.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../Windows/FileDir.h"
6 #include "../../../Windows/Menu.h"
7 #include "../../../Windows/TimeUtils.h"
8 #include "../../../Windows/Control/Dialog.h"
9 
10 #include "../../PropID.h"
11 
12 #include "../Common/CompressCall.h"
13 
14 #include "AboutDialog.h"
15 #include "App.h"
16 #include "BrowseDialog2.h"
17 #include "HelpUtils.h"
18 #include "LangUtils.h"
19 #include "MyLoadMenu.h"
20 #include "RegistryUtils.h"
21 
22 #include "PropertyNameRes.h"
23 #include "resource.h"
24 
25 using namespace NWindows;
26 
27 static const UINT k_MenuID_OpenBookmark = 830;
28 static const UINT k_MenuID_SetBookmark = 810;
29 static const UINT k_MenuID_TimePopup = IDM_VIEW_TIME_POPUP;
30 static const UINT k_MenuID_Time = IDM_VIEW_TIME;
31 
32 #if 0
33 // static const UINT k_MenuID_Bookmark_Temp = 850;
34 #endif
35 
36 extern HINSTANCE g_hInstance;
37 
38 #define kFMHelpTopic "FM/index.htm"
39 
40 extern void OptionsDialog(HWND hwndOwner, HINSTANCE hInstance);
41 
42 enum
43 {
44   k_MenuIndex_File = 0,
45   k_MenuIndex_Edit,
46   k_MenuIndex_View,
47   k_MenuIndex_Bookmarks
48 };
49 
50 #ifdef Z7_LANG
51 static const UInt32 k_LangID_TopMenuItems[] =
52 {
53   IDM_FILE,
54   IDM_EDIT,
55   IDM_VIEW,
56   IDM_FAVORITES,
57   IDM_TOOLS,
58   IDM_HELP
59 };
60 
61 static const UInt32 k_LangID_Toolbars = IDM_VIEW_TOOLBARS;
62 static const UInt32 k_LangID_AddToFavorites = IDM_ADD_TO_FAVORITES;
63 
64 static const CIDLangPair kIDLangPairs[] =
65 {
66   { IDCLOSE, 557 }, // IDM_EXIT
67   { IDM_VIEW_ARANGE_BY_NAME, IDS_PROP_NAME },
68   { IDM_VIEW_ARANGE_BY_TYPE, IDS_PROP_FILE_TYPE },
69   { IDM_VIEW_ARANGE_BY_DATE, IDS_PROP_MTIME },
70   { IDM_VIEW_ARANGE_BY_SIZE, IDS_PROP_SIZE }
71 };
72 
FindLangItem(unsigned controlID)73 static int FindLangItem(unsigned controlID)
74 {
75   for (unsigned i = 0; i < Z7_ARRAY_SIZE(kIDLangPairs); i++)
76     if (kIDLangPairs[i].ControlID == controlID)
77       return (int)i;
78   return -1;
79 }
80 #endif
81 
GetSortControlID(PROPID propID)82 static unsigned GetSortControlID(PROPID propID)
83 {
84   switch (propID)
85   {
86     case kpidName:       return IDM_VIEW_ARANGE_BY_NAME;
87     case kpidExtension:  return IDM_VIEW_ARANGE_BY_TYPE;
88     case kpidMTime:      return IDM_VIEW_ARANGE_BY_DATE;
89     case kpidSize:       return IDM_VIEW_ARANGE_BY_SIZE;
90     case kpidNoProperty: return IDM_VIEW_ARANGE_NO_SORT;
91   }
92   return IDM_VIEW_ARANGE_BY_NAME;
93   // IDM_VIEW_ARANGE_NO_SORT;
94   // return -1;
95 }
96 
97 /*
98 #if _MSC_VER > 1400
99 // GetVersion was declared deprecated
100 #pragma warning(disable : 4996)
101 #endif
102 
103 static bool g_IsNew_fMask = false;
104 static class CInit_fMask
105 {
106 public:
107   CInit_fMask()
108   {
109     DWORD v = GetVersion();
110     v = ((v & 0xff) << 8) | ((v >> 8) & 0xFF);
111     g_IsNew_fMask = (v > 0x400); // (win98/win2000) or newer
112   }
113 } g_Init_fMask;
114 static UINT Get_fMask_for_String()
115   { return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE; }
116 static UINT Get_fMask_for_FType_and_String()
117   { return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE; }
118 */
119 
120 /*
121 We can use new MIIM_STRING / MIIM_FTYPE flags in the following conditions:
122   1) we run at new Windows (win98/win2000) or newer
123   2) also we probably must set MENUITEMINFO::cbSize as sizeof of full
124      (MENUITEMINFO) that was compiled with (WINVER >= 0x0500)
125 But it's simpler to use old MIIM_TYPE without these complex checks.
126 */
127 
128 // /*
Get_fMask_for_String()129 static inline UINT Get_fMask_for_String() { return MIIM_TYPE; }
Get_fMask_for_FType_and_String()130 static inline UINT Get_fMask_for_FType_and_String() { return MIIM_TYPE; }
131 // */
132 
Is_MenuItem_TimePopup(const CMenuItem & item)133 static bool Is_MenuItem_TimePopup(const CMenuItem &item)
134 {
135   return item.wID == k_MenuID_TimePopup ||
136     item.StringValue.IsPrefixedBy_Ascii_NoCase("20");
137 }
138 
139 #ifdef Z7_LANG
MyChangeMenu(HMENU menuLoc,unsigned menuID,unsigned level,unsigned menuIndex)140 static void MyChangeMenu(HMENU menuLoc, unsigned menuID, unsigned level, unsigned menuIndex)
141 {
142   CMenu menu;
143   menu.Attach(menuLoc);
144 
145   for (unsigned i = 0;; i++)
146   {
147     CMenuItem item;
148     /* here we can use
149          Get_fMask_for_String() or
150          Get_fMask_for_FType_and_String()
151        We want to change only String of menu item.
152        It's not required to change (fType) of menu item.
153        We can look (fType) to check for SEPARATOR item.
154        But String of separator is empty and (wID == 0).
155        So we can check for SEPARATOR without (fType) requesting.
156        So it's enough to use Get_fMask_for_String() here */
157     item.fMask =
158         Get_fMask_for_String()
159         // Get_fMask_for_FType_and_String()
160         | MIIM_SUBMENU | MIIM_ID;
161     if (!menu.GetItem(i, true, item))
162       break;
163     {
164       UString newString;
165       if (item.hSubMenu)
166       {
167         /* in win10:
168            MENU+POPUP:
169              (wID == item.hSubMenu)
170            MENUEX+POPUP where ID is not set:
171              (wID == 0)
172            MENU+SEPARATOR
173              (wID == 0)
174         */
175         UInt32 langID = item.wID;
176         if (langID >= (1 << 16))
177         {
178           // here we try to exclude the case (wID == item.hSubMenu) if (MENU+POPUP)
179           continue;
180         }
181         if (langID == 0)
182         {
183           if (level == 0)
184           {
185             if (i < Z7_ARRAY_SIZE(k_LangID_TopMenuItems))
186               langID = k_LangID_TopMenuItems[i];
187           }
188           else if (level == 1)
189           {
190             if (menuID == IDM_FAVORITES || (menuID == 0 && menuIndex == k_MenuIndex_Bookmarks))
191               langID = k_LangID_AddToFavorites;
192             else if (menuID == IDM_VIEW || (menuID == 0 && menuIndex == k_MenuIndex_View))
193             {
194               if (Is_MenuItem_TimePopup(item))
195                 langID = k_MenuID_TimePopup;
196               else
197                 langID = k_LangID_Toolbars;
198             }
199           }
200         }
201         if (langID == k_MenuID_TimePopup)
202           continue;
203         if (langID != k_LangID_AddToFavorites)
204           MyChangeMenu(item.hSubMenu, langID, level + 1, i);
205         if (langID == 0)
206           continue;
207         LangString_OnlyFromLangFile(langID, newString);
208         if (newString.IsEmpty())
209           continue;
210       }
211       else
212       {
213         if (item.fMask & (MIIM_TYPE | MIIM_FTYPE))
214         if (item.IsSeparator())
215           continue;
216         if (item.StringValue.IsEmpty())
217           continue;
218         const int langPos = FindLangItem(item.wID);
219         // we don't need lang change for CRC items!!!
220         const UInt32 langID = langPos >= 0 ? kIDLangPairs[langPos].LangID : item.wID;
221         if (langID == 0)
222           continue;
223 
224         if (langID == IDM_OPEN_INSIDE_ONE ||
225             langID == IDM_OPEN_INSIDE_PARSER)
226         {
227           LangString_OnlyFromLangFile(IDM_OPEN_INSIDE, newString);
228           if (newString.IsEmpty())
229             continue;
230           newString.Replace(L"&", L"");
231           const int tabPos = newString.Find(L"\t");
232           if (tabPos >= 0)
233             newString.DeleteFrom(tabPos);
234           newString += (langID == IDM_OPEN_INSIDE_ONE ? " *" : " #");
235         }
236         else if (langID == IDM_BENCHMARK2)
237         {
238           LangString_OnlyFromLangFile(IDM_BENCHMARK, newString);
239           if (newString.IsEmpty())
240             continue;
241           newString.Replace(L"&", L"");
242           const int tabPos = newString.Find(L"\t");
243           if (tabPos >= 0)
244             newString.DeleteFrom(tabPos);
245           newString += " 2";
246         }
247         else
248         {
249           LangString_OnlyFromLangFile(langID, newString);
250         }
251 
252         if (newString.IsEmpty())
253           continue;
254 
255         const int tabPos = item.StringValue.ReverseFind(L'\t');
256         if (tabPos >= 0)
257           newString += item.StringValue.Ptr(tabPos);
258       }
259 
260       {
261         item.StringValue = newString;
262         // we want to change only String
263         item.fMask = Get_fMask_for_String();
264         menu.SetItem(i, true, item);
265       }
266     }
267   }
268 }
269 #endif
270 
271 static CMenu g_FileMenu;
272 
273 static struct CFileMenuDestroyer
274 {
~CFileMenuDestroyerCFileMenuDestroyer275   ~CFileMenuDestroyer() { if ((HMENU)g_FileMenu) g_FileMenu.Destroy(); }
276 } g_FileMenuDestroyer;
277 
278 
279 static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec);
280 
CopyPopMenu_IfRequired(CMenuItem & item)281 static void CopyPopMenu_IfRequired(CMenuItem &item)
282 {
283   /* if (item.hSubMenu) is defined
284   {
285     - it creates new (popup) menu
286     - it copies menu items from old item.hSubMenu menu to new (popup) menu
287     - it sets item.hSubMenu to handle of created (popup) menu
288   } */
289   if (item.hSubMenu)
290   {
291     CMenu popup;
292     popup.CreatePopup();
293     CopyMenu(item.hSubMenu, popup);
294     item.hSubMenu = popup;
295   }
296 }
297 
298 /* destMenuSpec must be non-NULL handle to created empty popup menu */
CopyMenu(HMENU srcMenuSpec,HMENU destMenuSpec)299 static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec)
300 {
301   CMenu srcMenu;
302   srcMenu.Attach(srcMenuSpec);
303   CMenu destMenu;
304   destMenu.Attach(destMenuSpec);
305   unsigned startPos = 0;
306   for (unsigned i = 0;; i++)
307   {
308     CMenuItem item;
309     item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
310     if (!srcMenu.GetItem(i, true, item))
311       break;
312     CopyPopMenu_IfRequired(item);
313     if (destMenu.InsertItem(startPos, true, item))
314       startPos++;
315   }
316 }
317 
318 
319 /* use for (needResetMenu):
320     false : for call from program window creation code
321     true  : for another calls : (from Options language change)
322 */
MyLoadMenu(bool needResetMenu)323 void MyLoadMenu(bool needResetMenu)
324 {
325   #ifdef UNDER_CE
326 
327   const HMENU oldMenu = g_App._commandBar.GetMenu(0);
328   if (oldMenu)
329     ::DestroyMenu(oldMenu);
330   /* BOOL b = */ g_App._commandBar.InsertMenubar(g_hInstance, IDM_MENU, 0);
331   const HMENU baseMenu = g_App._commandBar.GetMenu(0);
332   // if (startInit)
333   // SetIdsForSubMenus(baseMenu, 0, 0);
334   if (!g_LangID.IsEmpty())
335     MyChangeMenu(baseMenu, 0, 0);
336   g_App._commandBar.DrawMenuBar(0);
337 
338   #else // UNDER_CE
339 
340   const HWND hWnd = g_HWND;
341   bool menuWasChanged = false;
342   /*
343      We must reload to english default menu for at least two cases:
344      - if some submenu was changed (File or another submenu can be changed after menu activating).
345      - for change from non-english lang to another partial non-english lang,
346        where we still need some english strings.
347      But we reload menu to default menu everytime except of program starting stage.
348      That scheme is simpler than complex checks for exact conditions for menu reload.
349   */
350   if (needResetMenu)
351   {
352     const HMENU oldMenu = ::GetMenu(hWnd);
353     const HMENU newMenu = ::LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_MENU));
354     // docs for SetMenu(): the window is redrawn to reflect the menu change.
355     if (newMenu && ::SetMenu(hWnd, newMenu))
356       ::DestroyMenu(oldMenu);
357     menuWasChanged = true;
358   }
359   const HMENU baseMenu = ::GetMenu(hWnd);
360   // if (startInit)
361   // SetIdsForSubMenus(baseMenu, 0, 0);
362   #ifdef Z7_LANG
363   if (!g_Lang.IsEmpty()) // !g_LangID.IsEmpty() &&
364   {
365     MyChangeMenu(baseMenu, 0, 0, 0);
366     menuWasChanged = true;
367   }
368   #endif
369 
370   if (menuWasChanged)
371     ::DrawMenuBar(hWnd);
372 
373   #endif // UNDER_CE
374 
375   // menuWasChanged = false; // for debug
376   if (menuWasChanged || !(HMENU)g_FileMenu)
377   {
378     if ((HMENU)g_FileMenu)
379       g_FileMenu.Destroy();
380     g_FileMenu.CreatePopup();
381     CopyMenu(::GetSubMenu(baseMenu, k_MenuIndex_File), g_FileMenu);
382   }
383 }
384 
OnMenuActivating(HWND,HMENU hMenu,int position)385 void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
386 {
387   HMENU mainMenu =
388     #ifdef UNDER_CE
389     g_App._commandBar.GetMenu(0);
390     #else
391     ::GetMenu(g_HWND)
392     #endif
393     ;
394 
395   if (::GetSubMenu(mainMenu, position) != hMenu)
396     return;
397 
398   if (position == k_MenuIndex_File)
399   {
400     CMenu menu;
401     menu.Attach(hMenu);
402     menu.RemoveAllItems();
403     g_App.GetFocusedPanel().CreateFileMenu(hMenu);
404   }
405   else if (position == k_MenuIndex_Edit)
406   {
407     /*
408     CMenu menu;
409     menu.Attach(hMenu);
410     menu.EnableItem(IDM_EDIT_CUT, MF_ENABLED);
411     menu.EnableItem(IDM_EDIT_COPY, MF_ENABLED);
412     menu.EnableItem(IDM_EDIT_PASTE, IsClipboardFormatAvailableHDROP() ? MF_ENABLED : MF_GRAYED);
413     */
414   }
415   else if (position == k_MenuIndex_View)
416   {
417     // View;
418     CMenu menu;
419     menu.Attach(hMenu);
420     menu.CheckRadioItem(
421         IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,
422         IDM_VIEW_LARGE_ICONS + g_App.GetListViewMode(), MF_BYCOMMAND);
423 
424     menu.CheckRadioItem(
425         IDM_VIEW_ARANGE_BY_NAME,
426         IDM_VIEW_ARANGE_NO_SORT,
427         GetSortControlID(g_App.GetSortID()),
428         MF_BYCOMMAND);
429 
430     menu.CheckItemByID(IDM_VIEW_TWO_PANELS, g_App.NumPanels == 2);
431     menu.CheckItemByID(IDM_VIEW_FLAT_VIEW, g_App.GetFlatMode());
432     menu.CheckItemByID(IDM_VIEW_ARCHIVE_TOOLBAR, g_App.ShowArchiveToolbar);
433     menu.CheckItemByID(IDM_VIEW_STANDARD_TOOLBAR, g_App.ShowStandardToolbar);
434     menu.CheckItemByID(IDM_VIEW_TOOLBARS_LARGE_BUTTONS, g_App.LargeButtons);
435     menu.CheckItemByID(IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT, g_App.ShowButtonsLables);
436     menu.CheckItemByID(IDM_VIEW_AUTO_REFRESH, g_App.Get_AutoRefresh_Mode());
437     // menu.CheckItemByID(IDM_VIEW_SHOW_STREAMS, g_App.Get_ShowNtfsStrems_Mode());
438     // menu.CheckItemByID(IDM_VIEW_SHOW_DELETED, g_App.ShowDeletedFiles);
439 
440     for (unsigned i = 0;; i++)
441     {
442       CMenuItem item;
443       item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID;
444       item.fType = MFT_STRING;
445       if (!menu.GetItem(i, true, item))
446         break;
447       if (item.hSubMenu && Is_MenuItem_TimePopup(item))
448       {
449         FILETIME ft;
450         NTime::GetCurUtcFileTime(ft);
451 
452         {
453           wchar_t s[64];
454           s[0] = 0;
455           if (ConvertUtcFileTimeToString(ft, s, kTimestampPrintLevel_DAY))
456             item.StringValue = s;
457         }
458 
459         item.fMask = Get_fMask_for_String() | MIIM_ID;
460         item.fType = MFT_STRING;
461         item.wID = k_MenuID_TimePopup;
462         menu.SetItem(i, true, item);
463 
464         CMenu subMenu;
465         subMenu.Attach(menu.GetSubMenu((int)i));
466         subMenu.RemoveAllItems();
467 
468         const int k_TimeLevels[] =
469         {
470           kTimestampPrintLevel_DAY,
471           kTimestampPrintLevel_MIN,
472           kTimestampPrintLevel_SEC,
473           // 1,2,3,4,5,6,
474           kTimestampPrintLevel_NTFS,
475           kTimestampPrintLevel_NS
476         };
477 
478         unsigned last = k_MenuID_Time;
479         unsigned selectedCommand = 0;
480         g_App._timestampLevels.Clear();
481         unsigned id = k_MenuID_Time;
482 
483         for (unsigned k = 0; k < Z7_ARRAY_SIZE(k_TimeLevels); k++)
484         {
485           wchar_t s[64];
486           s[0] = 0;
487           const int timestampLevel = k_TimeLevels[k];
488           if (ConvertUtcFileTimeToString(ft, s, timestampLevel))
489           {
490             if (subMenu.AppendItem(MF_STRING, id, s))
491             {
492               last = id;
493               g_App._timestampLevels.Add(timestampLevel);
494               if (g_App.GetTimestampLevel() == timestampLevel)
495                 selectedCommand = id;
496               id++;
497             }
498           }
499         }
500         if (selectedCommand != 0)
501           menu.CheckRadioItem(k_MenuID_Time, last, selectedCommand, MF_BYCOMMAND);
502 
503         if (subMenu.AppendItem(MF_STRING, IDM_VIEW_TIME_UTC, L"UTC"))
504           subMenu.CheckItemByID(IDM_VIEW_TIME_UTC, g_Timestamp_Show_UTC);
505       }
506     }
507   }
508   else if (position == k_MenuIndex_Bookmarks)
509   {
510     CMenu menu;
511     menu.Attach(hMenu);
512 
513     CMenu subMenu;
514     subMenu.Attach(menu.GetSubMenu(0));
515     subMenu.RemoveAllItems();
516     unsigned i;
517 
518     for (i = 0; i < 10; i++)
519     {
520       UString s = LangString(IDS_BOOKMARK);
521       s.Add_Space();
522       const char c = (char)(L'0' + i);
523       s.Add_Char(c);
524       s += "\tAlt+Shift+";
525       s.Add_Char(c);
526       subMenu.AppendItem(MF_STRING, k_MenuID_SetBookmark + i, s);
527     }
528 
529     menu.RemoveAllItemsFrom(2);
530 
531     for (i = 0; i < 10; i++)
532     {
533       UString s = g_App.AppState.FastFolders.GetString(i);
534       const int kMaxSize = 100;
535       const int kFirstPartSize = kMaxSize / 2;
536       if (s.Len() > kMaxSize)
537       {
538         s.Delete(kFirstPartSize, s.Len() - kMaxSize);
539         s.Insert(kFirstPartSize, L" ... ");
540       }
541       if (s.IsEmpty())
542         s = '-';
543       s += "\tAlt+";
544       s.Add_Char((char)('0' + i));
545       menu.AppendItem(MF_STRING, k_MenuID_OpenBookmark + i, s);
546     }
547 #if 0
548     {
549       FString tempPathF;
550       if (NFile::NDir::MyGetTempPath(tempPathF))
551       {
552         menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)NULL);
553         UString s;
554         s = "Temp : ";
555         s  += fs2us(tempPathF);
556         menu.AppendItem(MF_STRING, k_MenuID_Bookmark_Temp, s);
557       }
558     }
559 #endif
560   }
561 }
562 
563 /*
564 It doesn't help
565 void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id)
566 {
567   if (::GetSubMenu(::GetMenu(g_HWND), 0) != hMenu)
568     return;
569 }
570 */
571 
572 static const unsigned g_Zvc_IDs[] =
573 {
574   IDM_VER_EDIT,
575   IDM_VER_COMMIT,
576   IDM_VER_REVERT,
577   IDM_VER_DIFF
578 };
579 
580 static const char * const g_Zvc_Strings[] =
581 {
582     "Ver Edit (&1)"
583   , "Ver Commit"
584   , "Ver Revert"
585   , "Ver Diff (&0)"
586 };
587 
Load(HMENU hMenu,unsigned startPos)588 void CFileMenu::Load(HMENU hMenu, unsigned startPos)
589 {
590   CMenu destMenu;
591   destMenu.Attach(hMenu);
592 
593   UString diffPath;
594   ReadRegDiff(diffPath);
595 
596   unsigned numRealItems = startPos;
597 
598   const bool isBigScreen = NControl::IsDialogSizeOK(40, 200, g_HWND);
599 
600   for (unsigned i = 0;; i++)
601   {
602     CMenuItem item;
603 
604     item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
605     item.fType = MFT_STRING;
606 
607     if (!g_FileMenu.GetItem(i, true, item))
608       break;
609 
610     {
611       if (!programMenu && item.wID == IDCLOSE)
612         continue;
613 
614       if (item.wID == IDM_DIFF && diffPath.IsEmpty())
615         continue;
616 
617       if (item.wID == IDM_OPEN_INSIDE_ONE || item.wID == IDM_OPEN_INSIDE_PARSER)
618       {
619         // We use diff as "super mode" marker for additional commands.
620         /*
621         if (diffPath.IsEmpty())
622           continue;
623         */
624       }
625 
626       if (item.wID == IDM_BENCHMARK2)
627       {
628         // We use diff as "super mode" marker for additional commands.
629         if (diffPath.IsEmpty())
630           continue;
631       }
632 
633       bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles);
634       bool disable = (!isOneFsFile && (item.wID == IDM_SPLIT || item.wID == IDM_COMBINE));
635 
636       if (readOnly)
637       {
638         switch (item.wID)
639         {
640           case IDM_RENAME:
641           case IDM_MOVE_TO:
642           case IDM_DELETE:
643           case IDM_COMMENT:
644           case IDM_CREATE_FOLDER:
645           case IDM_CREATE_FILE:
646             disable = true;
647         }
648       }
649 
650       if (isHashFolder)
651       {
652         switch (item.wID)
653         {
654           case IDM_OPEN:
655           case IDM_OPEN_INSIDE:
656           case IDM_OPEN_INSIDE_ONE:
657           case IDM_OPEN_INSIDE_PARSER:
658           case IDM_OPEN_OUTSIDE:
659           case IDM_FILE_VIEW:
660           case IDM_FILE_EDIT:
661           // case IDM_RENAME:
662           case IDM_COPY_TO:
663           case IDM_MOVE_TO:
664           // case IDM_DELETE:
665           case IDM_COMMENT:
666           case IDM_CREATE_FOLDER:
667           case IDM_CREATE_FILE:
668           case IDM_LINK:
669           case IDM_DIFF:
670             disable = true;
671         }
672       }
673 
674 
675       if (item.wID == IDM_LINK && numItems != 1)
676         disable = true;
677 
678       if (item.wID == IDM_ALT_STREAMS)
679         disable = !isAltStreamsSupported;
680 
681       if (!isBigScreen && (disable || item.IsSeparator()))
682         continue;
683 
684       CopyPopMenu_IfRequired(item);
685       if (destMenu.InsertItem(startPos, true, item))
686       {
687         if (disable)
688           destMenu.EnableItem(startPos, MF_BYPOSITION | MF_GRAYED);
689         startPos++;
690       }
691 
692       if (!item.IsSeparator())
693         numRealItems = startPos;
694     }
695   }
696 
697   UString vercPath;
698   if (!diffPath.IsEmpty() && isFsFolder && allAreFiles && numItems == 1)
699     ReadReg_VerCtrlPath(vercPath);
700 
701   if (!vercPath.IsEmpty())
702   {
703     NFile::NFind::CFileInfo fi;
704     if (fi.Find(FilePath) && fi.Size < ((UInt32)1 << 31) && !fi.IsDir())
705     {
706       for (unsigned k = 0; k < Z7_ARRAY_SIZE(g_Zvc_IDs); k++)
707       {
708         const unsigned id = g_Zvc_IDs[k];
709         if (fi.IsReadOnly())
710         {
711           if (id == IDM_VER_COMMIT ||
712               id == IDM_VER_REVERT ||
713               id == IDM_VER_DIFF)
714             continue;
715         }
716         else
717         {
718           if (id == IDM_VER_EDIT)
719             continue;
720         }
721 
722         CMenuItem item;
723         UString s (g_Zvc_Strings[k]);
724         if (destMenu.AppendItem(MF_STRING, id, s))
725         {
726           startPos++;
727           numRealItems = startPos;
728         }
729       }
730     }
731   }
732 
733   destMenu.RemoveAllItemsFrom(numRealItems);
734 }
735 
ExecuteFileCommand(unsigned id)736 bool ExecuteFileCommand(unsigned id)
737 {
738   if (id >= kMenuCmdID_Plugin_Start)
739   {
740     g_App.GetFocusedPanel().InvokePluginCommand(id);
741     g_App.GetFocusedPanel()._sevenZipContextMenu.Release();
742     g_App.GetFocusedPanel()._systemContextMenu.Release();
743     return true;
744   }
745 
746   switch (id)
747   {
748     // File
749     case IDM_OPEN: g_App.OpenItem(); break;
750 
751     case IDM_OPEN_INSIDE:        g_App.OpenItemInside(NULL); break;
752     case IDM_OPEN_INSIDE_ONE:    g_App.OpenItemInside(L"*"); break;
753     case IDM_OPEN_INSIDE_PARSER: g_App.OpenItemInside(L"#"); break;
754 
755     case IDM_OPEN_OUTSIDE: g_App.OpenItemOutside(); break;
756     case IDM_FILE_VIEW: g_App.EditItem(false); break;
757     case IDM_FILE_EDIT: g_App.EditItem(true); break;
758     case IDM_RENAME: g_App.Rename(); break;
759     case IDM_COPY_TO: g_App.CopyTo(); break;
760     case IDM_MOVE_TO: g_App.MoveTo(); break;
761     case IDM_DELETE: g_App.Delete(!IsKeyDown(VK_SHIFT)); break;
762 
763     case IDM_HASH_ALL: g_App.CalculateCrc("*"); break;
764     case IDM_CRC32: g_App.CalculateCrc("CRC32"); break;
765     case IDM_CRC64: g_App.CalculateCrc("CRC64"); break;
766     case IDM_XXH64: g_App.CalculateCrc("XXH64"); break;
767     case IDM_MD5: g_App.CalculateCrc("MD5"); break;
768     case IDM_SHA1: g_App.CalculateCrc("SHA1"); break;
769     case IDM_SHA256: g_App.CalculateCrc("SHA256"); break;
770     case IDM_SHA384: g_App.CalculateCrc("SHA384"); break;
771     case IDM_SHA512: g_App.CalculateCrc("SHA512"); break;
772     case IDM_SHA3_256: g_App.CalculateCrc("SHA3-256"); break;
773     case IDM_BLAKE2SP: g_App.CalculateCrc("BLAKE2sp"); break;
774 
775     case IDM_DIFF: g_App.DiffFiles(); break;
776 
777     case IDM_VER_EDIT:
778     case IDM_VER_COMMIT:
779     case IDM_VER_REVERT:
780     case IDM_VER_DIFF:
781         g_App.VerCtrl(id); break;
782 
783     case IDM_SPLIT: g_App.Split(); break;
784     case IDM_COMBINE: g_App.Combine(); break;
785     case IDM_PROPERTIES: g_App.Properties(); break;
786     case IDM_COMMENT: g_App.Comment(); break;
787     case IDM_CREATE_FOLDER: g_App.CreateFolder(); break;
788     case IDM_CREATE_FILE: g_App.CreateFile(); break;
789     #ifndef UNDER_CE
790     case IDM_LINK: g_App.Link(); break;
791     case IDM_ALT_STREAMS: g_App.OpenAltStreams(); break;
792     #endif
793     default: return false;
794   }
795   return true;
796 }
797 
MyBenchmark(bool totalMode)798 static void MyBenchmark(bool totalMode)
799 {
800   CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]);
801   CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]);
802   Benchmark(totalMode);
803 }
804 
OnMenuCommand(HWND hWnd,unsigned id)805 bool OnMenuCommand(HWND hWnd, unsigned id)
806 {
807   if (ExecuteFileCommand(id))
808     return true;
809 
810   switch (id)
811   {
812     // File
813     case IDCLOSE:
814       // SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd);
815       // g_ExitEventLauncher.Exit(false);
816       SendMessage(hWnd, WM_CLOSE, 0, 0);
817       break;
818 
819     // Edit
820     /*
821     case IDM_EDIT_CUT:
822       g_App.EditCut();
823       break;
824     case IDM_EDIT_COPY:
825       g_App.EditCopy();
826       break;
827     case IDM_EDIT_PASTE:
828       g_App.EditPaste();
829       break;
830     */
831     case IDM_SELECT_ALL:
832       g_App.SelectAll(true);
833       g_App.Refresh_StatusBar();
834       break;
835     case IDM_DESELECT_ALL:
836       g_App.SelectAll(false);
837       g_App.Refresh_StatusBar();
838       break;
839     case IDM_INVERT_SELECTION:
840       g_App.InvertSelection();
841       g_App.Refresh_StatusBar();
842       break;
843     case IDM_SELECT:
844       g_App.SelectSpec(true);
845       g_App.Refresh_StatusBar();
846       break;
847     case IDM_DESELECT:
848       g_App.SelectSpec(false);
849       g_App.Refresh_StatusBar();
850       break;
851     case IDM_SELECT_BY_TYPE:
852       g_App.SelectByType(true);
853       g_App.Refresh_StatusBar();
854       break;
855     case IDM_DESELECT_BY_TYPE:
856       g_App.SelectByType(false);
857       g_App.Refresh_StatusBar();
858       break;
859 
860     //View
861     case IDM_VIEW_LARGE_ICONS:
862     case IDM_VIEW_SMALL_ICONS:
863     case IDM_VIEW_LIST:
864     case IDM_VIEW_DETAILS:
865     {
866       UINT index = id - IDM_VIEW_LARGE_ICONS;
867       if (index < 4)
868       {
869         g_App.SetListViewMode(index);
870         /*
871         CMenu menu;
872         menu.Attach(::GetSubMenu(::GetMenu(hWnd), k_MenuIndex_View));
873         menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,
874             id, MF_BYCOMMAND);
875         */
876       }
877       break;
878     }
879     case IDM_VIEW_ARANGE_BY_NAME: g_App.SortItemsWithPropID(kpidName); break;
880     case IDM_VIEW_ARANGE_BY_TYPE: g_App.SortItemsWithPropID(kpidExtension); break;
881     case IDM_VIEW_ARANGE_BY_DATE: g_App.SortItemsWithPropID(kpidMTime); break;
882     case IDM_VIEW_ARANGE_BY_SIZE: g_App.SortItemsWithPropID(kpidSize); break;
883     case IDM_VIEW_ARANGE_NO_SORT: g_App.SortItemsWithPropID(kpidNoProperty); break;
884 
885     case IDM_OPEN_ROOT_FOLDER:    g_App.OpenRootFolder(); break;
886     case IDM_OPEN_PARENT_FOLDER:  g_App.OpenParentFolder(); break;
887     case IDM_FOLDERS_HISTORY:     g_App.FoldersHistory(); break;
888     case IDM_VIEW_FLAT_VIEW:      g_App.ChangeFlatMode(); break;
889     case IDM_VIEW_REFRESH:        g_App.RefreshView(); break;
890     case IDM_VIEW_AUTO_REFRESH:   g_App.Change_AutoRefresh_Mode(); break;
891 
892     // case IDM_VIEW_SHOW_STREAMS:     g_App.Change_ShowNtfsStrems_Mode(); break;
893     /*
894     case IDM_VIEW_SHOW_DELETED:
895     {
896       g_App.Change_ShowDeleted();
897       bool isChecked = g_App.ShowDeletedFiles;
898       Save_ShowDeleted(isChecked);
899     }
900     */
901 
902     case IDM_VIEW_TWO_PANELS:       g_App.SwitchOnOffOnePanel(); break;
903     case IDM_VIEW_STANDARD_TOOLBAR: g_App.SwitchStandardToolbar(); break;
904     case IDM_VIEW_ARCHIVE_TOOLBAR:  g_App.SwitchArchiveToolbar(); break;
905 
906     case IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT: g_App.SwitchButtonsLables(); break;
907     case IDM_VIEW_TOOLBARS_LARGE_BUTTONS:     g_App.SwitchLargeButtons(); break;
908 
909     case IDM_VIEW_TIME_UTC:
910       g_Timestamp_Show_UTC = !g_Timestamp_Show_UTC;
911       g_App.RedrawListItems_InPanels();
912       break;
913 
914     // Tools
915     case IDM_OPTIONS: OptionsDialog(hWnd, g_hInstance); break;
916 
917     case IDM_BENCHMARK: MyBenchmark(false); break;
918     case IDM_BENCHMARK2: MyBenchmark(true); break;
919 
920     // Help
921     case IDM_HELP_CONTENTS:
922       ShowHelpWindow(kFMHelpTopic);
923       break;
924     case IDM_ABOUT:
925     {
926       CAboutDialog dialog;
927       dialog.Create(hWnd);
928       break;
929     }
930 
931     case IDM_TEMP_DIR:
932     {
933       /*
934       CPanel &panel = g_App.GetFocusedPanel();
935       FString tempPathF;
936       if (NFile::NDir::MyGetTempPath(tempPathF))
937         panel.BindToPathAndRefresh(tempPathF);
938       */
939       MyBrowseForTempFolder(g_HWND);
940       break;
941     }
942 
943     default:
944     {
945       if (id >= k_MenuID_OpenBookmark && id <= k_MenuID_OpenBookmark + 9)
946       {
947         g_App.OpenBookmark(id - k_MenuID_OpenBookmark);
948         return true;
949       }
950       else if (id >= k_MenuID_SetBookmark && id <= k_MenuID_SetBookmark + 9)
951       {
952         g_App.SetBookmark(id - k_MenuID_SetBookmark);
953         return true;
954       }
955       else if (id >= k_MenuID_Time && (unsigned)id < k_MenuID_Time + g_App._timestampLevels.Size())
956       {
957         g_App.SetTimestampLevel(g_App._timestampLevels[id - k_MenuID_Time]);
958         return true;
959       }
960       return false;
961     }
962   }
963   return true;
964 }
965