+// Contains the data about the radio items groups in the given menu.
+class wxMenuRadioItemsData
+{
+public:
+ wxMenuRadioItemsData() { }
+
+ // Default copy ctor, assignment operator and dtor are all ok.
+
+ // Find the start and end of the group containing the given position or
+ // return false if it's not inside any range.
+ bool GetGroupRange(int pos, int *start, int *end) const
+ {
+ // We use a simple linear search here because there are not that many
+ // items in a menu and hence even fewer radio items ranges anyhow, so
+ // normally there is no need to do anything fancy (like keeping the
+ // array sorted and using binary search).
+ for ( Ranges::const_iterator it = m_ranges.begin();
+ it != m_ranges.end();
+ ++it )
+ {
+ const Range& r = *it;
+
+ if ( r.start <= pos && pos <= r.end )
+ {
+ if ( start )
+ *start = r.start;
+ if ( end )
+ *end = r.end;
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Take into account the new radio item about to be added at the given
+ // position.
+ //
+ // Returns true if this item starts a new radio group, false if it extends
+ // an existing one.
+ bool UpdateOnInsert(int pos)
+ {
+ bool inExistingGroup = false;
+
+ for ( Ranges::iterator it = m_ranges.begin();
+ it != m_ranges.end();
+ ++it )
+ {
+ Range& r = *it;
+
+ if ( pos < r.start )
+ {
+ // Item is inserted before this range, update its indices.
+ r.start++;
+ r.end++;
+ }
+ else if ( pos <= r.end + 1 )
+ {
+ // Item is inserted in the middle of this range or immediately
+ // after it in which case it extends this range so make it span
+ // one more item in any case.
+ r.end++;
+
+ inExistingGroup = true;
+ }
+ //else: Item is inserted after this range, nothing to do for it.
+ }
+
+ if ( inExistingGroup )
+ return false;
+
+ // Make a new range for the group this item will belong to.
+ Range r;
+ r.start = pos;
+ r.end = pos;
+ m_ranges.push_back(r);
+
+ return true;
+ }
+
+private:
+ // Contains the inclusive positions of the range start and end.
+ struct Range
+ {
+ int start;
+ int end;
+ };
+
+ typedef wxVector<Range> Ranges;
+ Ranges m_ranges;
+};
+
+namespace
+{
+
+// make the given menu item default
+void SetDefaultMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu),
+ UINT WXUNUSED_IN_WINCE(id))
+{
+#ifndef __WXWINCE__
+ MENUITEMINFO mii;
+ wxZeroMemory(mii);
+ mii.cbSize = sizeof(MENUITEMINFO);
+ mii.fMask = MIIM_STATE;
+ mii.fState = MFS_DEFAULT;
+
+ if ( !::SetMenuItemInfo(hmenu, id, FALSE, &mii) )
+ {
+ wxLogLastError(wxT("SetMenuItemInfo"));
+ }
+#endif // !__WXWINCE__
+}
+
+// make the given menu item owner-drawn
+void SetOwnerDrawnMenuItem(HMENU WXUNUSED_IN_WINCE(hmenu),
+ UINT WXUNUSED_IN_WINCE(id),
+ ULONG_PTR WXUNUSED_IN_WINCE(data),
+ BOOL WXUNUSED_IN_WINCE(byPositon = FALSE))
+{
+#ifndef __WXWINCE__
+ MENUITEMINFO mii;
+ wxZeroMemory(mii);
+ mii.cbSize = sizeof(MENUITEMINFO);
+ mii.fMask = MIIM_FTYPE | MIIM_DATA;
+ mii.fType = MFT_OWNERDRAW;
+ mii.dwItemData = data;
+
+ if ( reinterpret_cast<wxMenuItem*>(data)->IsSeparator() )
+ mii.fType |= MFT_SEPARATOR;
+
+ if ( !::SetMenuItemInfo(hmenu, id, byPositon, &mii) )
+ {
+ wxLogLastError(wxT("SetMenuItemInfo"));
+ }
+#endif // !__WXWINCE__
+}
+
+#ifdef __WXWINCE__
+UINT GetMenuState(HMENU hMenu, UINT id, UINT flags)
+{
+ MENUITEMINFO info;
+ wxZeroMemory(info);
+ info.cbSize = sizeof(info);
+ info.fMask = MIIM_STATE;
+ // MF_BYCOMMAND is zero so test MF_BYPOSITION
+ if ( !::GetMenuItemInfo(hMenu, id, flags & MF_BYPOSITION ? TRUE : FALSE , & info) )
+ {
+ wxLogLastError(wxT("GetMenuItemInfo"));
+ }
+ return info.fState;
+}
+#endif // __WXWINCE__
+
+inline bool IsGreaterThanStdSize(const wxBitmap& bmp)
+{
+ return bmp.GetWidth() > ::GetSystemMetrics(SM_CXMENUCHECK) ||
+ bmp.GetHeight() > ::GetSystemMetrics(SM_CYMENUCHECK);
+}