00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
#include "precomp.h"
00014
#pragma hdrstop
00015
00016
00017
00018
00019
00020
00021 #define CMENUITEMALLOC 8
00022 #define CMENUITEMDEALLOC 10
00023
00024
BOOL xxxSetLPITEMInfo(
PMENU pMenu,
PITEM pItem, LPMENUITEMINFOW lpmii, PUNICODE_STRING pstr);
00025 typedef BOOL (*
MENUAPIFN)(
PMENU,
UINT,
BOOL, LPMENUITEMINFOW);
00026
00027
00028
#if DBG
00029
VOID RelocateMenuLockRecords(
00030
PITEM pItem,
00031
int cItem,
00032 LONG_PTR cbMove)
00033 {
00034
while (cItem > 0) {
00035
if (pItem->
spSubMenu !=
NULL) {
00036 HMRelocateLockRecord(&(pItem->
spSubMenu), cbMove);
00037 }
00038 pItem++;
00039 cItem--;
00040 }
00041 }
00042
#endif
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 PMENU UnlockSubMenu(
00053
PMENU pMenu,
00054
PMENU* ppSubMenu)
00055 {
00056
PMENULIST* pp;
00057
PMENULIST pMLFound;
00058
00059
if (*ppSubMenu ==
NULL) {
00060
return NULL;
00061 }
00062
00063
00064
00065
for (pp = &(*ppSubMenu)->pParentMenus; *pp !=
NULL; pp = &(*pp)->
pNext) {
00066
if ((*pp)->pMenu == pMenu) {
00067 pMLFound = *pp;
00068 *pp = (*pp)->
pNext;
00069
DesktopFree(pMenu->
head.rpdesk, pMLFound);
00070
break;
00071 }
00072 }
00073
return Unlock(ppSubMenu);
00074 }
00075
00076 #define NESTED_MENU_LIMIT 25
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 CHAR GetMenuDepth(
PMENU pMenu, UINT uMaxAllowedDepth)
00087 {
00088
UINT uItems, uMaxDepth = 0, uSubMenuDepth;
00089
PITEM pItem;
00090
00091
00092
00093
00094
if (uMaxAllowedDepth == 0) {
00095
return NESTED_MENU_LIMIT;
00096 }
00097 pItem = pMenu->
rgItems;
00098
for (uItems = pMenu->
cItems; uItems--; pItem++) {
00099
if (pItem->
spSubMenu !=
NULL) {
00100 uSubMenuDepth =
GetMenuDepth(pItem->
spSubMenu, uMaxAllowedDepth-1);
00101
if (uSubMenuDepth > uMaxDepth) {
00102
00103
00104
00105
if (uSubMenuDepth >=
NESTED_MENU_LIMIT) {
00106
return NESTED_MENU_LIMIT;
00107 }
00108 uMaxDepth = uSubMenuDepth;
00109 }
00110 }
00111 }
00112
return uMaxDepth + 1;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 CHAR GetMenuAncestors(
PMENU pMenu)
00127 {
00128
PMENULIST pParentMenu;
00129
CHAR uParentAncestors;
00130
CHAR retVal = 0;
00131
00132
for (pParentMenu = pMenu->
pParentMenus; pParentMenu; pParentMenu = pParentMenu->
pNext) {
00133 uParentAncestors =
GetMenuAncestors(pParentMenu->
pMenu);
00134
if (uParentAncestors > retVal) {
00135 retVal = uParentAncestors;
00136 }
00137 }
00138
return retVal+1;
00139 }
00140
00141
00142
00143
00144
00145
00146 BOOL xxxSetMenuItemInfo(
00147
PMENU pMenu,
00148 UINT wIndex,
00149 BOOL fByPosition,
00150 LPMENUITEMINFOW lpmii,
00151 PUNICODE_STRING pstrItem)
00152 {
00153
00154
PITEM pItem;
00155
00156
CheckLock(pMenu);
00157
00158 pItem =
MNLookUpItem(pMenu, wIndex, fByPosition,
NULL);
00159
if (pItem ==
NULL) {
00160
00161
00162
00163
00164
if (!fByPosition && (wIndex == SC_TASKLIST))
00165
return TRUE;
00166
00167
00168
00169
00170 RIPERR0(ERROR_MENU_ITEM_NOT_FOUND, RIP_WARNING,
"ModifyMenu: Menu item not found");
00171
return FALSE;
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
if (lpmii->fMask & MIIM_TYPE) {
00187
BOOL bRtoL = (lpmii->fType & MFT_RIGHTORDER) ?
TRUE :
FALSE;
00188
00189
if (bRtoL ||
TestMF(pMenu,
MFRTL)) {
00190
MakeMenuRtoL(pMenu, bRtoL);
00191 }
00192 }
00193
return xxxSetLPITEMInfo(pMenu, pItem, lpmii, pstrItem);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 BOOL xxxSetMenuInfo(
PMENU pMenu, LPCMENUINFO lpmi)
00205 {
00206
PPOPUPMENU ppopup;
00207
BOOL fRecompute =
FALSE;
00208
BOOL fRedraw =
FALSE;
00209
UINT uFlags =
MNUS_DEFAULT;
00210
PITEM pItem;
00211
UINT uItems;
00212
TL tlSubMenu;
00213
00214
CheckLock(pMenu);
00215
00216
if (lpmi->fMask & MIM_STYLE) {
00217 pMenu->
fFlags ^= (pMenu->
fFlags ^ lpmi->dwStyle) & MNS_VALID;
00218 fRecompute =
TRUE;
00219 }
00220
00221
if (lpmi->fMask & MIM_MAXHEIGHT) {
00222 pMenu->
cyMax = lpmi->cyMax;
00223 fRecompute =
TRUE;
00224 }
00225
00226
if (lpmi->fMask & MIM_BACKGROUND) {
00227 pMenu->
hbrBack = lpmi->hbrBack;
00228 fRedraw =
TRUE;
00229
if (pMenu->
dwArrowsOn !=
MSA_OFF) {
00230 uFlags |=
MNUS_DRAWFRAME;
00231 }
00232 }
00233
00234
if (lpmi->fMask & MIM_HELPID) {
00235 pMenu->
dwContextHelpId = lpmi->dwContextHelpID;
00236 }
00237
00238
if (lpmi->fMask & MIM_MENUDATA) {
00239 pMenu->
dwMenuData = lpmi->dwMenuData;
00240 }
00241
00242
00243
00244
00245
if (lpmi->fMask & MIM_APPLYTOSUBMENUS) {
00246 pItem = pMenu->
rgItems;
00247
for (uItems = pMenu->
cItems; uItems--; pItem++) {
00248
if (pItem->
spSubMenu !=
NULL) {
00249
ThreadLock(pItem->
spSubMenu, &tlSubMenu);
00250
xxxSetMenuInfo(pItem->
spSubMenu, lpmi);
00251
ThreadUnlock(&tlSubMenu);
00252 }
00253 }
00254 }
00255
00256
00257
if (fRecompute) {
00258
00259
00260 pMenu->
cyMenu = pMenu->
cxMenu = 0;
00261 }
00262
00263
if (fRecompute || fRedraw) {
00264
if (ppopup =
MNGetPopupFromMenu(pMenu,
NULL)) {
00265
00266
00267
xxxMNUpdateShownMenu(ppopup,
NULL, uFlags);
00268 }
00269 }
00270
00271
return TRUE;
00272 }
00273
00274
00275
00276
00277
00278
00279 void NNDeleteAdjustIndex (UINT * puAdjustIndex, UINT uDelIndex)
00280 {
00281
if (*puAdjustIndex == uDelIndex) {
00282 *puAdjustIndex =
MFMWFP_NOITEM;
00283 }
else if ((
int)*puAdjustIndex > (
int)uDelIndex) {
00284 (*puAdjustIndex)--;
00285 }
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 void MNDeleteAdjustIndexes (
PMENUSTATE pMenuState,
PPOPUPMENU ppopup, UINT uiPos)
00300 {
00301
00302
00303
00304
NNDeleteAdjustIndex(&ppopup->
posSelectedItem, uiPos);
00305
if (ppopup->
fHierarchyDropped) {
00306
NNDeleteAdjustIndex(&ppopup->
posDropped, uiPos);
00307 }
00308
00309
00310
00311
00312
if (pMenuState->
uButtonDownHitArea == (ULONG_PTR)ppopup->
spwndPopupMenu) {
00313
NNDeleteAdjustIndex(&pMenuState->
uButtonDownIndex, uiPos);
00314 }
00315
if (pMenuState->
uDraggingHitArea == (ULONG_PTR)ppopup->
spwndPopupMenu) {
00316
NNDeleteAdjustIndex(&pMenuState->
uDraggingIndex, uiPos);
00317 }
00318 }
00319
00320
00321
00322
00323 BOOL xxxInsertMenuItem(
00324
PMENU pMenu,
00325 UINT wIndex,
00326 BOOL fByPosition,
00327 LPMENUITEMINFOW lpmii,
00328 PUNICODE_STRING pstrItem)
00329 {
00330
BOOL fRet =
TRUE;
00331
PITEM pItem;
00332
PMENU pMenuItemIsOn;
00333
PMENUSTATE pMenuState;
00334
PITEM pNewItems;
00335
PPOPUPMENU ppopup =
NULL;
00336
TL tlMenu;
00337
UINT uiPos;
00338
00339
CheckLock(pMenu);
00340
00341
00342
if (wIndex !=
MFMWFP_NOITEM) {
00343 pItem =
MNLookUpItem(pMenu, wIndex, fByPosition, &pMenuItemIsOn);
00344
00345
if (pItem !=
NULL) {
00346 pMenu = pMenuItemIsOn;
00347 }
else {
00348 wIndex =
MFMWFP_NOITEM;
00349 }
00350 }
else {
00351 pItem =
NULL;
00352 }
00353
00354
00355
00356
if (!
TestMF(pMenu,
MFISPOPUP)
00357 && (pMenu->
cItems != 0)
00358 && (!(lpmii->fMask & MIIM_BITMAP)
00359 || (lpmii->hbmpItem > HBMMENU_MBARLAST)
00360 || (lpmii->hbmpItem == 0)
00361 )) {
00362
00363
UINT wSave, w;
00364
PITEM pItemWalk;
00365 wSave = w = wIndex;
00366
00367
if (pItem && !fByPosition) {
00368 w =
MNGetpItemIndex(pMenu, pItem);
00369 w = (
UINT)((
PBYTE)pItem - (
PBYTE)(pMenu->
rgItems)) /
sizeof(
ITEM);
00370 }
00371
00372
if (!w) {
00373 pItemWalk = pMenu->
rgItems;
00374
if ((pItemWalk->
hbmp == HBMMENU_SYSTEM)) {
00375 wIndex = 1;
00376 }
00377 }
else {
00378
if (w ==
MFMWFP_NOITEM) {
00379 w = pMenu->
cItems;
00380 }
00381
00382 w--;
00383 pItemWalk = pMenu->
rgItems + w;
00384
while (w && (pItemWalk->
hbmp) && (pItemWalk->
hbmp < HBMMENU_MBARLAST)) {
00385 wIndex = w--;
00386 pItemWalk--;
00387 }
00388 }
00389
00390
if (wIndex != wSave) {
00391 pItem = pMenu->
rgItems + wIndex;
00392 }
00393 }
00394
00395
00396
00397
if (pMenu->
cItems >= pMenu->
cAlloced) {
00398
if (pMenu->
rgItems) {
00399 pNewItems = (
PITEM)
DesktopAlloc(pMenu->
head.rpdesk,
00400 (pMenu->
cAlloced +
CMENUITEMALLOC) *
sizeof(
ITEM),
00401
DTAG_MENUITEM);
00402
if (pNewItems) {
00403 RtlCopyMemory(pNewItems, pMenu->
rgItems,
00404 pMenu->
cAlloced *
sizeof(
ITEM));
00405
#if DEBUGTAGS
00406
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
00407 RelocateMenuLockRecords(pNewItems, pMenu->
cItems,
00408 ((
PBYTE)pNewItems) - (
PBYTE)(pMenu->
rgItems));
00409 }
00410
#endif
00411
DesktopFree(pMenu->
head.rpdesk, pMenu->
rgItems);
00412 }
00413 }
else {
00414 pNewItems = (
PITEM)
DesktopAlloc(pMenu->
head.rpdesk,
00415
sizeof(
ITEM) *
CMENUITEMALLOC,
DTAG_MENUITEM);
00416 }
00417
00418
if (pNewItems ==
NULL)
00419
return(
FALSE);
00420
00421 pMenu->
cAlloced +=
CMENUITEMALLOC;
00422 pMenu->
rgItems = pNewItems;
00423
00424
00425
00426
00427
00428
if (wIndex !=
MFMWFP_NOITEM)
00429 pItem =
MNLookUpItem(pMenu, wIndex, fByPosition, &pMenuItemIsOn);
00430
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
if ((pItem !=
NULL)
00441 && (ppopup =
MNGetPopupFromMenu(pMenu, &pMenuState))) {
00442
00443
00444
00445
00446 uiPos =
MNGetpItemIndex(pMenu, pItem);
00447
if (ppopup->
posSelectedItem >= (
int)uiPos) {
00448 ppopup->
posSelectedItem++;
00449 }
00450
if (ppopup->
fHierarchyDropped && (ppopup->
posDropped >= (
int)uiPos)) {
00451 ppopup->
posDropped++;
00452 }
00453
00454
00455
00456
00457
if (pMenuState->
uButtonDownHitArea == (ULONG_PTR)ppopup->
spwndPopupMenu) {
00458
if ((
int)pMenuState->
uButtonDownIndex >= (
int)uiPos) {
00459 pMenuState->
uButtonDownIndex++;
00460 }
00461 }
00462
if (pMenuState->
uDraggingHitArea == (ULONG_PTR)ppopup->
spwndPopupMenu) {
00463
00464
00465
00466
00467
if (((
int)pMenuState->
uDraggingIndex == (
int)uiPos)
00468 && (pMenuState->
uDraggingFlags & MNGOF_TOPGAP)) {
00469
00470
xxxMNSetGapState(pMenuState->
uDraggingHitArea,
00471 pMenuState->
uDraggingIndex,
00472 pMenuState->
uDraggingFlags,
00473
FALSE);
00474 }
00475
00476
if ((
int)pMenuState->
uDraggingIndex >= (
int)uiPos) {
00477 pMenuState->
uDraggingIndex++;
00478 }
00479 }
00480 }
00481
00482 pMenu->
cItems++;
00483
if (pItem !=
NULL) {
00484
00485 RtlMoveMemory(pItem + 1, pItem, (pMenu->
cItems - 1) *
00486
sizeof(
ITEM) - ((
char *)pItem - (
char *)pMenu->
rgItems));
00487
#if DEBUGTAGS
00488
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
00489 RelocateMenuLockRecords(pItem + 1,
00490 (
int)(&(pMenu->
rgItems[pMenu->
cItems]) - (pItem + 1)),
00491
sizeof(
ITEM));
00492 }
00493
#endif
00494
}
else {
00495
00496
00497
00498 pItem = pMenu->
rgItems + pMenu->
cItems - 1;
00499 }
00500
00501
00502
00503 pItem->
fType = 0;
00504 pItem->
fState = 0;
00505 pItem->
wID = 0;
00506 pItem->
spSubMenu =
NULL;
00507 pItem->
hbmpChecked =
NULL;
00508 pItem->
hbmpUnchecked =
NULL;
00509 pItem->
cch = 0;
00510 pItem->
dwItemData = 0;
00511 pItem->
xItem = 0;
00512 pItem->
yItem = 0;
00513 pItem->
cxItem = 0;
00514 pItem->
cyItem = 0;
00515 pItem->
hbmp =
NULL;
00516 pItem->
cxBmp =
MNIS_MEASUREBMP;
00517 pItem->
lpstr =
NULL;
00518
00519
00520
00521
00522
ThreadLock(pMenu, &tlMenu);
00523
if (!
xxxSetLPITEMInfo(pMenu, pItem, lpmii, pstrItem)) {
00524
00525
00526
00527
00528
if (ppopup !=
NULL) {
00529
MNDeleteAdjustIndexes(pMenuState, ppopup, uiPos);
00530 }
00531
00532
MNFreeItem(pMenu, pItem,
TRUE);
00533
00534
00535
00536 RtlMoveMemory(pItem, pItem + 1, pMenu->
cItems * (
UINT)
sizeof(
ITEM) +
00537 (
UINT)((
char *)&pMenu->
rgItems[0] - (
char *)(pItem + 1)));
00538
#if DEBUGTAGS
00539
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
00540 RelocateMenuLockRecords(pItem,
00541 (
int)(&(pMenu->
rgItems[pMenu->
cItems - 1]) - pItem),
00542 -(
int)
sizeof(
ITEM));
00543 }
00544
#endif
00545
pMenu->
cItems--;
00546 fRet =
FALSE;
00547 }
else {
00548
00549
00550
00551
00552
00553
00554
00555
if (
TestMF(pMenu,
MFRTL) ||
00556 (pItem &&
TestMFT(pItem, MFT_RIGHTORDER) && !
TestMFT(pItem, MFT_BITMAP))) {
00557 pItem->
fType |= (MFT_RIGHTORDER | MFT_RIGHTJUSTIFY);
00558
if (pItem->
spSubMenu) {
00559
MakeMenuRtoL(pItem->
spSubMenu,
TRUE);
00560 }
00561 }
00562 }
00563
00564
ThreadUnlock(&tlMenu);
00565
return fRet;
00566
00567 }
00568
00569
00570
00571
00572
00573
00574
00575 void FreeItemBitmap(
PITEM pItem)
00576 {
00577
00578
00579
if ((pItem->
hbmp !=
NULL) && !
TestMFS(pItem, MFS_CACHEDBMP)) {
00580
00581
00582
00583
00584
00585 GreSetBitmapOwner((HBITMAP)(pItem->
hbmp), OBJECT_OWNER_CURRENT);
00586 }
00587
00588
00589 pItem->
hbmp =
NULL;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598 void FreeItemString(
PMENU pMenu,
PITEM pItem)
00599 {
00600
00601
if ((pItem->
lpstr !=
NULL)) {
00602
DesktopFree(pMenu->
head.rpdesk, pItem->
lpstr);
00603 }
00604
00605 pItem->
lpstr =
NULL;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 void MNFreeItem(
00618
PMENU pMenu,
00619
PITEM pItem,
00620 BOOL fFreeItemPopup)
00621 {
00622
PMENU pSubMenu;
00623
00624
FreeItemBitmap(pItem);
00625
FreeItemString(pMenu, pItem);
00626
00627 pSubMenu =
UnlockSubMenu(pMenu, &(pItem->
spSubMenu));
00628
if (pSubMenu) {
00629
if (fFreeItemPopup) {
00630
_DestroyMenu(pSubMenu);
00631 }
00632 }
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 BOOL xxxRemoveDeleteMenuHelper(
00645
PMENU pMenu,
00646 UINT nPosition,
00647 DWORD wFlags,
00648 BOOL fDeleteMenu)
00649 {
00650
PITEM pItem;
00651
PITEM pNewItems;
00652
PMENU pMenuSave;
00653
PMENUSTATE pMenuState;
00654
PPOPUPMENU ppopup;
00655
UINT uiPos;
00656
00657
CheckLock(pMenu);
00658
00659 pMenuSave = pMenu;
00660
00661 pItem =
MNLookUpItem(pMenu, nPosition, (
BOOL) (wFlags & MF_BYPOSITION), &pMenu);
00662
if (pItem ==
NULL) {
00663
00664
00665
00666
00667
00668
00669
00670
if (nPosition >= 0xFFFFF000 && !(wFlags & MF_BYPOSITION)) {
00671 nPosition &= 0x0000FFFF;
00672 pMenu = pMenuSave;
00673 pItem =
MNLookUpItem(pMenu, nPosition,
FALSE, &pMenu);
00674
00675
if (pItem ==
NULL)
00676
return FALSE;
00677 }
else
00678
return FALSE;
00679 }
00680
00681
if (ppopup =
MNGetPopupFromMenu(pMenu, &pMenuState)) {
00682
00683
00684
00685
00686
00687 uiPos =
MNGetpItemIndex(pMenu, pItem);
00688
MNDeleteAdjustIndexes(pMenuState, ppopup, uiPos);
00689 }
00690
MNFreeItem(pMenu, pItem, fDeleteMenu);
00691
00692
00693
00694
00695 pMenu->cyMenu = pMenu->cxMenu = 0;
00696
00697
if (pMenu->cItems == 1) {
00698
DesktopFree(pMenu->head.rpdesk, pMenu->rgItems);
00699 pMenu->cAlloced = 0;
00700 pNewItems =
NULL;
00701 }
else {
00702
00703
00704
00705
00706
00707 RtlMoveMemory(pItem, pItem + 1, pMenu->cItems * (
UINT)
sizeof(
ITEM) +
00708 (
UINT)((
char *)&pMenu->rgItems[0] - (
char *)(pItem + 1)));
00709
#if DEBUGTAGS
00710
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
00711 RelocateMenuLockRecords(pItem,
00712 (
int)(&(pMenu->rgItems[pMenu->cItems - 1]) - pItem),
00713 -(
int)
sizeof(
ITEM));
00714 }
00715
#endif
00716
00717
00718
00719
00720 UserAssert(pMenu->cAlloced >= pMenu->cItems);
00721
if ((pMenu->cAlloced - pMenu->cItems) >=
CMENUITEMDEALLOC - 1) {
00722 pNewItems = (
PITEM)
DesktopAlloc(pMenu->head.rpdesk,
00723 (pMenu->cAlloced -
CMENUITEMDEALLOC) *
sizeof(
ITEM),
00724
DTAG_MENUITEM);
00725
if (pNewItems !=
NULL) {
00726
00727 RtlCopyMemory(pNewItems, pMenu->rgItems,
00728 (pMenu->cAlloced -
CMENUITEMDEALLOC) *
sizeof(
ITEM));
00729
#if DEBUGTAGS
00730
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
00731 RelocateMenuLockRecords(pNewItems, pMenu->cItems - 1,
00732 ((
PBYTE)pNewItems) - (
PBYTE)(pMenu->rgItems));
00733 }
00734
#endif
00735
DesktopFree(pMenu->head.rpdesk, pMenu->rgItems);
00736 pMenu->cAlloced -=
CMENUITEMDEALLOC;
00737 }
else
00738 pNewItems = pMenu->rgItems;
00739 }
else
00740 pNewItems = pMenu->rgItems;
00741 }
00742
00743 pMenu->rgItems = pNewItems;
00744 pMenu->cItems--;
00745
00746
if (ppopup !=
NULL) {
00747
00748
00749
00750
00751
xxxMNUpdateShownMenu(ppopup, pMenu->rgItems + uiPos,
MNUS_DELETE);
00752 }
00753
return TRUE;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 BOOL xxxRemoveMenu(
00767
PMENU pMenu,
00768 UINT nPosition,
00769 UINT wFlags)
00770 {
00771
return xxxRemoveDeleteMenuHelper(pMenu, nPosition, wFlags,
FALSE);
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 BOOL xxxDeleteMenu(
00783
PMENU pMenu,
00784 UINT nPosition,
00785 UINT wFlags)
00786 {
00787
return xxxRemoveDeleteMenuHelper(pMenu, nPosition, wFlags,
TRUE);
00788 }
00789
00790
00791
00792
00793
00794
00795
00796 BOOL NEAR
xxxSetLPITEMInfo(
00797
PMENU pMenu,
00798
PITEM pItem,
00799 LPMENUITEMINFOW lpmii,
00800 PUNICODE_STRING pstrItem)
00801 {
00802
00803 HANDLE hstr;
00804
UINT cch;
00805
BOOL fRecompute =
FALSE;
00806
BOOL fRedraw =
FALSE;
00807
PPOPUPMENU ppopup;
00808
00809
CheckLock(pMenu);
00810
00811
if (lpmii->fMask & MIIM_FTYPE) {
00812 pItem->
fType &= ~MFT_MASK;
00813 pItem->
fType |= lpmii->fType;
00814
if (lpmii->fType & MFT_SEPARATOR ) {
00815 pItem->
fState |= MFS_DISABLED ;
00816 }
00817 fRecompute =
TRUE;
00818 fRedraw = (lpmii->fType & MFT_OWNERDRAW);
00819 }
00820
00821
if (lpmii->fMask & MIIM_STRING) {
00822
if (pstrItem->Buffer !=
NULL) {
00823 hstr = (HANDLE)
DesktopAlloc(pMenu->
head.rpdesk,
00824 pstrItem->Length +
sizeof(UNICODE_NULL),
DTAG_MENUTEXT);
00825
00826
if (hstr ==
NULL) {
00827
return FALSE;
00828 }
00829
00830
try {
00831 RtlCopyMemory(hstr, pstrItem->Buffer, pstrItem->Length);
00832 } except (W32ExceptionHandler(
FALSE, RIP_WARNING)) {
00833
DesktopFree(pMenu->
head.rpdesk, hstr);
00834
return FALSE;
00835 }
00836 cch = pstrItem->Length /
sizeof(WCHAR);
00837
00838
00839
00840
00841 }
else {
00842 cch = 0;
00843 hstr =
NULL;
00844 }
00845
FreeItemString(pMenu,pItem);
00846 pItem->
cch = cch;
00847 pItem->
lpstr = hstr;
00848 fRecompute =
TRUE;
00849 fRedraw =
TRUE;
00850 }
00851
00852
if (lpmii->fMask & MIIM_BITMAP) {
00853
FreeItemBitmap(pItem);
00854 pItem->
hbmp = lpmii->hbmpItem;
00855 fRecompute =
TRUE;
00856 fRedraw =
TRUE;
00857 pItem->
cxBmp =
MNIS_MEASUREBMP;
00858
00859
00860
00861
if ((pItem->
hbmp > HBMMENU_MIN) && (pItem->
hbmp < HBMMENU_MAX)) {
00862
SetMFS(pItem, MFS_CACHEDBMP);
00863 }
else {
00864
ClearMFS(pItem, MFS_CACHEDBMP);
00865 }
00866 }
00867
00868
if (lpmii->fMask & MIIM_ID) {
00869 pItem->
wID = lpmii->wID;
00870 }
00871
00872
if (lpmii->fMask & MIIM_DATA) {
00873 pItem->
dwItemData = lpmii->dwItemData;
00874 }
00875
00876
if (lpmii->fMask & MIIM_STATE) {
00877
00878
00879
00880
00881
00882 UserAssert(!(lpmii->fState & ~MFS_MASK));
00883 pItem->
fState &= ~MFS_MASK | MFS_HILITE | MFS_DEFAULT;
00884 pItem->
fState |= lpmii->fState;
00885
if (pItem->
fType & MFT_SEPARATOR)
00886 pItem->
fState |= MFS_DISABLED;
00887 fRedraw =
TRUE;
00888 }
00889
00890
if (lpmii->fMask & MIIM_CHECKMARKS) {
00891 pItem->
hbmpChecked = lpmii->hbmpChecked;
00892 pItem->
hbmpUnchecked = lpmii->hbmpUnchecked;
00893 fRedraw =
TRUE;
00894 }
00895
00896
if (lpmii->fMask & MIIM_SUBMENU) {
00897
PMENU pSubMenu =
NULL;
00898
00899
if (lpmii->hSubMenu !=
NULL) {
00900 pSubMenu =
ValidateHmenu(lpmii->hSubMenu);
00901 }
00902
00903
00904
if (pItem->
spSubMenu != pSubMenu) {
00905
if (pItem->
spSubMenu !=
NULL) {
00906
_DestroyMenu(pItem->
spSubMenu);
00907 }
00908
if (pSubMenu !=
NULL) {
00909
00910
BOOL bMenuCreated =
FALSE;
00911
00912
00913
00914
00915
00916
if (pSubMenu == pMenu) {
00917 pSubMenu =
_CreateMenu();
00918
if (!pSubMenu) {
00919
return FALSE;
00920 }
00921 bMenuCreated =
TRUE;
00922 }
00923
00924
00925
00926
Lock(&(pItem->
spSubMenu), pSubMenu);
00927
SetMF(pItem->
spSubMenu,
MFISPOPUP);
00928
00929
00930
00931
00932
00933
00934
if (
GetMenuDepth(pSubMenu,
NESTED_MENU_LIMIT) +
GetMenuAncestors(pMenu) >=
NESTED_MENU_LIMIT) {
00935 FailInsertion:
00936 RIPMSG1(RIP_WARNING,
"The menu hierarchy is very deep or has a loop %#p", pMenu);
00937
ClearMF(pItem->
spSubMenu,
MFISPOPUP);
00938
Unlock(&(pItem->
spSubMenu));
00939
if (bMenuCreated) {
00940
_DestroyMenu(pSubMenu);
00941 }
00942
return FALSE;
00943 }
00944
00945
00946
00947 {
00948
PMENULIST pMenuList =
DesktopAlloc(pMenu->
head.rpdesk,
00949
sizeof(
MENULIST),
00950
DTAG_MENUITEM);
00951
if (!pMenuList) {
00952
goto FailInsertion;
00953 }
00954 pMenuList->
pMenu = pMenu;
00955 pMenuList->
pNext = pSubMenu->
pParentMenus;
00956 pSubMenu->
pParentMenus = pMenuList;
00957 }
00958 }
else {
00959
UnlockSubMenu(pMenu, &(pItem->
spSubMenu));
00960 }
00961 fRedraw =
TRUE;
00962 }
00963 }
00964
00965
00966
00967
00968
if (!(pItem->
fType & (MFT_OWNERDRAW | MFT_SEPARATOR))
00969 && (pItem->
lpstr ==
NULL)
00970 && (pItem->
hbmp ==
NULL)) {
00971
00972 pItem->
fType = MFT_SEPARATOR;
00973 pItem->
fState|=MFS_DISABLED;
00974 }
00975
00976
if (fRecompute) {
00977 pItem->
dxTab = 0;
00978 pItem->
ulX =
UNDERLINE_RECALC;
00979 pItem->
ulWidth = 0;
00980
00981
00982
00983 pMenu->
cyMenu = pMenu->
cxMenu = 0;
00984
00985
00986
if (fRedraw) {
00987
if (ppopup =
MNGetPopupFromMenu(pMenu,
NULL)) {
00988
00989
00990
xxxMNUpdateShownMenu(ppopup, pItem,
MNUS_DEFAULT);
00991 }
00992 }
00993
00994 }
00995
00996
return TRUE;
00997 }
00998
00999 BOOL _SetMenuContextHelpId(
PMENU pMenu, DWORD dwContextHelpId)
01000 {
01001
01002
01003 pMenu->
dwContextHelpId = dwContextHelpId;
01004
01005
return TRUE;
01006 }
01007
01008 BOOL _SetMenuFlagRtoL(
PMENU pMenu)
01009 {
01010
01011
01012
SetMF(pMenu,
MFRTL);
01013
01014
return TRUE;
01015 }
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 PPOPUPMENU MNGetPopupFromMenu(
PMENU pMenu,
PMENUSTATE *ppMenuState)
01028 {
01029
PPOPUPMENU ppopup;
01030
PMENUSTATE pMenuState;
01031
01032
01033
01034
01035
01036
if (pMenu->
spwndNotify ==
NULL) {
01037
return NULL;
01038 }
01039
01040
01041
01042
01043 pMenuState =
GetpMenuState(pMenu->
spwndNotify);
01044
if (pMenuState ==
NULL) {
01045
return NULL;
01046 }
01047
01048
01049
01050
01051
if (!pMenuState->
fInsideMenuLoop) {
01052
return NULL;
01053 }
01054
01055
01056
01057
01058
if (ppMenuState !=
NULL) {
01059 *ppMenuState = pMenuState;
01060 }
01061
01062
01063
01064
01065
01066 ppopup = pMenuState->
pGlobalPopupMenu;
01067
while (ppopup !=
NULL) {
01068
01069
01070
01071
if (ppopup->
spmenu == pMenu) {
01072
if (ppopup->
fIsMenuBar) {
01073
return NULL;
01074 }
01075
01076
01077
01078
MNAnimate(pMenuState,
FALSE);
01079
return ppopup;
01080 }
01081
01082
01083
01084
if (ppopup->
spwndNextPopup ==
NULL) {
01085
return NULL;
01086 }
01087
01088
01089
01090
01091 ppopup = ((
PMENUWND)ppopup->
spwndNextPopup)->ppopupmenu;
01092 }
01093
01094
return NULL;
01095 }
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106 void xxxMNUpdateShownMenu(
PPOPUPMENU ppopup,
PITEM pItem, UINT uFlags)
01107 {
01108 RECT rc;
01109
PWND pwnd = ppopup->
spwndPopupMenu;
01110
PMENU pMenu = ppopup->
spmenu;
01111
TL tlpwnd;
01112
TL tlpmenu;
01113
01114
01115
01116
01117
ThreadLock(pwnd, &tlpwnd);
01118
ThreadLock(ppopup->
spmenu, &tlpmenu);
01119
01120
_GetClientRect(pwnd, &rc);
01121
01122
01123
01124
01125
if (pMenu->
cxMenu == 0) {
01126 RECT rcScroll = rc;
01127
int cySave = rc.bottom;
01128
int cxSave = rc.right;
01129
DWORD dwSize;
01130
DWORD dwArrowsOnBefore;
01131
01132 dwArrowsOnBefore = pMenu->
dwArrowsOn;
01133 UserAssert(uFlags != 0);
01134 dwSize = (
DWORD)
xxxSendMessage(pwnd, MN_SIZEWINDOW, uFlags, 0
L);
01135 uFlags &= ~
MNUS_DRAWFRAME;
01136
01137
01138
01139
if (dwArrowsOnBefore ^ pMenu->
dwArrowsOn) {
01140
goto InvalidateAll;
01141 }
01142
01143 rc.right = LOWORD(dwSize);
01144
if (pItem !=
NULL) {
01145
if (rc.right != cxSave) {
01146
01147
01148
01149
goto InvalidateAll;
01150 }
else {
01151 rc.bottom = pMenu->
cyMenu;
01152
if (pMenu->
dwArrowsOn !=
MSA_OFF) {
01153
if (rc.bottom <= cySave) {
01154 rc.top = pItem->
yItem -
MNGetToppItem(pMenu)->
yItem;
01155
goto InvalidateRest;
01156 }
01157
01158
_GetClientRect(pwnd, &rcScroll);
01159 }
01160
01161 rc.top = rcScroll.top = pItem->
yItem -
MNGetToppItem(pMenu)->
yItem;
01162
if ((rc.top >= 0) && (rc.top < (
int)pMenu->
cyMenu)) {
01163
xxxScrollWindowEx(pwnd, 0, rc.bottom - cySave, &rcScroll, &rc,
NULL,
NULL, SW_INVALIDATE | SW_ERASE);
01164 }
01165 }
01166 }
01167 }
01168
01169
if (!(uFlags &
MNUS_DELETE)) {
01170
if (pItem !=
NULL) {
01171 rc.top = pItem->
yItem -
MNGetToppItem(pMenu)->
yItem;
01172 rc.bottom = rc.top + pItem->
cyItem;
01173 InvalidateRest:
01174
if ((rc.top >= 0) && (rc.top < (
int)pMenu->
cyMenu)) {
01175
xxxInvalidateRect(pwnd, &rc,
TRUE);
01176 }
01177 }
else {
01178 InvalidateAll:
01179
xxxInvalidateRect(pwnd,
NULL,
TRUE);
01180 }
01181
if (uFlags &
MNUS_DRAWFRAME) {
01182
xxxSetWindowPos(pwnd,
NULL, 0, 0, 0, 0,
01183 SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE
01184 | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
01185 }
01186 }
01187
01188
ThreadUnlock(&tlpmenu);
01189
ThreadUnlock(&tlpwnd);
01190 }