xref: /aosp_15_r20/external/lzma/CPP/Windows/Menu.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Windows/Menu.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
6*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StringConvert.h"
7*f6dc9357SAndroid Build Coastguard Worker #endif
8*f6dc9357SAndroid Build Coastguard Worker #include "Menu.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
11*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
12*f6dc9357SAndroid Build Coastguard Worker #endif
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker /*
17*f6dc9357SAndroid Build Coastguard Worker structures
18*f6dc9357SAndroid Build Coastguard Worker   MENUITEMINFOA
19*f6dc9357SAndroid Build Coastguard Worker   MENUITEMINFOW
20*f6dc9357SAndroid Build Coastguard Worker contain additional member:
21*f6dc9357SAndroid Build Coastguard Worker   #if (WINVER >= 0x0500)
22*f6dc9357SAndroid Build Coastguard Worker     HBITMAP hbmpItem;
23*f6dc9357SAndroid Build Coastguard Worker   #endif
24*f6dc9357SAndroid Build Coastguard Worker If we compile the source code with (WINVER >= 0x0500), some functions
25*f6dc9357SAndroid Build Coastguard Worker will not work at NT4, if cbSize is set as sizeof(MENUITEMINFO).
26*f6dc9357SAndroid Build Coastguard Worker So we use size of old version of structure in some conditions.
27*f6dc9357SAndroid Build Coastguard Worker Win98 probably supports full structure including hbmpItem.
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker We have 2 ways to get/set string in menu item:
30*f6dc9357SAndroid Build Coastguard Worker win95/NT4: we must use MIIM_TYPE only.
31*f6dc9357SAndroid Build Coastguard Worker   MIIM_TYPE    : Retrieves or sets the fType and dwTypeData members.
32*f6dc9357SAndroid Build Coastguard Worker win98/win2000: there are new flags that can be used instead of MIIM_TYPE:
33*f6dc9357SAndroid Build Coastguard Worker   MIIM_FTYPE   : Retrieves or sets the fType member.
34*f6dc9357SAndroid Build Coastguard Worker   MIIM_STRING  : Retrieves or sets the dwTypeData member.
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker Windows versions probably support MIIM_TYPE flag, if we set MENUITEMINFO::cbSize
37*f6dc9357SAndroid Build Coastguard Worker as sizeof of old (small) MENUITEMINFO that doesn't include (hbmpItem) field.
38*f6dc9357SAndroid Build Coastguard Worker But do all Windows versions support old MIIM_TYPE flag, if we use
39*f6dc9357SAndroid Build Coastguard Worker MENUITEMINFO::cbSize as sizeof of new (big) MENUITEMINFO including (hbmpItem) field ?
40*f6dc9357SAndroid Build Coastguard Worker win10 probably supports any combination of small/big (cbSize) and old/new MIIM_TYPE/MIIM_STRING.
41*f6dc9357SAndroid Build Coastguard Worker */
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker #if defined(UNDER_CE) || defined(_WIN64) || (WINVER < 0x0500)
44*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
45*f6dc9357SAndroid Build Coastguard Worker   #define my_compatib_MENUITEMINFOA_size  sizeof(MENUITEMINFOA)
46*f6dc9357SAndroid Build Coastguard Worker   #endif
47*f6dc9357SAndroid Build Coastguard Worker   #define my_compatib_MENUITEMINFOW_size  sizeof(MENUITEMINFOW)
48*f6dc9357SAndroid Build Coastguard Worker #else
49*f6dc9357SAndroid Build Coastguard Worker   #define MY_STRUCT_SIZE_BEFORE(structname, member) ((UINT)(UINT_PTR)((LPBYTE)(&((structname*)0)->member) - (LPBYTE)(structname*)0))
50*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
51*f6dc9357SAndroid Build Coastguard Worker   #define my_compatib_MENUITEMINFOA_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOA, hbmpItem)
52*f6dc9357SAndroid Build Coastguard Worker   #endif
53*f6dc9357SAndroid Build Coastguard Worker   #define my_compatib_MENUITEMINFOW_size MY_STRUCT_SIZE_BEFORE(MENUITEMINFOW, hbmpItem)
54*f6dc9357SAndroid Build Coastguard Worker #if defined(__clang__) && __clang_major__ >= 13
55*f6dc9357SAndroid Build Coastguard Worker // error : performing pointer subtraction with a null pointer may have undefined behavior
56*f6dc9357SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wnull-pointer-subtraction"
57*f6dc9357SAndroid Build Coastguard Worker #endif
58*f6dc9357SAndroid Build Coastguard Worker #endif
59*f6dc9357SAndroid Build Coastguard Worker 
60*f6dc9357SAndroid Build Coastguard Worker 
61*f6dc9357SAndroid Build Coastguard Worker #define COPY_MENUITEM_field(d, s, name) \
62*f6dc9357SAndroid Build Coastguard Worker   d.name = s.name;
63*f6dc9357SAndroid Build Coastguard Worker 
64*f6dc9357SAndroid Build Coastguard Worker #define COPY_MENUITEM_fields(d, s)  \
65*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, fMask)  \
66*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, fType)  \
67*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, fState)  \
68*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, wID)  \
69*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, hSubMenu)  \
70*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, hbmpChecked)  \
71*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, hbmpUnchecked)  \
72*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_field(d, s, dwItemData)  \
73*f6dc9357SAndroid Build Coastguard Worker 
ConvertItemToSysForm(const CMenuItem & item,MENUITEMINFOW & si)74*f6dc9357SAndroid Build Coastguard Worker static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOW &si)
75*f6dc9357SAndroid Build Coastguard Worker {
76*f6dc9357SAndroid Build Coastguard Worker   ZeroMemory(&si, sizeof(si));
77*f6dc9357SAndroid Build Coastguard Worker   si.cbSize = my_compatib_MENUITEMINFOW_size; // sizeof(si);
78*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_fields(si, item)
79*f6dc9357SAndroid Build Coastguard Worker }
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
ConvertItemToSysForm(const CMenuItem & item,MENUITEMINFOA & si)82*f6dc9357SAndroid Build Coastguard Worker static void ConvertItemToSysForm(const CMenuItem &item, MENUITEMINFOA &si)
83*f6dc9357SAndroid Build Coastguard Worker {
84*f6dc9357SAndroid Build Coastguard Worker   ZeroMemory(&si, sizeof(si));
85*f6dc9357SAndroid Build Coastguard Worker   si.cbSize = my_compatib_MENUITEMINFOA_size; // sizeof(si);
86*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_fields(si, item)
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker #endif
89*f6dc9357SAndroid Build Coastguard Worker 
ConvertItemToMyForm(const MENUITEMINFOW & si,CMenuItem & item)90*f6dc9357SAndroid Build Coastguard Worker static void ConvertItemToMyForm(const MENUITEMINFOW &si, CMenuItem &item)
91*f6dc9357SAndroid Build Coastguard Worker {
92*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_fields(item, si)
93*f6dc9357SAndroid Build Coastguard Worker }
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
ConvertItemToMyForm(const MENUITEMINFOA & si,CMenuItem & item)96*f6dc9357SAndroid Build Coastguard Worker static void ConvertItemToMyForm(const MENUITEMINFOA &si, CMenuItem &item)
97*f6dc9357SAndroid Build Coastguard Worker {
98*f6dc9357SAndroid Build Coastguard Worker   COPY_MENUITEM_fields(item, si)
99*f6dc9357SAndroid Build Coastguard Worker }
100*f6dc9357SAndroid Build Coastguard Worker #endif
101*f6dc9357SAndroid Build Coastguard Worker 
102*f6dc9357SAndroid Build Coastguard Worker 
GetItem(UINT itemIndex,bool byPosition,CMenuItem & item) const103*f6dc9357SAndroid Build Coastguard Worker bool CMenu::GetItem(UINT itemIndex, bool byPosition, CMenuItem &item) const
104*f6dc9357SAndroid Build Coastguard Worker {
105*f6dc9357SAndroid Build Coastguard Worker   item.StringValue.Empty();
106*f6dc9357SAndroid Build Coastguard Worker   const unsigned kMaxSize = 512;
107*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
108*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
109*f6dc9357SAndroid Build Coastguard Worker   {
110*f6dc9357SAndroid Build Coastguard Worker     MENUITEMINFOA si;
111*f6dc9357SAndroid Build Coastguard Worker     ConvertItemToSysForm(item, si);
112*f6dc9357SAndroid Build Coastguard Worker     const bool isString = item.IsString();
113*f6dc9357SAndroid Build Coastguard Worker     unsigned bufSize = kMaxSize;
114*f6dc9357SAndroid Build Coastguard Worker     AString a;
115*f6dc9357SAndroid Build Coastguard Worker     if (isString)
116*f6dc9357SAndroid Build Coastguard Worker     {
117*f6dc9357SAndroid Build Coastguard Worker       si.cch = bufSize;
118*f6dc9357SAndroid Build Coastguard Worker       si.dwTypeData = a.GetBuf(bufSize);
119*f6dc9357SAndroid Build Coastguard Worker     }
120*f6dc9357SAndroid Build Coastguard Worker     bool res = GetItemInfo(itemIndex, byPosition, &si);
121*f6dc9357SAndroid Build Coastguard Worker     if (isString)
122*f6dc9357SAndroid Build Coastguard Worker       a.ReleaseBuf_CalcLen(bufSize);
123*f6dc9357SAndroid Build Coastguard Worker     if (!res)
124*f6dc9357SAndroid Build Coastguard Worker       return false;
125*f6dc9357SAndroid Build Coastguard Worker     {
126*f6dc9357SAndroid Build Coastguard Worker       if (isString && si.cch >= bufSize - 1)
127*f6dc9357SAndroid Build Coastguard Worker       {
128*f6dc9357SAndroid Build Coastguard Worker         si.dwTypeData = NULL;
129*f6dc9357SAndroid Build Coastguard Worker         res = GetItemInfo(itemIndex, byPosition, &si);
130*f6dc9357SAndroid Build Coastguard Worker         if (!res)
131*f6dc9357SAndroid Build Coastguard Worker           return false;
132*f6dc9357SAndroid Build Coastguard Worker         si.cch++;
133*f6dc9357SAndroid Build Coastguard Worker         bufSize = si.cch;
134*f6dc9357SAndroid Build Coastguard Worker         si.dwTypeData = a.GetBuf(bufSize);
135*f6dc9357SAndroid Build Coastguard Worker         res = GetItemInfo(itemIndex, byPosition, &si);
136*f6dc9357SAndroid Build Coastguard Worker         a.ReleaseBuf_CalcLen(bufSize);
137*f6dc9357SAndroid Build Coastguard Worker         if (!res)
138*f6dc9357SAndroid Build Coastguard Worker           return false;
139*f6dc9357SAndroid Build Coastguard Worker       }
140*f6dc9357SAndroid Build Coastguard Worker       ConvertItemToMyForm(si, item);
141*f6dc9357SAndroid Build Coastguard Worker       if (isString)
142*f6dc9357SAndroid Build Coastguard Worker         item.StringValue = GetUnicodeString(a);
143*f6dc9357SAndroid Build Coastguard Worker       return true;
144*f6dc9357SAndroid Build Coastguard Worker     }
145*f6dc9357SAndroid Build Coastguard Worker   }
146*f6dc9357SAndroid Build Coastguard Worker   else
147*f6dc9357SAndroid Build Coastguard Worker   #endif
148*f6dc9357SAndroid Build Coastguard Worker   {
149*f6dc9357SAndroid Build Coastguard Worker     wchar_t s[kMaxSize + 1];
150*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
151*f6dc9357SAndroid Build Coastguard Worker     MENUITEMINFOW si;
152*f6dc9357SAndroid Build Coastguard Worker     ConvertItemToSysForm(item, si);
153*f6dc9357SAndroid Build Coastguard Worker     const bool isString = item.IsString();
154*f6dc9357SAndroid Build Coastguard Worker     unsigned bufSize = kMaxSize;
155*f6dc9357SAndroid Build Coastguard Worker     if (isString)
156*f6dc9357SAndroid Build Coastguard Worker     {
157*f6dc9357SAndroid Build Coastguard Worker       si.cch = bufSize;
158*f6dc9357SAndroid Build Coastguard Worker       si.dwTypeData = s;
159*f6dc9357SAndroid Build Coastguard Worker     }
160*f6dc9357SAndroid Build Coastguard Worker     bool res = GetItemInfo(itemIndex, byPosition, &si);
161*f6dc9357SAndroid Build Coastguard Worker     if (!res)
162*f6dc9357SAndroid Build Coastguard Worker       return false;
163*f6dc9357SAndroid Build Coastguard Worker     if (isString)
164*f6dc9357SAndroid Build Coastguard Worker     {
165*f6dc9357SAndroid Build Coastguard Worker       s[Z7_ARRAY_SIZE(s) - 1] = 0;
166*f6dc9357SAndroid Build Coastguard Worker       item.StringValue = s;
167*f6dc9357SAndroid Build Coastguard Worker       if (si.cch >= bufSize - 1)
168*f6dc9357SAndroid Build Coastguard Worker       {
169*f6dc9357SAndroid Build Coastguard Worker         si.dwTypeData = NULL;
170*f6dc9357SAndroid Build Coastguard Worker         res = GetItemInfo(itemIndex, byPosition, &si);
171*f6dc9357SAndroid Build Coastguard Worker         if (!res)
172*f6dc9357SAndroid Build Coastguard Worker           return false;
173*f6dc9357SAndroid Build Coastguard Worker         si.cch++;
174*f6dc9357SAndroid Build Coastguard Worker         bufSize = si.cch;
175*f6dc9357SAndroid Build Coastguard Worker         si.dwTypeData = item.StringValue.GetBuf(bufSize);
176*f6dc9357SAndroid Build Coastguard Worker         res = GetItemInfo(itemIndex, byPosition, &si);
177*f6dc9357SAndroid Build Coastguard Worker         item.StringValue.ReleaseBuf_CalcLen(bufSize);
178*f6dc9357SAndroid Build Coastguard Worker         if (!res)
179*f6dc9357SAndroid Build Coastguard Worker           return false;
180*f6dc9357SAndroid Build Coastguard Worker       }
181*f6dc9357SAndroid Build Coastguard Worker       // if (item.StringValue.Len() != si.cch) throw 123; // for debug
182*f6dc9357SAndroid Build Coastguard Worker     }
183*f6dc9357SAndroid Build Coastguard Worker     ConvertItemToMyForm(si, item);
184*f6dc9357SAndroid Build Coastguard Worker     return true;
185*f6dc9357SAndroid Build Coastguard Worker   }
186*f6dc9357SAndroid Build Coastguard Worker }
187*f6dc9357SAndroid Build Coastguard Worker 
188*f6dc9357SAndroid Build Coastguard Worker 
SetItem(UINT itemIndex,bool byPosition,const CMenuItem & item)189*f6dc9357SAndroid Build Coastguard Worker bool CMenu::SetItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
192*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
193*f6dc9357SAndroid Build Coastguard Worker   {
194*f6dc9357SAndroid Build Coastguard Worker     MENUITEMINFOA si;
195*f6dc9357SAndroid Build Coastguard Worker     ConvertItemToSysForm(item, si);
196*f6dc9357SAndroid Build Coastguard Worker     AString s;
197*f6dc9357SAndroid Build Coastguard Worker     if (item.IsString())
198*f6dc9357SAndroid Build Coastguard Worker     {
199*f6dc9357SAndroid Build Coastguard Worker       s = GetSystemString(item.StringValue);
200*f6dc9357SAndroid Build Coastguard Worker       si.dwTypeData = s.Ptr_non_const();
201*f6dc9357SAndroid Build Coastguard Worker     }
202*f6dc9357SAndroid Build Coastguard Worker     return SetItemInfo(itemIndex, byPosition, &si);
203*f6dc9357SAndroid Build Coastguard Worker   }
204*f6dc9357SAndroid Build Coastguard Worker   else
205*f6dc9357SAndroid Build Coastguard Worker   #endif
206*f6dc9357SAndroid Build Coastguard Worker   {
207*f6dc9357SAndroid Build Coastguard Worker     MENUITEMINFOW si;
208*f6dc9357SAndroid Build Coastguard Worker     ConvertItemToSysForm(item, si);
209*f6dc9357SAndroid Build Coastguard Worker     if (item.IsString())
210*f6dc9357SAndroid Build Coastguard Worker       si.dwTypeData = item.StringValue.Ptr_non_const();
211*f6dc9357SAndroid Build Coastguard Worker     return SetItemInfo(itemIndex, byPosition, &si);
212*f6dc9357SAndroid Build Coastguard Worker   }
213*f6dc9357SAndroid Build Coastguard Worker }
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker 
InsertItem(UINT itemIndex,bool byPosition,const CMenuItem & item)216*f6dc9357SAndroid Build Coastguard Worker bool CMenu::InsertItem(UINT itemIndex, bool byPosition, const CMenuItem &item)
217*f6dc9357SAndroid Build Coastguard Worker {
218*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
219*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
220*f6dc9357SAndroid Build Coastguard Worker   {
221*f6dc9357SAndroid Build Coastguard Worker     MENUITEMINFOA si;
222*f6dc9357SAndroid Build Coastguard Worker     ConvertItemToSysForm(item, si);
223*f6dc9357SAndroid Build Coastguard Worker     AString s;
224*f6dc9357SAndroid Build Coastguard Worker     if (item.IsString())
225*f6dc9357SAndroid Build Coastguard Worker     {
226*f6dc9357SAndroid Build Coastguard Worker       s = GetSystemString(item.StringValue);
227*f6dc9357SAndroid Build Coastguard Worker       si.dwTypeData = s.Ptr_non_const();
228*f6dc9357SAndroid Build Coastguard Worker     }
229*f6dc9357SAndroid Build Coastguard Worker     return InsertItem(itemIndex, byPosition, &si);
230*f6dc9357SAndroid Build Coastguard Worker   }
231*f6dc9357SAndroid Build Coastguard Worker   else
232*f6dc9357SAndroid Build Coastguard Worker   #endif
233*f6dc9357SAndroid Build Coastguard Worker   {
234*f6dc9357SAndroid Build Coastguard Worker     MENUITEMINFOW si;
235*f6dc9357SAndroid Build Coastguard Worker     ConvertItemToSysForm(item, si);
236*f6dc9357SAndroid Build Coastguard Worker     if (item.IsString())
237*f6dc9357SAndroid Build Coastguard Worker       si.dwTypeData = item.StringValue.Ptr_non_const();
238*f6dc9357SAndroid Build Coastguard Worker     #ifdef UNDER_CE
239*f6dc9357SAndroid Build Coastguard Worker     UINT flags = (item.fType & MFT_SEPARATOR) ? MF_SEPARATOR : MF_STRING;
240*f6dc9357SAndroid Build Coastguard Worker     UINT_PTR id = item.wID;
241*f6dc9357SAndroid Build Coastguard Worker     if ((item.fMask & MIIM_SUBMENU) != 0)
242*f6dc9357SAndroid Build Coastguard Worker     {
243*f6dc9357SAndroid Build Coastguard Worker       flags |= MF_POPUP;
244*f6dc9357SAndroid Build Coastguard Worker       id = (UINT_PTR)item.hSubMenu;
245*f6dc9357SAndroid Build Coastguard Worker     }
246*f6dc9357SAndroid Build Coastguard Worker     if (!Insert(itemIndex, flags | (byPosition ? MF_BYPOSITION : MF_BYCOMMAND), id, item.StringValue))
247*f6dc9357SAndroid Build Coastguard Worker       return false;
248*f6dc9357SAndroid Build Coastguard Worker     return SetItemInfo(itemIndex, byPosition, &si);
249*f6dc9357SAndroid Build Coastguard Worker     #else
250*f6dc9357SAndroid Build Coastguard Worker     return InsertItem(itemIndex, byPosition, &si);
251*f6dc9357SAndroid Build Coastguard Worker     #endif
252*f6dc9357SAndroid Build Coastguard Worker   }
253*f6dc9357SAndroid Build Coastguard Worker }
254*f6dc9357SAndroid Build Coastguard Worker 
255*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
AppendItem(UINT flags,UINT_PTR newItemID,LPCWSTR newItem)256*f6dc9357SAndroid Build Coastguard Worker bool CMenu::AppendItem(UINT flags, UINT_PTR newItemID, LPCWSTR newItem)
257*f6dc9357SAndroid Build Coastguard Worker {
258*f6dc9357SAndroid Build Coastguard Worker   if (g_IsNT)
259*f6dc9357SAndroid Build Coastguard Worker     return BOOLToBool(::AppendMenuW(_menu, flags, newItemID, newItem));
260*f6dc9357SAndroid Build Coastguard Worker   else
261*f6dc9357SAndroid Build Coastguard Worker     return AppendItem(flags, newItemID, GetSystemString(newItem));
262*f6dc9357SAndroid Build Coastguard Worker }
263*f6dc9357SAndroid Build Coastguard Worker #endif
264*f6dc9357SAndroid Build Coastguard Worker 
265*f6dc9357SAndroid Build Coastguard Worker }
266