]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/win32/BCMenu.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / win32 / BCMenu.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it 
9 // under the terms of the GNU General Public License as published by the Free 
10 // Software Foundation; either version 2 of the License, or (at your option) 
11 // any later version.
12 // 
13 // This program is distributed in the hope that it will be useful, but WITHOUT 
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16 // more details.
17 // 
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc., 
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25
26 //#####DESCRIPTIONBEGIN####                                             
27 //
28 //*************************************************************************
29 // BCMenu.cpp : implementation file
30 // Version : 2.63
31 // Date : December 2, 1999
32 // Author : Brent Corkum
33 // Email :  corkum@rocscience.com
34 // Latest Version : http://www.rocscience.com/~corkum/BCMenu.html
35 // 
36 // Bug Fixes and portions of code supplied by:
37 //
38 // Ben Ashley,Girish Bharadwaj,Jean-Edouard Lachand-Robert,
39 // Robert Edward Caldecott,Kenny Goers,Leonardo Zide,
40 // Stefan Kuhr,Reiner Jung,Martin Vladic,Kim Yoo Chul,
41 // Oz Solomonovich
42 //
43 // You are free to use/modify this code but leave this header intact.
44 // This class is public domain so you are free to use it any of
45 // your applications (Freeware,Shareware,Commercial). All I ask is
46 // that you let me know so that if you have a real winner I can
47 // brag to my buddies that some of my code is in your app. I also
48 // wouldn't mind if you sent me a copy of your application since I
49 // like to play with new stuff.
50 //*************************************************************************
51 //####DESCRIPTIONEND####
52 //==========================================================================
53
54 #include "stdafx.h"        // Standard windows header file
55 #include "BCMenu.h"        // BCMenu class declaration
56 #include <afxpriv.h>       //SK: makes A2W and other spiffy AFX macros work
57
58 #ifdef _DEBUG
59 #define new DEBUG_NEW
60 #undef THIS_FILE
61 static char THIS_FILE[] = __FILE__;
62 #endif
63
64 #define GAP 1
65 #ifndef OBM_CHECK
66 #define OBM_CHECK 32760 // from winuser.h
67 #endif
68
69 #if _MFC_VER <0x400
70 #error This code does not work on Versions of MFC prior to 4.0
71 #endif
72
73 static CPINFO CPInfo;
74
75 enum Win32Type{
76 Win32s,
77 Windoze95,
78 WinNT3,
79 WinNT4orHigher
80 };
81
82
83 Win32Type IsShellType()
84 {
85   Win32Type  ShellType;
86   DWORD winVer;
87   OSVERSIONINFO *osvi;
88
89   winVer=GetVersion();
90   if(winVer<0x80000000){/*NT */
91     ShellType=WinNT3;
92     osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
93     if (osvi!=NULL){
94       memset(osvi,0,sizeof(OSVERSIONINFO));
95       osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
96       GetVersionEx(osvi);
97       if (osvi->dwMajorVersion>=4L)
98         ShellType=WinNT4orHigher;//yup, it is NT 4 or higher!
99       free(osvi);
100     }
101   }
102   else if  (LOBYTE(LOWORD(winVer))<4)
103     ShellType=Win32s;/*Win32s*/
104   else
105     ShellType=Windoze95;/*Windoze95*/
106   return ShellType;
107 }
108
109 static Win32Type g_Shell=IsShellType();
110
111 void BCMenuData::SetAnsiString(LPCSTR szAnsiString)
112 {
113 USES_CONVERSION;
114 SetWideString(A2W(szAnsiString));  //SK:  see MFC Tech Note 059
115 }
116
117 CString BCMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
118 //depending on the MFC-Version we are using
119 {
120 CString strText;
121 if (m_szMenuText)
122     {
123 #ifdef UNICODE
124     strText = m_szMenuText;
125 #else
126 USES_CONVERSION;
127     strText=W2A(m_szMenuText);     //SK:  see MFC Tech Note 059
128 #endif    
129     }
130 return strText;
131 }
132
133 CTypedPtrArray<CPtrArray, HMENU> BCMenu::m_AllSubMenus;  // Stores list of all sub-menus
134
135 /*
136  
137 ===============================================================================
138   BCMenu::BCMenu()
139   TCMeny::~BCMenu()
140   -----------------
141
142   Constructor and Destructor.
143  
144 ===============================================================================
145 */
146
147 BCMenu::BCMenu()
148 {
149   m_bDynIcons = FALSE;     // O.S. - no dynamic icons by default
150   disable_old_style=FALSE;
151   m_iconX = 16;            // Icon sizes default to 16 x 16
152   m_iconY = 15;            // ...
153   m_selectcheck = -1;
154   m_unselectcheck = -1;
155   checkmaps=NULL;
156   checkmapsshare=FALSE;
157   // set the color used for the transparent background in all bitmaps
158   m_bitmapBackground=RGB(192,192,192); //gray
159   m_bitmapBackgroundFlag=FALSE;
160   GetCPInfo(CP_ACP,&CPInfo);
161 }
162
163
164 BCMenu::~BCMenu()
165 {
166   DestroyMenu();
167 }
168
169 BOOL BCMenu::IsNewShell ()
170 {
171 return (Windoze95==g_Shell || WinNT4orHigher==g_Shell);
172 }
173
174
175 BCMenuData::~BCMenuData()
176 {
177   if(bitmap)
178     delete(bitmap);
179
180   delete[] m_szMenuText; //Need not check for NULL because ANSI X3J16 allows "delete NULL"
181 }
182
183
184 void BCMenuData::SetWideString(const wchar_t *szWideString)
185 {
186 delete[] m_szMenuText;//Need not check for NULL because ANSI X3J16 allows "delete NULL"
187
188 if (szWideString)
189     {
190     m_szMenuText = new wchar_t[sizeof(wchar_t)*(wcslen(szWideString)+1)];
191     if (m_szMenuText)
192         wcscpy(m_szMenuText,szWideString);
193     }
194 else
195     m_szMenuText=NULL;//set to NULL so we need not bother about dangling non-NULL Ptrs
196 }
197
198 BOOL BCMenu::IsMenu(CMenu *submenu)
199 {
200   int m;
201   int numSubMenus = m_AllSubMenus.GetUpperBound();
202   for(m=0;m<=numSubMenus;++m){
203     if(submenu->m_hMenu==m_AllSubMenus[m])return(TRUE);
204   }
205   return(FALSE);
206 }
207
208 BOOL BCMenu::IsMenu(HMENU submenu)
209 {
210   int m;
211   int numSubMenus = m_AllSubMenus.GetUpperBound();
212   for(m=0;m<=numSubMenus;++m){
213     if(submenu==m_AllSubMenus[m])return(TRUE);
214   }
215   return(FALSE);
216 }
217
218 BOOL BCMenu::DestroyMenu()
219 {
220   // Destroy Sub menus:
221   int m,n;
222   int numAllSubMenus = m_AllSubMenus.GetUpperBound();
223   for(n = numAllSubMenus; n>= 0; n--){
224     if(m_AllSubMenus[n]==this->m_hMenu)m_AllSubMenus.RemoveAt(n);
225   }
226   int numSubMenus = m_SubMenus.GetUpperBound();
227   for(m = numSubMenus; m >= 0; m--){
228     numAllSubMenus = m_AllSubMenus.GetUpperBound();
229     for(n = numAllSubMenus; n>= 0; n--){
230       if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
231     }
232     delete((BCMenu *)FromHandle(m_SubMenus[m]));
233   }
234   m_SubMenus.RemoveAll();
235   // Destroy menu data
236   int numItems = m_MenuList.GetUpperBound();
237   for(m = 0; m <= numItems; m++)delete(m_MenuList[m]);
238   m_MenuList.RemoveAll();
239   if(checkmaps&&!checkmapsshare){
240     delete checkmaps;
241     checkmaps=NULL;
242   }
243   // Call base-class implementation last:
244   return(CMenu::DestroyMenu());
245 };
246
247
248 ///////////////////////////////////////////////////////////////////////////
249 //
250 // BCMenu message handlers
251
252
253 /*
254 ==========================================================================
255 void BCMenu::DrawItem(LPDRAWITEMSTRUCT)
256 ---------------------------------------
257
258 Called by the framework when a particular item needs to be drawn.  We
259 overide this to draw the menu item in a custom-fashion, including icons
260 and the 3D rectangle bar.
261 ==========================================================================
262 */
263
264
265 void BCMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
266 {
267   ASSERT(lpDIS != NULL);
268   CDC* pDC = CDC::FromHandle(lpDIS->hDC);
269   CRect rect;
270   UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
271   if(state & MF_SEPARATOR){
272     rect.CopyRect(&lpDIS->rcItem);
273     rect.top+=rect.Height()>>1;
274     pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
275   }
276   else{
277     CRect rect2;
278     BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
279     BOOL checkflag=FALSE;
280     COLORREF crText = GetSysColor(COLOR_MENUTEXT);
281     COLORREF m_clrBack=GetSysColor(COLOR_MENU);
282     CBrush m_brBackground,m_brSelect;
283     CPen m_penBack;
284     int x0,y0,dy;
285     int nIconNormal=-1,xoffset=-1;
286     CImageList *bitmap=NULL;
287     CFont m_fontMenu;
288     LOGFONT m_lf;
289
290     // set some colors and the font
291     m_penBack.CreatePen (PS_SOLID,0,GetSysColor(COLOR_MENU));
292     m_brBackground.CreateSolidBrush(GetSysColor(COLOR_MENU));
293     m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
294     ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
295     NONCLIENTMETRICS nm;
296     nm.cbSize = sizeof (NONCLIENTMETRICS);
297     VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
298     m_lf =  nm.lfMenuFont;
299     m_fontMenu.CreateFontIndirect (&m_lf);
300
301     // draw the colored rectangle portion
302   
303     rect.CopyRect(&lpDIS->rcItem);
304     rect2=rect;
305  
306     // draw the up/down/focused/disabled state
307
308     UINT state = lpDIS->itemState;
309     CString strText;
310     LOGFONT lf;
311     lf = m_lf;
312
313     CFont dispFont;
314     CFont *pFont=NULL;
315       
316     if(lpDIS->itemData != NULL){
317       nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
318       xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
319       bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
320       strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
321     
322       if(state&ODS_CHECKED && nIconNormal<0){
323         if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
324         else if(m_unselectcheck>0) checkflag=TRUE;
325       }
326       else if(nIconNormal != -1){
327         standardflag=TRUE;
328         if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
329         else if(state&ODS_GRAYED) disableflag=TRUE;
330       }
331     }
332     else{
333       strText.Empty();
334     }
335
336     if(state&ODS_SELECTED){ // draw the down edges
337
338       CPen *pOldPen = pDC->SelectObject (&m_penBack);
339
340       // You need only Text highlight and thats what you get
341      
342       if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
343         rect2.SetRect(rect.left+m_iconX+4+GAP,rect.top,rect.right,rect.bottom);
344       pDC->FillRect (rect2,&m_brSelect);
345
346       pDC->SelectObject (pOldPen);
347       if((HFONT)dispFont != NULL)dispFont.DeleteObject ();
348       dispFont.CreateFontIndirect (&lf);
349       crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
350     }
351     else {
352       CPen *pOldPen = pDC->SelectObject (&m_penBack);
353       pDC->FillRect (rect,&m_brBackground);
354       pDC->SelectObject (pOldPen);
355
356       // draw the up edges
357
358       pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
359       if ((HFONT)dispFont != NULL) dispFont.DeleteObject ();
360       dispFont.CreateFontIndirect (&lf); //Normal
361     }
362
363     // draw the text if there is any
364     //We have to paint the text only if the image is nonexistant
365
366     dy = (rect.Height()-4-m_iconY)/2;
367     dy = dy<0 ? 0 : dy;
368
369     if(checkflag||standardflag||selectedflag||disableflag){
370       rect2.SetRect(rect.left+1,rect.top+1+dy,rect.left+m_iconX+3,
371                     rect.top+m_iconY+3+dy);
372       pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
373       if(checkflag && checkmaps){
374         pDC->FillRect (rect2,&m_brBackground);
375         rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
376                       rect.top+m_iconY+4+dy);
377         
378                                 pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
379         CPoint ptImage(rect.left+2,rect.top+2+dy);
380        
381         if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
382         else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
383       }
384       else if(disableflag){
385         if(!selectedflag){
386           CBitmap bitmapstandard;
387           GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
388           rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
389                         rect.top+m_iconY+4+dy);
390           pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
391           if(disable_old_style)
392             DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
393                      (HBITMAP)(bitmapstandard),0,0);
394           else
395             DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
396                          bitmapstandard,0,0);
397           bitmapstandard.DeleteObject();
398         }
399       }
400       else if(selectedflag){
401         pDC->FillRect (rect2,&m_brBackground);
402         rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
403                       rect.top+m_iconY+4+dy);
404         if (IsNewShell()){
405           if(state&ODS_CHECKED)
406             pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
407                             GetSysColor(COLOR_3DHILIGHT));
408           else
409             pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),
410                             GetSysColor(COLOR_3DSHADOW));
411         }
412         CPoint ptImage(rect.left+2,rect.top+2+dy);
413         if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
414       }
415       else{
416         if(state&ODS_CHECKED){
417           CBrush brush;
418           COLORREF col =GetSysColor(COLOR_3DLIGHT);
419           brush.CreateSolidBrush(col);
420           pDC->FillRect(rect2,&brush);
421           brush.DeleteObject();
422           rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
423                         rect.top+m_iconY+4+dy);
424           if (IsNewShell())
425             pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
426                             GetSysColor(COLOR_3DHILIGHT));
427         }
428         else{
429           pDC->FillRect (rect2,&m_brBackground);
430           rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
431                         rect.top+m_iconY+4+dy);
432           pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
433         }
434         CPoint ptImage(rect.left+2,rect.top+2+dy);
435         if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
436       }
437     }
438     if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
439       rect2.SetRect(rect.left+1,rect.top+2+dy,rect.left+m_iconX+1,
440                     rect.top+m_iconY+2+dy);
441       CMenuItemInfo info;
442       info.fMask = MIIM_CHECKMARKS;
443       ::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
444                       MF_BYCOMMAND, &info);
445       if(state&ODS_CHECKED || info.hbmpUnchecked) {
446         Draw3DCheckmark(pDC, rect2, state&ODS_SELECTED,
447                         state&ODS_CHECKED ? info.hbmpChecked :
448                         info.hbmpUnchecked);
449       }
450     }
451
452     //This is needed always so that we can have the space for check marks
453
454     x0=rect.left;y0=rect.top;
455     rect.left = rect.left + m_iconX + 8 + GAP; 
456
457     if(!strText.IsEmpty()){
458
459       CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
460
461       //   Find tabs
462
463       CString leftStr,rightStr;
464       leftStr.Empty();rightStr.Empty();
465       int tablocr=strText.ReverseFind(_T('\t'));
466       if(tablocr!=-1){
467         rightStr=strText.Mid(tablocr+1);
468         leftStr=strText.Left(strText.Find(_T('\t')));
469         rectt.right-=m_iconX;
470       }
471       else leftStr=strText;
472
473       int iOldMode = pDC->GetBkMode();
474       pDC->SetBkMode( TRANSPARENT);
475
476       // Draw the text in the correct colour:
477
478       UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
479       UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
480       if(!(lpDIS->itemState & ODS_GRAYED)){
481         pDC->SetTextColor(crText);
482         pDC->DrawText (leftStr,rectt,nFormat);
483         if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
484       }
485       else{
486
487         // Draw the disabled text
488         if(!(state & ODS_SELECTED)){
489           RECT offset = *rectt;
490           offset.left+=1;
491           offset.right+=1;
492           offset.top+=1;
493           offset.bottom+=1;
494           pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
495           pDC->DrawText(leftStr,&offset, nFormat);
496           if(tablocr!=-1) pDC->DrawText (rightStr,&offset,nFormatr);
497           pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
498           pDC->DrawText(leftStr,rectt, nFormat);
499           if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
500         }
501         else{
502         // And the standard Grey text:
503           pDC->SetTextColor(m_clrBack);
504           pDC->DrawText(leftStr,rectt, nFormat);
505           if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
506         }
507       }
508       pFont = pDC->SelectObject (&dispFont);
509       pDC->SetBkMode( iOldMode );
510       pDC->SelectObject (pFont); //set it to the old font
511     }
512
513     m_penBack.DeleteObject();
514     m_brBackground.DeleteObject();
515     m_fontMenu.DeleteObject();
516     m_brSelect.DeleteObject();
517     dispFont.DeleteObject ();
518   }
519 }
520
521 BOOL BCMenu::GetBitmapFromImageList(CDC* pDC,CImageList *imglist,int nIndex,CBitmap &bmp)
522 {
523         HICON hIcon = imglist->ExtractIcon(nIndex);
524         CDC dc;
525         dc.CreateCompatibleDC(pDC);
526         bmp.CreateCompatibleBitmap(pDC,m_iconX,m_iconY);
527         CBitmap* pOldBmp = dc.SelectObject(&bmp);
528         CBrush brush ;
529         brush.CreateSolidBrush(GetSysColor(COLOR_MENU));
530         ::DrawIconEx(
531                         dc.GetSafeHdc(),
532                         0,
533                         0,
534                         hIcon,
535                         m_iconX,
536                         m_iconY,
537                         0,
538                         (HBRUSH)brush,
539                         DI_NORMAL
540         );
541         dc.SelectObject( pOldBmp );
542         dc.DeleteDC();
543         // the icon is not longer needed
544         DestroyIcon(hIcon);
545         return(TRUE);
546 }
547
548 /*
549 ==========================================================================
550 void BCMenu::MeasureItem(LPMEASUREITEMSTRUCT)
551 ---------------------------------------------
552
553 Called by the framework when it wants to know what the width and height
554 of our item will be.  To accomplish this we provide the width of the
555 icon plus the width of the menu text, and then the height of the icon.
556  
557 ==========================================================================
558 */
559
560 void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
561 {
562   UINT state = (((BCMenuData*)(lpMIS->itemData))->nFlags);
563   if(state & MF_SEPARATOR){
564     lpMIS->itemWidth = 0;
565     lpMIS->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
566   }
567   else{
568     CFont m_fontMenu;
569     LOGFONT m_lf;
570     ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
571     NONCLIENTMETRICS nm;
572     nm.cbSize = sizeof (NONCLIENTMETRICS);
573     VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
574            nm.cbSize,&nm,0)); 
575     m_lf =  nm.lfMenuFont;
576     m_fontMenu.CreateFontIndirect (&m_lf);
577
578     // Obtain the width of the text:
579     CWnd *pWnd = AfxGetMainWnd();            // Get main window
580     CDC *pDC = pWnd->GetDC();              // Get device context
581     CFont* pFont=NULL;    // Select menu font in...
582     
583     if (IsNewShell())
584         pFont = pDC->SelectObject (&m_fontMenu);// Select menu font in...
585         
586     //Get pointer to text SK
587     const wchar_t *lpstrText = ((BCMenuData*)(lpMIS->itemData))->GetWideString();//SK: we use const to prevent misuse
588     
589         
590     SIZE size;
591
592     if (Win32s!=g_Shell)
593       VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,
594              wcslen(lpstrText),&size)); //SK should also work on 95
595 #ifndef UNICODE //can't be UNICODE for Win32s
596     else{//it's Win32suckx
597       RECT rect;
598       rect.left=rect.top=0;
599       size.cy=DrawText(pDC->m_hDC,(LPCTSTR)lpstrText,
600                        wcslen(lpstrText),&rect,
601                        DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT);
602       //+3 makes at least three pixels space to the menu border
603       size.cx=rect.right-rect.left+3;
604       size.cx += 3*(size.cx/wcslen(lpstrText));
605     }
606 #endif    
607
608     CSize t = CSize(size);
609     if(IsNewShell())
610       pDC->SelectObject (pFont);  // Select old font in
611     AfxGetMainWnd()->ReleaseDC(pDC);  // Release the DC
612
613     // Set width and height:
614
615     lpMIS->itemWidth = m_iconX + t.cx + m_iconX + GAP;
616     int temp = GetSystemMetrics(SM_CYMENU);
617     lpMIS->itemHeight = temp>m_iconY+4 ? temp : m_iconY+4;
618     m_fontMenu.DeleteObject();
619   }
620 }
621
622 void BCMenu::SetIconSize (int width, int height)
623 {
624   m_iconX = width;
625   m_iconY = height;
626 }
627
628 BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
629                            int nIconNormal)
630 {
631 USES_CONVERSION;
632 return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal);//SK: See MFC Tech Note 059
633 }
634
635
636 BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
637                            int nIconNormal)
638 {
639   // Add the MF_OWNERDRAW flag if not specified:
640   if(!nID){
641     if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
642     else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
643   }
644   else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
645
646   if(nFlags & MF_POPUP){
647                 m_AllSubMenus.Add((HMENU)nID);
648                 m_SubMenus.Add((HMENU)nID);
649         }
650
651   BCMenuData *mdata = new BCMenuData;
652   m_MenuList.Add(mdata);
653   mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
654   
655   mdata->menuIconNormal = nIconNormal;
656   mdata->xoffset=-1;
657   if(nIconNormal>=0){
658     mdata->xoffset=0;
659     LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
660     if(mdata->bitmap)mdata->bitmap->DeleteImageList();
661     else mdata->bitmap=new(CImageList);
662     mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
663     if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
664                         mdata->bitmap->DeleteImageList();
665                         delete mdata->bitmap;
666                         mdata->bitmap=NULL;
667       mdata->menuIconNormal = nIconNormal = -1;
668       mdata->xoffset = -1;
669     }
670   }
671   mdata->nFlags = nFlags;
672   mdata->nID = nID;
673   return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
674 }
675
676 BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
677                            CImageList *il,int xoffset)
678 {
679 USES_CONVERSION;
680 return AppendODMenuW(A2W(lpstrText),nFlags,nID,il,xoffset);
681 }
682
683 BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
684                            CImageList *il,int xoffset)
685 {
686   // Add the MF_OWNERDRAW flag if not specified:
687   if(!nID){
688     if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
689     else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
690   }
691   else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
692
693   if(nFlags & MF_POPUP){
694                 m_AllSubMenus.Add((HMENU)nID);
695                 m_SubMenus.Add((HMENU)nID);
696         }
697
698   BCMenuData *mdata = new BCMenuData;
699   m_MenuList.Add(mdata);
700   mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
701   
702   if(il){
703     mdata->menuIconNormal = 0;
704     mdata->xoffset=0;
705     if(mdata->bitmap)mdata->bitmap->DeleteImageList();
706     else mdata->bitmap=new(CImageList);
707     ImageListDuplicate(il,xoffset,mdata->bitmap);
708   }
709   else{
710     mdata->menuIconNormal = -1;
711     mdata->xoffset = -1;
712   }
713   mdata->nFlags = nFlags;
714   mdata->nID = nID;
715   return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
716 }
717
718 BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
719                            int nIconNormal)
720 {
721 USES_CONVERSION;
722 return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,nIconNormal);
723 }
724
725
726 BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
727                            int nIconNormal)
728 {
729   if(!(nFlags & MF_BYPOSITION)){
730                 int iPosition =0;
731                 BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
732     if(pMenu){
733       return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,nIconNormal));
734     }
735     else return(FALSE);
736   }
737
738   if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
739   else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
740
741   if(nFlags & MF_POPUP){
742                 m_AllSubMenus.Add((HMENU)nID);
743                 m_SubMenus.InsertAt(nPosition,(HMENU)nID);
744         }
745
746   BCMenuData *mdata = new BCMenuData;
747   m_MenuList.InsertAt(nPosition,mdata);
748   mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
749   
750   mdata->menuIconNormal = nIconNormal;
751   mdata->xoffset=-1;
752   if(nIconNormal>=0){
753     mdata->xoffset=0;
754     LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
755     if(mdata->bitmap)mdata->bitmap->DeleteImageList();
756     else mdata->bitmap=new(CImageList);
757     mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
758     if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
759                         mdata->bitmap->DeleteImageList();
760                         delete mdata->bitmap;
761                         mdata->bitmap=NULL;
762       mdata->menuIconNormal = nIconNormal = -1;
763       mdata->xoffset = -1;
764     }
765   }
766   mdata->nFlags = nFlags;
767   mdata->nID = nID;
768   return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
769 }
770
771 BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
772                            CImageList *il,int xoffset)
773 {
774 USES_CONVERSION;
775 return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,il,xoffset);
776 }
777
778 BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
779                            CImageList *il,int xoffset)
780 {
781   if(!(nFlags & MF_BYPOSITION)){
782                 int iPosition =0;
783                 BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
784     if(pMenu){
785       return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,il,xoffset));
786     }
787     else return(FALSE);
788   }
789
790   if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
791   else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
792
793   if(nFlags & MF_POPUP){
794                 m_AllSubMenus.Add((HMENU)nID);
795                 m_SubMenus.InsertAt(nPosition,(HMENU)nID);
796         }
797
798   BCMenuData *mdata = new BCMenuData;
799   m_MenuList.InsertAt(nPosition,mdata);
800   mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
801
802   if(il){
803     mdata->menuIconNormal = 0;
804     mdata->xoffset=0;
805     if(mdata->bitmap)mdata->bitmap->DeleteImageList();
806     else mdata->bitmap=new(CImageList);
807     ImageListDuplicate(il,xoffset,mdata->bitmap);
808   }
809   else{
810     mdata->menuIconNormal = -1;
811     mdata->xoffset = -1;
812   }
813   mdata->nFlags = nFlags;
814   mdata->nID = nID;
815   return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
816 }
817
818 BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal)
819 {
820 USES_CONVERSION;
821 return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal);//SK: see MFC Tech Note 059
822 }
823
824 BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal)
825 {
826   int nLoc;
827   BCMenuData *mdata;
828
829   // Find the old BCMenuData structure:
830   BCMenu *psubmenu = FindMenuOption(nID,nLoc);
831   if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
832   else{
833   // Create a new BCMenuData structure:
834     mdata = new BCMenuData;
835     m_MenuList.Add(mdata);
836   }
837
838   ASSERT(mdata);
839   if(lpstrText)
840      mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
841   mdata->menuIconNormal = nIconNormal;
842   mdata->xoffset=-1;
843   if(nIconNormal>=0){
844     mdata->xoffset=0;
845     LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
846     if(mdata->bitmap)mdata->bitmap->DeleteImageList();
847     else mdata->bitmap=new CImageList;
848     mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
849     if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
850                         mdata->bitmap->DeleteImageList();
851                         delete mdata->bitmap;
852                         mdata->bitmap=NULL;
853       mdata->menuIconNormal = nIconNormal = -1;
854       mdata->xoffset = -1;
855     }
856   }
857   mdata->nFlags = MF_BYCOMMAND | MF_OWNERDRAW;
858   mdata->nID = nID;
859   return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
860 }
861
862 BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CImageList *il,int xoffset)
863 {
864 USES_CONVERSION;
865 return ModifyODMenuW(A2W(lpstrText),nID,il,xoffset);
866 }
867
868 BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CImageList *il,int xoffset)
869 {
870   int nLoc;
871   BCMenuData *mdata;
872
873   // Find the old BCMenuData structure:
874   BCMenu *psubmenu = FindMenuOption(nID,nLoc);
875   if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
876   else{
877   // Create a new BCMenuData structure:
878     mdata = new BCMenuData;
879     m_MenuList.Add(mdata);
880   }
881
882   ASSERT(mdata);
883   if(lpstrText)
884      mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
885   if(il){
886     mdata->menuIconNormal = 0;
887     mdata->xoffset=0;
888     if(mdata->bitmap)mdata->bitmap->DeleteImageList();
889     else mdata->bitmap=new(CImageList);
890     ImageListDuplicate(il,xoffset,mdata->bitmap);
891   }
892   else{
893     mdata->menuIconNormal = -1;
894     mdata->xoffset = -1;
895   }
896   mdata->nFlags = MF_BYCOMMAND | MF_OWNERDRAW;
897   mdata->nID = nID;
898   return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
899 }
900
901 BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CBitmap *bmp)
902 {
903 USES_CONVERSION;
904 return ModifyODMenuW(A2W(lpstrText),nID,bmp);
905 }
906
907 BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CBitmap *bmp)
908 {
909   if(bmp){
910         CImageList temp;
911     temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
912     if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
913     else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
914     return ModifyODMenuW(lpstrText,nID,&temp,0);
915   }
916   return ModifyODMenuW(lpstrText,nID,NULL,0);
917 }
918
919
920 BOOL BCMenu::ModifyODMenuA(const char *lpstrText,const char *OptionText,
921                            int nIconNormal)
922 {
923 USES_CONVERSION;
924 return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal);//SK: see MFC  Tech Note 059
925 }
926
927 BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,
928                            int nIconNormal)
929 {
930   BCMenuData *mdata;
931
932   // Find the old BCMenuData structure:
933   CString junk=OptionText;
934   mdata=FindMenuOption(OptionText);
935   if(mdata){
936     if(lpstrText)
937         mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
938     mdata->menuIconNormal = nIconNormal;
939     mdata->xoffset=-1;
940     if(nIconNormal>=0){
941       mdata->xoffset=0;
942       if(mdata->bitmap)mdata->bitmap->DeleteImageList();
943       else mdata->bitmap=new(CImageList);
944       mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
945             if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
946                                 mdata->bitmap->DeleteImageList();
947                                 delete mdata->bitmap;
948                                 mdata->bitmap=NULL;
949                                 mdata->menuIconNormal = nIconNormal = -1;
950                                 mdata->xoffset = -1;
951                         }
952     }
953     return(TRUE);
954   }
955   return(FALSE);
956 }
957
958 BCMenuData *BCMenu::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
959 {
960   BCMenuData *mdata;
961
962   mdata = new BCMenuData;
963   mdata->menuIconNormal = -1;
964   mdata->xoffset=-1;
965   #ifdef UNICODE
966   mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
967   #else
968   mdata->SetAnsiString(string);
969   #endif
970   mdata->nFlags = nFlags;
971   mdata->nID = nID;
972
973   if(nFlags & MF_POPUP)m_AllSubMenus.Add((HMENU)nID);
974   
975   if (nFlags&MF_OWNERDRAW){
976     ASSERT(!(nFlags&MF_STRING));
977     ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
978   }
979   else if (nFlags&MF_STRING){
980     ASSERT(!(nFlags&MF_OWNERDRAW));
981     ModifyMenu(pos,nFlags,nID,mdata->GetString());
982   }
983   else{
984     ASSERT(nFlags&MF_SEPARATOR);
985     ModifyMenu(pos,nFlags,nID);
986   }
987
988   return(mdata);
989 };
990
991 BOOL BCMenu::LoadToolbars(const UINT *arID,int n)
992 {
993   ASSERT(arID);
994   BOOL returnflag=TRUE;
995   for(int i=0;i<n;++i){
996     if(!LoadToolbar(arID[i]))returnflag=FALSE;
997   }
998   return(returnflag);
999 }
1000
1001 BOOL BCMenu::LoadToolbar(UINT nToolBar)
1002 {
1003   UINT nID;
1004   BOOL returnflag=FALSE;
1005   CToolBar bar;
1006
1007   bar.Create(AfxGetMainWnd());
1008   if(bar.LoadToolBar(nToolBar)){
1009     for(int i=0;i<bar.GetCount();++i){
1010       nID = bar.GetItemID(i); 
1011       if(nID && GetMenuState(nID, MF_BYCOMMAND)
1012         !=0xFFFFFFFF){
1013         ModifyODMenu(NULL,nID,nToolBar);
1014       }
1015     }
1016     returnflag=TRUE;
1017   }
1018   return(returnflag);
1019 }
1020
1021 BOOL BCMenu::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
1022 {
1023   int xset,offset;
1024   UINT nStyle;
1025   BOOL returnflag=FALSE;
1026   CToolBar bar;
1027
1028   bar.Create(AfxGetMainWnd());
1029   if(bar.LoadToolBar(nToolBar)){
1030     offset=bar.CommandToIndex(nID);
1031     if(offset>=0){
1032       bar.GetButtonInfo(offset,nID,nStyle,xset);
1033       if(xset>0)xoffset=xset;
1034       returnflag=TRUE;
1035     }
1036   }
1037   return(returnflag);
1038 }
1039
1040 // O.S.
1041 BCMenuData *BCMenu::FindMenuItem(UINT nID)
1042 {
1043   BCMenuData *pData = NULL;
1044   int i;
1045
1046   for(i = 0; i <= m_MenuList.GetUpperBound(); i++){
1047     if (m_MenuList[i]->nID == nID){
1048       pData = m_MenuList[i];
1049       break;
1050     }
1051   }
1052   if (!pData){
1053     int loc;
1054     BCMenu *pMenu = FindMenuOption(nID, loc);
1055     ASSERT(pMenu != this);
1056     if (loc >= 0){
1057       return pMenu->FindMenuItem(nID);
1058     }
1059   }
1060   return pData;
1061 }
1062
1063 BCMenu *BCMenu::FindMenuOption(int nId,int& nLoc)
1064 {
1065   int i;
1066   BCMenu *psubmenu,*pgoodmenu;
1067
1068   for(i=0;i<(int)(GetMenuItemCount());++i){
1069 #ifdef _CPPRTTI 
1070     psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
1071 #else
1072     psubmenu=(BCMenu *)GetSubMenu(i);
1073 #endif
1074     if(psubmenu){
1075       pgoodmenu=psubmenu->FindMenuOption(nId,nLoc);
1076       if(pgoodmenu)return(pgoodmenu);
1077     }
1078     else if(nId==(int)GetMenuItemID(i)){
1079       nLoc=i;
1080       return(this);
1081     }
1082   }
1083   nLoc = -1;
1084   return(NULL);
1085 }
1086
1087 BCMenuData *BCMenu::FindMenuOption(wchar_t *lpstrText)
1088 {
1089   int i,j;
1090   BCMenu *psubmenu;
1091   BCMenuData *pmenulist;
1092
1093   for(i=0;i<(int)(GetMenuItemCount());++i){
1094 #ifdef _CPPRTTI 
1095     psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
1096 #else
1097     psubmenu=(BCMenu *)GetSubMenu(i);
1098 #endif
1099     if(psubmenu){
1100       pmenulist=psubmenu->FindMenuOption(lpstrText);
1101       if(pmenulist)return(pmenulist);
1102     }
1103     else{
1104       const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
1105       for(j=0;j<=m_MenuList.GetUpperBound();++j){     
1106         szWide = m_MenuList[j]->GetWideString ();
1107         if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
1108           return(m_MenuList[j]);
1109       }
1110     }
1111   }
1112   return(NULL);
1113 }
1114
1115
1116 BOOL BCMenu::LoadMenu(int nResource)
1117 {
1118   return(BCMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
1119 };
1120
1121 BOOL BCMenu::LoadMenu(LPCTSTR lpszResourceName)
1122 {
1123   TRACE(_T(
1124     "IMPORTANT:Use BCMenu::DestroyMenu to destroy Loaded Menu's\n"));
1125   ASSERT_VALID(this);
1126   ASSERT(lpszResourceName != NULL);
1127
1128   // Find the Menu Resource:
1129   HINSTANCE m_hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
1130   HRSRC hRsrc = ::FindResource(m_hInst,lpszResourceName,RT_MENU);
1131   if(hRsrc == NULL)return FALSE;
1132
1133   // Load the Menu Resource:
1134
1135   HGLOBAL hGlobal = LoadResource(m_hInst, hRsrc);
1136   if(hGlobal == NULL)return FALSE;
1137
1138   // Attempt to create us as a menu...
1139
1140   if(!CMenu::CreateMenu())return FALSE;
1141
1142   // Get Item template Header, and calculate offset of MENUITEMTEMPLATES
1143
1144   MENUITEMTEMPLATEHEADER *pTpHdr=
1145     (MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
1146   BYTE* pTp=(BYTE*)pTpHdr + 
1147     (sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);
1148
1149
1150   // Variables needed during processing of Menu Item Templates:
1151
1152   int j=0;
1153   WORD    dwFlags = 0;              // Flags of the Menu Item
1154   WORD    dwID  = 0;              // ID of the Menu Item
1155   UINT    uFlags;                  // Actual Flags.
1156   wchar_t *szCaption=NULL;
1157   int      nLen   = 0;                // Length of caption
1158   CTypedPtrArray<CPtrArray, BCMenu*>  m_Stack;    // Popup menu stack
1159   CArray<BOOL,BOOL>  m_StackEnd;    // Popup menu stack
1160   m_Stack.Add(this);                  // Add it to this...
1161   m_StackEnd.Add(FALSE);
1162
1163   do{
1164     // Obtain Flags and (if necessary), the ID...
1165     memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);// Obtain Flags
1166     if(!(dwFlags & MF_POPUP)){
1167       memcpy(&dwID, pTp, sizeof(WORD)); // Obtain ID
1168       pTp+=sizeof(WORD);
1169     }
1170     else dwID = 0;
1171
1172     uFlags = (UINT)dwFlags; // Remove MF_END from the flags that will
1173     if(uFlags & MF_END) // be passed to the Append(OD)Menu functions.
1174       uFlags -= MF_END;
1175
1176     // Obtain Caption (and length)
1177
1178     nLen = 0;
1179     szCaption=new wchar_t[wcslen((wchar_t *)pTp)+1];
1180     wcscpy(szCaption,(wchar_t *)pTp);
1181     pTp=&pTp[(wcslen((wchar_t *)pTp)+1)*sizeof(wchar_t)];//modified SK
1182     
1183     // Handle popup menus first....
1184
1185     //WideCharToMultiByte
1186     if(dwFlags & MF_POPUP){
1187       if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
1188       BCMenu* pSubMenu = new BCMenu;
1189       pSubMenu->m_unselectcheck=m_unselectcheck;
1190       pSubMenu->m_selectcheck=m_selectcheck;
1191       pSubMenu->checkmaps=checkmaps;
1192       pSubMenu->checkmapsshare=TRUE;
1193       pSubMenu->CreatePopupMenu();
1194
1195       // Append it to the top of the stack:
1196
1197       m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption,uFlags,
1198         (UINT)pSubMenu->m_hMenu, -1);
1199       m_Stack.Add(pSubMenu);
1200       m_StackEnd.Add(FALSE);
1201     }
1202     else {
1203       m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption, uFlags,
1204         dwID, -1);
1205       if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
1206       j = m_Stack.GetUpperBound();
1207       while(j>=0 && m_StackEnd.GetAt(j)){
1208         m_Stack[m_Stack.GetUpperBound()]->InsertSpaces();
1209         m_Stack.RemoveAt(j);
1210         m_StackEnd.RemoveAt(j);
1211         --j;
1212       }
1213     }
1214
1215     delete[] szCaption;
1216   }while(m_Stack.GetUpperBound() != -1);
1217
1218   for(int i=0;i<(int)GetMenuItemCount();++i){
1219     CString str=m_MenuList[i]->GetString();
1220
1221     if(GetSubMenu(i)){
1222       m_MenuList[i]->nFlags=MF_POPUP|MF_BYPOSITION;
1223       ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
1224         (UINT)GetSubMenu(i)->m_hMenu,str);
1225     }
1226     else{
1227       m_MenuList[i]->nFlags=MF_STRING|MF_BYPOSITION;
1228       ModifyMenu(i,MF_STRING|MF_BYPOSITION,m_MenuList[i]->nID,str);
1229     }
1230   }
1231   
1232   return(TRUE);
1233 }
1234
1235 void BCMenu::InsertSpaces(void)
1236 {
1237   int i,j,numitems,maxlength;
1238   CString string,newstring;
1239   CSize t;
1240   CFont m_fontMenu;
1241   LOGFONT m_lf;
1242
1243   ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
1244   NONCLIENTMETRICS nm;
1245   nm.cbSize = sizeof (NONCLIENTMETRICS);
1246   VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
1247   m_lf =  nm.lfMenuFont;
1248   m_fontMenu.CreateFontIndirect (&m_lf);
1249
1250   CWnd *pWnd = AfxGetMainWnd();  
1251   CDC *pDC = pWnd->GetDC();
1252   CFont* pFont = pDC->SelectObject (&m_fontMenu);
1253   
1254   numitems=GetMenuItemCount();
1255   maxlength = -1;
1256   for(i=0;i<numitems;++i){
1257     string=m_MenuList[i]->GetString();
1258     j=string.Find((char)9);
1259     newstring.Empty();
1260     if(j!=-1)newstring=string.Left(j);
1261     else newstring=string;
1262     newstring+=_T(" ");//SK: modified for Unicode correctness. 
1263     LPCTSTR lpstrText = (LPCTSTR)newstring;
1264     t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
1265     if(t.cx>maxlength)maxlength = t.cx;
1266   }
1267   for(i=0;i<numitems;++i){
1268     string=m_MenuList[i]->GetString();
1269     j=string.Find((char)9);
1270     if(j!=-1){
1271       newstring.Empty();
1272       newstring=string.Left(j);
1273       LPCTSTR lpstrText = (LPCTSTR)(newstring);
1274       t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
1275       while(t.cx<maxlength){
1276         newstring+=_T(' ');//SK: modified for Unicode correctness
1277         LPCTSTR lpstrText = (LPCTSTR)(newstring);
1278         t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
1279       }
1280       newstring+=string.Mid(j);
1281 #ifdef UNICODE      
1282       m_MenuList[i]->SetWideString(newstring);//SK: modified for dynamic allocation
1283 #else
1284       m_MenuList[i]->SetAnsiString(newstring);
1285 #endif
1286     }
1287   }
1288   pDC->SelectObject (pFont);              // Select old font in
1289   AfxGetMainWnd()->ReleaseDC(pDC);       // Release the DC
1290   m_fontMenu.DeleteObject();
1291 }
1292
1293 void BCMenu::LoadCheckmarkBitmap(int unselect, int select)
1294 {
1295   if(unselect>0 && select>0){
1296     m_selectcheck=select;
1297     m_unselectcheck=unselect;
1298     if(checkmaps)checkmaps->DeleteImageList();
1299     else checkmaps=new(CImageList);
1300     checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
1301     BOOL flag1=AddBitmapToImageList(checkmaps,unselect);
1302     BOOL flag2=AddBitmapToImageList(checkmaps,select);
1303                 if(!flag1||!flag2){
1304                         checkmaps->DeleteImageList();
1305                         delete checkmaps;
1306                         checkmaps=NULL;
1307     }
1308   }
1309 }
1310
1311 //--------------------------------------------------------------------------
1312 //[18.06.99 rj]
1313 BOOL BCMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
1314 {
1315         BOOL returnflag=FALSE;
1316
1317         if(MF_BYPOSITION&nFlags){
1318                 UINT numMenuItems = m_MenuList.GetUpperBound();
1319                 if(id<=numMenuItems){
1320                         string=m_MenuList[id]->GetString();
1321                         returnflag=TRUE;
1322                 }
1323         }
1324         else{
1325                 int uiLoc;
1326                 BCMenu* pMenu = FindMenuOption(id,uiLoc);
1327                 if(NULL!=pMenu) returnflag = pMenu->GetMenuText(uiLoc,string);
1328         }
1329         return(returnflag);
1330 }
1331
1332
1333 void BCMenu::DrawRadioDot(CDC *pDC,int x,int y,COLORREF color)
1334 {
1335   CRect rcDot(x,y,x+6,y+6);
1336   CBrush brush;
1337   CPen pen;
1338   brush.CreateSolidBrush(color);
1339   pen.CreatePen(PS_SOLID,0,color);
1340   CBrush *pOldBrush=pDC->SelectObject(&brush);
1341   CPen *pOldPen=pDC->SelectObject(&pen);
1342   pDC->Ellipse(&rcDot);
1343         pDC->SelectObject(pOldBrush);
1344         pDC->SelectObject(pOldPen);
1345   pen.DeleteObject();
1346   brush.DeleteObject();
1347 }
1348
1349 void BCMenu::DrawCheckMark(CDC* pDC,int x,int y,COLORREF color)
1350 {
1351   pDC->SetPixel(x,y+2,color);
1352   pDC->SetPixel(x,y+3,color);
1353   pDC->SetPixel(x,y+4,color);
1354
1355   pDC->SetPixel(x+1,y+3,color);
1356   pDC->SetPixel(x+1,y+4,color);
1357   pDC->SetPixel(x+1,y+5,color);
1358
1359   pDC->SetPixel(x+2,y+4,color);
1360   pDC->SetPixel(x+2,y+5,color);
1361   pDC->SetPixel(x+2,y+6,color);
1362
1363   pDC->SetPixel(x+3,y+3,color);
1364   pDC->SetPixel(x+3,y+4,color);
1365   pDC->SetPixel(x+3,y+5,color);
1366
1367   pDC->SetPixel(x+4,y+2,color);
1368   pDC->SetPixel(x+4,y+3,color);
1369   pDC->SetPixel(x+4,y+4,color);
1370
1371   pDC->SetPixel(x+5,y+1,color);
1372   pDC->SetPixel(x+5,y+2,color);
1373   pDC->SetPixel(x+5,y+3,color);
1374
1375   pDC->SetPixel(x+6,y,color);
1376   pDC->SetPixel(x+6,y+1,color);
1377   pDC->SetPixel(x+6,y+2,color);
1378 }
1379
1380 BCMenuData *BCMenu::FindMenuList(UINT nID)
1381 {
1382   for(int i=0;i<=m_MenuList.GetUpperBound();++i){
1383     if(m_MenuList[i]->nID==nID && !m_MenuList[i]->syncflag){
1384       m_MenuList[i]->syncflag=1;
1385       return(m_MenuList[i]);
1386     }
1387   }
1388   return(NULL);
1389 }
1390
1391 void BCMenu::InitializeMenuList(int value)
1392 {
1393   for(int i=0;i<=m_MenuList.GetUpperBound();++i)
1394     m_MenuList[i]->syncflag=value;
1395 }
1396
1397 void BCMenu::DeleteMenuList(void)
1398 {
1399   for(int i=0;i<=m_MenuList.GetUpperBound();++i){
1400     if(!m_MenuList[i]->syncflag){
1401       delete m_MenuList[i];
1402     }
1403   }
1404 }
1405
1406 void BCMenu::SynchronizeMenu(void)
1407 {
1408   CTypedPtrArray<CPtrArray, BCMenuData*> temp;
1409   BCMenuData *mdata;
1410   CString string;
1411   UINT submenu,nID=0,state,j;
1412
1413   InitializeMenuList(0);
1414   for(j=0;j<GetMenuItemCount();++j){
1415     mdata=NULL;
1416     state=GetMenuState(j,MF_BYPOSITION);
1417     if(state&MF_POPUP){
1418       submenu=(UINT)GetSubMenu(j)->m_hMenu;
1419       mdata=FindMenuList(submenu);
1420       GetMenuString(j,string,MF_BYPOSITION);
1421       if(!mdata)mdata=NewODMenu(j,
1422         (state&0xFF)|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
1423       else if(string.GetLength()>0)
1424 #ifdef UNICODE
1425         mdata->SetWideString(string);  //SK: modified for dynamic allocation
1426 #else
1427         mdata->SetAnsiString(string);
1428 #endif
1429     }
1430     else if(state&MF_SEPARATOR){
1431       mdata=FindMenuList(0);
1432       if(!mdata)mdata=NewODMenu(j,
1433         state|MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW,0,_T(""));//SK: modified for Unicode correctness
1434       else ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
1435     }
1436     else{
1437       nID=GetMenuItemID(j);
1438       mdata=FindMenuList(nID);
1439       GetMenuString(j,string,MF_BYPOSITION);
1440       if(!mdata)mdata=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,
1441         nID,string);
1442       else{
1443         mdata->nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
1444         if(string.GetLength()>0)
1445 #ifdef UNICODE
1446                     mdata->SetWideString(string);//SK: modified for dynamic allocation
1447 #else
1448             mdata->SetAnsiString(string);
1449 #endif
1450             
1451         ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
1452       }
1453     }
1454     if(mdata)temp.Add(mdata);
1455   }
1456   DeleteMenuList();
1457   m_MenuList.RemoveAll();
1458   m_MenuList.Append(temp);
1459   temp.RemoveAll(); 
1460 }
1461
1462 void BCMenu::UpdateMenu(CMenu *pmenu)
1463 {
1464 #ifdef _CPPRTTI 
1465   BCMenu *psubmenu = dynamic_cast<BCMenu *>(pmenu);
1466 #else
1467   BCMenu *psubmenu = (BCMenu *)pmenu;
1468 #endif
1469   if(psubmenu)psubmenu->SynchronizeMenu();
1470 }
1471
1472 LRESULT BCMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags,
1473                                      CMenu *pMenu)
1474 {
1475 #ifdef _CPPRTTI 
1476   BCMenu *pBCMenu = dynamic_cast<BCMenu *>(pMenu);
1477 #else
1478   BCMenu *pBCMenu = (BCMenu *)pMenu;
1479 #endif
1480   if(pBCMenu && nFlags&MF_POPUP){
1481     CString key(_T('&'),2);//SK: modified for Unicode correctness
1482         key.SetAt(1,(TCHAR)nChar);
1483         key.MakeLower();
1484     CString menutext;
1485     int menusize = (int)pBCMenu->GetMenuItemCount();
1486     if(menusize!=(pBCMenu->m_MenuList.GetUpperBound()+1))
1487       pBCMenu->SynchronizeMenu();
1488     for(int i=0;i<menusize;++i){
1489       if(pBCMenu->GetMenuText(i,menutext)){
1490         menutext.MakeLower();
1491         if(menutext.Find(key)>=0)return(MAKELRESULT(i,2));
1492       }
1493     }
1494   }
1495   return(0);
1496 }
1497
1498 void BCMenu::DitherBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, 
1499                         int nHeight, HBITMAP hbm, int nXSrc, int nYSrc)
1500 {
1501   ASSERT(hdcDest && hbm);
1502   ASSERT(nWidth > 0 && nHeight > 0);
1503   
1504   // Create a generic DC for all BitBlts
1505   HDC hDC = CreateCompatibleDC(hdcDest);
1506   ASSERT(hDC);
1507   
1508   if (hDC)
1509   {
1510     // Create a DC for the monochrome DIB section
1511     HDC bwDC = CreateCompatibleDC(hDC);
1512     ASSERT(bwDC);
1513     
1514     if (bwDC)
1515     {
1516       // Create the monochrome DIB section with a black and white palette
1517       struct {
1518         BITMAPINFOHEADER bmiHeader; 
1519         RGBQUAD      bmiColors[2]; 
1520       } RGBBWBITMAPINFO = {
1521         
1522         {    // a BITMAPINFOHEADER
1523           sizeof(BITMAPINFOHEADER),  // biSize 
1524             nWidth,         // biWidth; 
1525             nHeight,        // biHeight; 
1526             1,            // biPlanes; 
1527             1,            // biBitCount 
1528             BI_RGB,         // biCompression; 
1529             0,            // biSizeImage; 
1530             0,            // biXPelsPerMeter; 
1531             0,            // biYPelsPerMeter; 
1532             0,            // biClrUsed; 
1533             0            // biClrImportant; 
1534         },    
1535         {
1536           { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 }
1537         } 
1538       };
1539       VOID *pbitsBW;
1540       HBITMAP hbmBW = CreateDIBSection(bwDC,
1541         (LPBITMAPINFO)&RGBBWBITMAPINFO, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
1542       ASSERT(hbmBW);
1543       
1544       if (hbmBW)
1545       {
1546         // Attach the monochrome DIB section and the bitmap to the DCs
1547         HBITMAP olddib = (HBITMAP)SelectObject(bwDC, hbmBW);
1548         HBITMAP hdcolddib = (HBITMAP)SelectObject(hDC, hbm);
1549         
1550         // BitBlt the bitmap into the monochrome DIB section
1551         BitBlt(bwDC, 0, 0, nWidth, nHeight, hDC, nXSrc, nYSrc, SRCCOPY);
1552         
1553         // Paint the destination rectangle in gray
1554         FillRect(hdcDest, CRect(nXDest, nYDest, nXDest + nWidth, nYDest +
1555                            nHeight), GetSysColorBrush((IsNewShell())?COLOR_3DFACE:COLOR_MENU));
1556                             //SK: looks better on the old shell
1557         // BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT
1558         // bits in the destination DC
1559         // The magic ROP comes from the Charles Petzold's book
1560         HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
1561         HBRUSH oldBrush = (HBRUSH)SelectObject(hdcDest, hb);
1562         BitBlt(hdcDest,nXDest+1,nYDest+1,nWidth,nHeight,bwDC,0,0,0xB8074A);
1563         
1564         // BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW
1565         // bits in the destination DC
1566         hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
1567         DeleteObject(SelectObject(hdcDest, hb));
1568         BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,bwDC,0,0,0xB8074A);
1569         DeleteObject(SelectObject(hdcDest, oldBrush));
1570         VERIFY(DeleteObject(SelectObject(bwDC, olddib)));
1571         SelectObject(hDC, hdcolddib);
1572       }
1573       
1574       VERIFY(DeleteDC(bwDC));
1575     }
1576     
1577     VERIFY(DeleteDC(hDC));
1578   }
1579 }
1580
1581 BOOL BCMenu::AddBitmapToImageList(CImageList *bmplist,UINT nResourceID)
1582 {
1583 // O.S.
1584   if (m_bDynIcons){
1585       bmplist->Add((HICON)nResourceID);
1586       return TRUE;
1587   }
1588
1589   BOOL bReturn=TRUE;
1590
1591   HBITMAP hbmp=LoadSysColorBitmap(nResourceID);
1592   if(hbmp){
1593     CBitmap bmp;
1594     bmp.Attach(hbmp);
1595     if(m_bitmapBackgroundFlag) bmplist->Add(&bmp,m_bitmapBackground);
1596     else bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE));
1597     bmp.Detach();
1598     DeleteObject(hbmp);
1599                 bReturn=TRUE;
1600   }
1601   else bReturn = FALSE;
1602   return(bReturn);
1603 }
1604
1605 void BCMenu::SetBitmapBackground(COLORREF color)
1606 {
1607   m_bitmapBackground=color;
1608   m_bitmapBackgroundFlag=TRUE;
1609 }
1610
1611 void BCMenu::UnSetBitmapBackground(void)
1612 {
1613   m_bitmapBackgroundFlag=FALSE;
1614 }
1615
1616 // Given a toolbar, append all the options from it to this menu
1617 // Passed a ptr to the toolbar object and the toolbar ID
1618 // Author : Robert Edward Caldecott
1619 void BCMenu::AddFromToolBar(CToolBar* pToolBar, int nResourceID)
1620 {
1621   for (int i = 0; i < pToolBar->GetCount(); i++) {
1622     UINT nID = pToolBar->GetItemID(i);
1623     // See if this toolbar option
1624     // appears as a command on this
1625     // menu or is a separator
1626     if (nID == 0 || GetMenuState(nID, MF_BYCOMMAND) == 0xFFFFFFFF)
1627       continue; // Item doesn't exist
1628     UINT nStyle;
1629     int nImage;
1630     // Get the toolbar button info
1631     pToolBar->GetButtonInfo(i, nID, nStyle, nImage);
1632     // OK, we have the command ID of the toolbar
1633     // option, and the tollbar bitmap offset
1634     int nLoc;
1635     BCMenuData* pData;
1636     BCMenu *pSubMenu = FindMenuOption(nID, nLoc);
1637     if (pSubMenu && nLoc >= 0)pData = pSubMenu->m_MenuList[nLoc];
1638     else {
1639       // Create a new BCMenuData structure
1640       pData = new BCMenuData;
1641       m_MenuList.Add(pData);
1642     }
1643     // Set some default structure members
1644     pData->menuIconNormal = nResourceID;
1645     pData->nID = nID;
1646     pData->nFlags =  MF_BYCOMMAND | MF_OWNERDRAW;
1647     pData->xoffset = nImage;
1648     if (pData->bitmap)pData->bitmap->DeleteImageList();
1649     else pData->bitmap = new CImageList;
1650     pData->bitmap->Create(m_iconX, m_iconY,ILC_COLORDDB|ILC_MASK, 1, 1);
1651
1652     if(!AddBitmapToImageList(pData->bitmap, nResourceID)){
1653                         pData->bitmap->DeleteImageList();
1654                         delete pData->bitmap;
1655                         pData->bitmap=NULL;
1656       pData->menuIconNormal = -1;
1657       pData->xoffset = -1;
1658     }
1659
1660     // Modify our menu
1661     ModifyMenu(nID,pData->nFlags,nID,(LPCTSTR)pData);
1662   }
1663 }
1664
1665 BOOL BCMenu::Draw3DCheckmark(CDC *dc, const CRect& rc,
1666                              BOOL bSelected, HBITMAP hbmCheck)
1667 {
1668   CRect rcDest = rc;
1669   CBrush brush;
1670   COLORREF col=GetSysColor((bSelected||!IsNewShell())?COLOR_MENU:COLOR_3DLIGHT);//SK: Looks better on the old shell
1671   brush.CreateSolidBrush(col);
1672   dc->FillRect(rcDest,&brush);
1673   brush.DeleteObject();
1674   if (IsNewShell()) //SK: looks better on the old shell
1675     dc->DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
1676   if (!hbmCheck)DrawCheckMark(dc,rc.left+4,rc.top+4,GetSysColor(COLOR_MENUTEXT));
1677   else DrawRadioDot(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
1678   return TRUE;
1679 }
1680
1681 void BCMenu::DitherBlt2(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
1682                         int nHeight, CBitmap &bmp, int nXSrc, int nYSrc)
1683 {
1684         // create a monochrome memory DC
1685         CDC ddc;
1686         ddc.CreateCompatibleDC(0);
1687   CBitmap bwbmp;
1688         bwbmp.CreateCompatibleBitmap(&ddc, nWidth, nHeight);
1689         CBitmap * pddcOldBmp = ddc.SelectObject(&bwbmp);
1690
1691   CDC dc;
1692         dc.CreateCompatibleDC(0);
1693   CBitmap * pdcOldBmp = dc.SelectObject(&bmp);
1694         
1695         // build a mask
1696         ddc.PatBlt(0, 0, nWidth, nHeight, WHITENESS);
1697         dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
1698         ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCCOPY);
1699         dc.SetBkColor(GetSysColor(COLOR_BTNHILIGHT));
1700         ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCPAINT);
1701
1702         // Copy the image from the toolbar into the memory DC
1703         // and draw it (grayed) back into the toolbar.
1704         dc.FillSolidRect(0,0, nWidth, nHeight, GetSysColor((IsNewShell())?COLOR_3DFACE:COLOR_MENU));
1705         //SK: Looks better on the old shell
1706         dc.SetBkColor(RGB(0, 0, 0));
1707         dc.SetTextColor(RGB(255, 255, 255));
1708         CBrush brShadow, brHilight;
1709         brHilight.CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
1710         brShadow.CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
1711         CBrush * pOldBrush = dc.SelectObject(&brHilight);
1712         dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
1713         drawdc->BitBlt(nXDest+1,nYDest+1,nWidth, nHeight, &dc,0,0,SRCCOPY);
1714         dc.BitBlt(1,1, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
1715         dc.SelectObject(&brShadow);
1716         dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
1717         drawdc->BitBlt(nXDest,nYDest,nWidth, nHeight, &dc,0,0,SRCCOPY);
1718         // reset DCs
1719         ddc.SelectObject(pddcOldBmp);
1720         ddc.DeleteDC();
1721         dc.SelectObject(pOldBrush);
1722         dc.SelectObject(pdcOldBmp);
1723         dc.DeleteDC();
1724
1725         brShadow.DeleteObject();
1726         brHilight.DeleteObject();
1727         bwbmp.DeleteObject();
1728 }
1729
1730 void BCMenu::SetDisableOldStyle(void)
1731 {
1732   disable_old_style=TRUE;
1733 }
1734
1735 void BCMenu::UnSetDisableOldStyle(void)
1736 {
1737   disable_old_style=FALSE;
1738 }
1739
1740 BOOL BCMenu::GetDisableOldStyle(void)
1741 {
1742   return(disable_old_style);
1743 }
1744
1745
1746 HBITMAP BCMenu::LoadSysColorBitmap(int nResourceId)
1747 {
1748   HINSTANCE hInst = 
1749     AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
1750   HRSRC hRsrc = 
1751     ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
1752         if (hRsrc == NULL)
1753                 return NULL;
1754         return AfxLoadSysColorBitmap(hInst, hRsrc, FALSE);
1755 }
1756
1757 BOOL BCMenu::RemoveMenu(UINT uiId,UINT nFlags)
1758 {
1759         if(MF_BYPOSITION&nFlags){
1760     UINT uint = GetMenuState(uiId,MF_BYPOSITION);
1761     if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
1762                   delete m_MenuList.GetAt(uiId);
1763           m_MenuList.RemoveAt(uiId);
1764     }
1765     else{
1766                 BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
1767                 if(NULL==pSubMenu){
1768                         UINT uiCommandId = GetMenuItemID(uiId);
1769                           for(int i=0;i<m_MenuList.GetSize(); i++){
1770                                   if(m_MenuList[i]->nID==uiCommandId){
1771                                         delete m_MenuList.GetAt(i);
1772                                         m_MenuList.RemoveAt(i);
1773                                         break;
1774                                 }
1775                           }
1776                   }
1777                   else{
1778         int numSubMenus = m_SubMenus.GetUpperBound();
1779         for(int m = numSubMenus; m >= 0; m--){
1780           if(m_SubMenus[m]==pSubMenu->m_hMenu){
1781             int numAllSubMenus = m_AllSubMenus.GetUpperBound();
1782             for(int n = numAllSubMenus; n>= 0; n--){
1783               if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
1784             }
1785                                         m_SubMenus.RemoveAt(m);
1786           }
1787         }
1788         int num = pSubMenu->GetMenuItemCount();
1789         for(int i=num-1;i>=0;--i)pSubMenu->RemoveMenu(i,MF_BYPOSITION);
1790                         for(i=m_MenuList.GetUpperBound();i>=0;i--){
1791                                 if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
1792                                         delete m_MenuList.GetAt(i);
1793                                         m_MenuList.RemoveAt(i);
1794                                         break;
1795                                   }
1796                           }
1797                           delete pSubMenu;
1798       }
1799                 }
1800         }
1801         else{
1802                 int iPosition =0;
1803                 BCMenu* pMenu = FindMenuOption(uiId,iPosition);
1804                 if(pMenu)pMenu->RemoveMenu(iPosition,MF_BYPOSITION);
1805         }
1806         return CMenu::RemoveMenu(uiId,nFlags);
1807 }
1808
1809 BOOL BCMenu::DeleteMenu(UINT uiId,UINT nFlags)
1810 {
1811         if(MF_BYPOSITION&nFlags){
1812     UINT uint = GetMenuState(uiId,MF_BYPOSITION);
1813     if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
1814                   delete m_MenuList.GetAt(uiId);
1815           m_MenuList.RemoveAt(uiId);
1816     }
1817     else{
1818                 BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
1819                 if(NULL==pSubMenu){
1820                         UINT uiCommandId = GetMenuItemID(uiId);
1821                           for(int i=0;i<m_MenuList.GetSize(); i++){
1822                                   if(m_MenuList[i]->nID==uiCommandId){
1823                                           delete m_MenuList.GetAt(i);
1824                                           m_MenuList.RemoveAt(i);
1825                                           break;
1826                                   }
1827                           }
1828       }
1829                 else{
1830         int numSubMenus = m_SubMenus.GetUpperBound();
1831         for(int m = numSubMenus; m >= 0; m--){
1832           if(m_SubMenus[m]==pSubMenu->m_hMenu){
1833             int numAllSubMenus = m_AllSubMenus.GetUpperBound();
1834             for(int n = numAllSubMenus; n>= 0; n--){
1835               if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
1836             }
1837                                         m_SubMenus.RemoveAt(m);
1838           }
1839         }
1840         int num = pSubMenu->GetMenuItemCount();
1841         for(int i=num-1;i>=0;--i)pSubMenu->DeleteMenu(i,MF_BYPOSITION);
1842                         for(i=m_MenuList.GetUpperBound();i>=0;i--){
1843                                 if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
1844                                         delete m_MenuList.GetAt(i);
1845                                           m_MenuList.RemoveAt(i);
1846                                         break;
1847                                 }
1848                         }
1849                           delete pSubMenu;
1850       }
1851                 }
1852         }
1853         else{
1854                 int iPosition =0;
1855                 BCMenu* pMenu = FindMenuOption(uiId,iPosition);
1856                 if(pMenu)pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
1857         }
1858         return CMenu::DeleteMenu(uiId,nFlags);
1859 }
1860
1861
1862 BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
1863 {
1864 USES_CONVERSION;
1865 return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
1866 }
1867
1868 BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
1869 {
1870   return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
1871 }
1872
1873 BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
1874 {
1875 USES_CONVERSION;
1876 return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
1877 }
1878
1879 BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
1880 {
1881   return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
1882 }
1883
1884 BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
1885 {
1886 USES_CONVERSION;
1887 return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
1888 }
1889
1890 BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
1891 {
1892   if(bmp){
1893         CImageList temp;
1894     temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
1895     if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
1896     else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
1897     return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,&temp,0);
1898   }
1899   return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,NULL,0);
1900 }
1901
1902 BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
1903 {
1904 USES_CONVERSION;
1905 return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
1906 }
1907
1908 BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
1909 {
1910   return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
1911 }
1912
1913 BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
1914 {
1915 USES_CONVERSION;
1916 return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
1917 }
1918
1919 BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
1920 {
1921   return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
1922 }
1923
1924 BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
1925 {
1926 USES_CONVERSION;
1927 return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
1928 }
1929
1930 BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
1931 {
1932   if(bmp){
1933         CImageList temp;
1934     temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
1935     if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
1936     else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
1937     return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,&temp,0);
1938   }
1939   return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,NULL,0);
1940 }
1941
1942 //--------------------------------------------------------------------------
1943 //[21.06.99 rj]
1944 BCMenu* BCMenu::AppendODPopupMenuW(wchar_t *lpstrText)
1945 {
1946         BCMenu* pSubMenu = new BCMenu;
1947         pSubMenu->m_unselectcheck=m_unselectcheck;
1948         pSubMenu->m_selectcheck=m_selectcheck;
1949         pSubMenu->checkmaps=checkmaps;
1950         pSubMenu->checkmapsshare=TRUE;
1951         pSubMenu->CreatePopupMenu();
1952         AppendODMenuW(lpstrText,MF_POPUP,(UINT)pSubMenu->m_hMenu, -1);
1953         return pSubMenu;
1954 }
1955
1956 //--------------------------------------------------------------------------
1957 //[21.06.99 rj]
1958 BCMenu* BCMenu::AppendODPopupMenuA(LPCSTR lpstrText)
1959 {
1960         USES_CONVERSION;
1961         return AppendODPopupMenuW(A2W(lpstrText));
1962 }
1963
1964 BOOL BCMenu::ImageListDuplicate(CImageList *il,int xoffset,CImageList *newlist)
1965 {
1966   if (il == NULL||newlist==NULL||xoffset<0) return FALSE;
1967   HICON hIcon = il->ExtractIcon(xoffset);
1968   int cx, cy;
1969   ImageList_GetIconSize(il->m_hImageList, &cx, &cy);
1970   newlist->Create(cx,cy,ILC_COLOR32|ILC_MASK,1,1);
1971   newlist->Add(hIcon);
1972   ::DestroyIcon(hIcon);
1973   return TRUE;
1974 }
1975
1976 //*************************************************************************