void TextSelection::SetText (const char *text) { #define CONTENT_START (0) #define CONTENT_END ((guint32)-1) if (anchor.GetParent() == NULL || moving.GetParent() == NULL) // if either are null we're going nowhere fast... return; ClearSelection (); // at this point the selection is empty and anchor == moving if (text && *text) { if (anchor.GetParent()->Is (Type::RUN)) { const char *run_text = ((Run*)anchor.GetParent())->GetText(); if (run_text == NULL) run_text = "\0"; char *new_text = (char*)g_malloc0 (strlen (run_text) + strlen (text) + 1); if (strlen (text) < (size_t) anchor.ResolveLocation ()){ // #339RT enters here g_free (new_text); new_text = g_strdup ("BUGBUGBUG"); } else { strncpy (new_text, run_text, anchor.ResolveLocation()); strcpy (new_text + anchor.ResolveLocation(), text); strncpy (new_text + anchor.ResolveLocation() + strlen(text), run_text + anchor.ResolveLocation(), strlen (run_text) - anchor.ResolveLocation()); } ((Run*)anchor.GetParent())->SetText (new_text); if (moving.GetLocation() > strlen (new_text)) { anchor = TextPointer (anchor.GetParent(), CONTENT_END, anchor.GetLogicalDirection()); moving = TextPointer (anchor.GetParent(), CONTENT_END, anchor.GetLogicalDirection()); } else { TextPointer new_anchor (anchor.GetParent(), anchor.ResolveLocation () + strlen (text), anchor.GetLogicalDirection()); moving = TextPointer (anchor.GetParent(), anchor.ResolveLocation () + strlen (text), anchor.GetLogicalDirection()); anchor = new_anchor; } g_free (new_text); if (anchor.CompareTo_np (moving) < 0) { start = anchor; end = moving; } else { start = moving; end = anchor; } } else { IDocumentNode *node = anchor.GetParentNode(); DependencyObjectCollection *children = node->GetDocumentChildren(); if (!children) { // this can happen when anchor is in an InlineUIContainer. printf ("NIEX TextSelection.SetText for anchor == InlineUIContainer.\n"); return; } Run *r = MoonUnmanagedFactory::CreateRun (); r->SetText (text); if (children->Is(Type::BLOCK_COLLECTION)) { // the node takes Blocks as children, so we need to create a Paragraph first. Paragraph *p = MoonUnmanagedFactory::CreateParagraph(); children->Insert (anchor.GetLocation(), Value (p)); children = p->GetInlines(); children->Add (Value (r)); p->unref (); } else { children->Insert (anchor.GetLocation(), Value (r)); } anchor = TextPointer (r, CONTENT_END, anchor.GetLogicalDirection()); moving = TextPointer (r, CONTENT_END, anchor.GetLogicalDirection()); r->unref (); if (anchor.CompareTo_np (moving) < 0) { start = anchor; end = moving; } else { start = moving; end = anchor; } } } g_free (this->text); this->text = NULL; }
/***************************************************************************\ * xxxItemSize * * Calc the dimensions of bitmaps and strings. Loword of returned * value contains width, high word contains height of item. * * History: * 07-23-96 GerardoB - fixed up for 5.0 \***************************************************************************/ BOOL xxxMNItemSize( PMENU pMenu, PWND pwndNotify, HDC hdc, PITEM pItem, BOOL fPopup, LPPOINT lppt) { BITMAP bmp; int width = 0; int height = 0; DWORD xRightJustify; LPWSTR lpMenuString; HFONT hfnOld; int tcExtra; UNREFERENCED_PARAMETER(pMenu); CheckLock(pMenu); CheckLock(pwndNotify); if (!fPopup) { /* * Save off the height of the top menu bar since we will used this often * if the pItem is not in a popup. (ie. it is in the top level menu bar) */ height = SYSMET(CYMENUSIZE); } hfnOld = NULL; if (TestMFS(pItem, MFS_DEFAULT)) { if (ghMenuFontDef) hfnOld = GreSelectFont(hdc, ghMenuFontDef); else { tcExtra = GreGetTextCharacterExtra(hdc); GreSetTextCharacterExtra(hdc, tcExtra + 1 + (gcxMenuFontChar / gpsi->cxSysFontChar)); } } /* * Compute bitmap dimensions if needed */ if (pItem->hbmp != NULL) { if (pItem->hbmp == HBMMENU_CALLBACK) { xxxMNGetBitmapSize(pItem, pwndNotify); } else if (pItem->cxBmp == MNIS_MEASUREBMP) { if (TestMFS(pItem, MFS_CACHEDBMP)) { pItem->cxBmp = SYSMET(CXMENUSIZE); pItem->cyBmp = SYSMET(CYMENUSIZE); if (pItem->hbmp == HBMMENU_SYSTEM) { pItem->cxBmp += SYSMET(CXEDGE); /* * Chicago/Memphis only stretch the width, * not the height. NT Bug 124779. FritzS */ // pItem->cyBmp += SYSMET(CXEDGE); } } else { if (GreExtGetObjectW(pItem->hbmp, sizeof(BITMAP), (LPSTR)&bmp)) { pItem->cxBmp = bmp.bmWidth; pItem->cyBmp = bmp.bmHeight; } else { /* * If the bitmap is not useable, this is as good a default * as any. */ pItem->cxBmp = SYSMET(CXMENUSIZE); pItem->cyBmp = SYSMET(CYMENUSIZE); } } } width = pItem->cxBmp; /* * Remember the max bitmap width to align the text in all items. */ pMenu->cxTextAlign = max(pMenu->cxTextAlign, (DWORD)width); /* * In menu bars, we force the item to be at least CYMNSIZE. * Fixes many, many problems w/ apps that fake own MDI. */ if (fPopup) { height = pItem->cyBmp; } else { height = max((int)pItem->cyBmp, height); } } else if (TestMFT(pItem, MFT_OWNERDRAW)) { // This is an ownerdraw item -- the width and height are stored in // cxBmp and cyBmp xxxMNGetBitmapSize(pItem, pwndNotify); width = pItem->cxBmp; // // Ignore height with menu bar now--that's set by user. // if (fPopup) { height = pItem->cyBmp; // If this item has a popup (hierarchical) menu associated with it, then // reserve room for the bitmap that tells the user that a hierarchical // menu exists here. // B#2966, t-arthb UserAssert(fPopup == (TestMF(pMenu, MFISPOPUP) != 0)); width = width + (gcxMenuFontChar << 1); } } if ((pItem->lpstr != NULL) && (!TestMFT(pItem, MFT_OWNERDRAW)) ) { SIZE size; /* * This menu item contains a string */ /* * We want to keep the menu bar height if this isn't a popup. */ if (fPopup) { /* The thickness of mnemonic underscore is CYBORDER and the gap * between the characters and the underscore is another CYBORDER */ height = max(height, gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE)); } lpMenuString = TextPointer(pItem->lpstr); xRightJustify = FindCharPosition(lpMenuString, TEXT('\t')); xxxPSMGetTextExtent(hdc, lpMenuString, xRightJustify, &size); if (width) { width += MNXSPACE + size.cx; } else { width = size.cx; } } if (fPopup && !TestMFT(pItem, MFT_OWNERDRAW)) { /* * Add on space for checkmark, then horz spacing for default & disabled * plus some left margin. */ if (TestMF(pMenu, MNS_CHECKORBMP) || !TestMF(pMenu, MNS_NOCHECK)) { width += gpsi->oembmi[OBI_MENUCHECK].cx; } width += MNXSPACE + MNLEFTMARGIN + 2; height += 2; } if (TestMFS(pItem, MFS_DEFAULT)) { if (hfnOld) GreSelectFont(hdc, hfnOld); else GreSetTextCharacterExtra(hdc, tcExtra); } /* * Loword contains width, high word contains height of item. */ lppt->x = width; lppt->y = height; return(TestMFT(pItem, MFT_OWNERDRAW)); }
DWORD MNRecalcTabStrings( HDC hdc, PMENU pMenu, UINT iBeg, UINT iEnd, DWORD xTab, DWORD hCount) { UINT i; UINT cOwnerDraw; int adx; int maxWidth = 0; int cx; PITEM pItem; CheckLock(pMenu); xTab += hCount; if ((iBeg >= pMenu->cItems) || (iBeg > iEnd)) goto SeeYa; cOwnerDraw = 0; for (i = iBeg, pItem = pMenu->rgItems + iBeg; i < iEnd; pItem++, i++) { adx = 0; /* * Subtract hCount to make dxTab relative to start of column for * multi-column menus. */ pItem->dxTab = xTab - hCount; // Skip non-string or empty string items if ((pItem->lpstr != NULL) && !TestMFT(pItem, MFT_OWNERDRAW)) { LPWSTR lpString = TextPointer(pItem->lpstr); int tp; SIZE size; // Are there any tabs? tp = FindCharPosition(lpString, TEXT('\t')); if (tp < (int) pItem->cch) { PTHREADINFO ptiCurrent = PtiCurrentShared(); if (CALL_LPK(ptiCurrent)) { xxxClientGetTextExtentPointW(hdc, lpString + tp + 1, pItem->cch - tp - 1, &size); } else { GreGetTextExtentW(hdc, lpString + tp + 1, pItem->cch - tp - 1, &size, GGTE_WIN3_EXTENT); } adx = gcxMenuFontChar + size.cx; } } else if (TestMFT(pItem, MFT_OWNERDRAW)) cOwnerDraw++; adx += xTab; if (adx > maxWidth) maxWidth = adx; } /* * Add on space for hierarchical arrow. So basically, popup menu items * can have 4 columns: * (1) Checkmark * (2) Text * (3) Tabbed text for accel * (4) Hierarchical arrow * * But, we only do this if at least one item isn't ownerdraw * and if there's at least one submenu in the popup. */ if (cOwnerDraw != (iEnd - iBeg)) { maxWidth += gcxMenuFontChar + gpsi->oembmi[OBI_MENUCHECK].cx; } cx = maxWidth - hCount; for (i = iBeg, pItem = pMenu->rgItems + iBeg; i < iEnd; pItem++, i++) pItem->cxItem = cx; SeeYa: return(maxWidth); }
int xxxMNCompute( PMENU pMenu, PWND pwndNotify, DWORD yMenuTop, DWORD xMenuLeft, DWORD cxMax, LPDWORD lpdwMenuHeight) { UINT cItem; DWORD cxItem; DWORD cyItem; DWORD cyItemKeep; DWORD yPopupTop; INT cMaxWidth; DWORD cMaxHeight; UINT cItemBegCol; DWORD temp; int ret; PITEM pCurItem; POINT ptMNItemSize; BOOL fOwnerDrawItems; BOOL fMenuBreak; LPWSTR lpsz; BOOL fPopupMenu; DWORD menuHeight = 0; HDC hdc; HFONT hOldFont; PTHREADINFO ptiCurrent = PtiCurrent(); BOOL fStringAndBitmapItems; CheckLock(pMenu); CheckLock(pwndNotify); /* * Whoever computes the menu, becomes the owner. */ if (pwndNotify != pMenu->spwndNotify) { Lock(&pMenu->spwndNotify, pwndNotify); } if (lpdwMenuHeight != NULL) menuHeight = *lpdwMenuHeight; /* * Empty menus have a height of zero. */ ret = 0; if (pMenu->cItems == 0) return ret; hdc = _GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE); hOldFont = GreSelectFont(hdc, ghMenuFont); /* * Try to make a non-multirow menu first. */ pMenu->fFlags &= (~MFMULTIROW); fPopupMenu = TestMF(pMenu, MFISPOPUP); if (fPopupMenu) { /* * Reset the menu bar height to 0 if this is a popup since we are * being called from menu.c MN_SIZEWINDOW. */ menuHeight = 0; } else if (pwndNotify != NULL) { pMenu->cxMenu = cxMax; } /* * Initialize the computing variables. */ cMaxWidth = cyItemKeep = 0L; cItemBegCol = 0; cyItem = yPopupTop = yMenuTop; cxItem = xMenuLeft; pCurItem = (PITEM)&pMenu->rgItems[0]; /* * cxTextAlign is used to align the text in all items; this is useful * in popup menus that mix text only items with bitmap-text items. It's * set to the max bitmap width plus some spacing. * Do this for new menus wich use string AND bitmaps on the same item */ fStringAndBitmapItems = FALSE; pMenu->cxTextAlign = 0; /* * Process each item in the menu. */ fOwnerDrawItems = FALSE; for (cItem = 0; cItem < pMenu->cItems; cItem++) { /* * If it's not a separator, find the dimensions of the object. */ if (TestMFT(pCurItem, MFT_SEPARATOR) && ( !TestMFT(pCurItem, MFT_OWNERDRAW) || (LOWORD(ptiCurrent->dwExpWinVer) < VER40)) ) { /* * If version is less than 4.0 don't test the MFT_OWNERDRAW * flag. Bug 21922; App MaxEda has both separator and Ownerdraw * flags on. In 3.51 we didn't test the OwnerDraw flag */ // // This is a separator. It's drawn as wide as the menu area, // leaving some space above and below. Since the menu area is // the max of the items' widths, we set our width to 0 so as not // to affect the result. // pCurItem->cxItem = 0; pCurItem->cyItem = SYSMET(CYMENUSIZE) / 2; } else { /* * Are we using NT5 strings and bitmaps? */ fStringAndBitmapItems |= ((pCurItem->hbmp != NULL) && (pCurItem->lpstr != NULL)); /* * Get the item's X and Y dimensions. */ if (xxxMNItemSize(pMenu, pwndNotify, hdc, pCurItem, fPopupMenu, &ptMNItemSize)) fOwnerDrawItems = TRUE; pCurItem->cxItem = ptMNItemSize.x; pCurItem->cyItem = ptMNItemSize.y; if (!fPopupMenu && ((pCurItem->hbmp == NULL) || (pCurItem->lpstr != NULL))) { pCurItem->cxItem += gcxMenuFontChar * 2; } } if (menuHeight != 0) pCurItem->cyItem = menuHeight; /* * If this is the first item, initialize cMaxHeight. */ if (cItem == 0) cMaxHeight = pCurItem->cyItem; /* * Is this a Pull-Down menu? */ if (fPopupMenu) { /* * If this item has a break or is the last item... */ if ((fMenuBreak = TestMFT(pCurItem, MFT_BREAK)) || pMenu->cItems == cItem + (UINT)1) { /* * Keep cMaxWidth around if this is not the last item. */ temp = cMaxWidth; if (pMenu->cItems == cItem + (UINT)1) { if ((int)(pCurItem->cxItem) > cMaxWidth) temp = pCurItem->cxItem; } /* * Get new width of string from RecalcTabStrings. */ temp = MNRecalcTabStrings(hdc, pMenu, cItemBegCol, (UINT)(cItem + (fMenuBreak ? 0 : 1)), temp, cxItem); /* * If this item has a break, account for it. */ if (fMenuBreak) { // // Add on space for the etch and a border on either side. // NOTE: For old apps that do weird stuff with owner // draw, keep 'em happy by adding on the same amount // of space we did in 3.1. // if (fOwnerDrawItems && !TestWF(pwndNotify, WFWIN40COMPAT)) cxItem = temp + SYSMET(CXBORDER); else cxItem = temp + 2 * SYSMET(CXEDGE); /* * Reset the cMaxWidth to the current item. */ cMaxWidth = pCurItem->cxItem; /* * Start at the top. */ cyItem = yPopupTop; /* * Save the item where this column begins. */ cItemBegCol = cItem; /* * If this item is also the last item, recalc for this * column. */ if (pMenu->cItems == (UINT)(cItem + 1)) { temp = MNRecalcTabStrings(hdc, pMenu, cItem, (UINT)(cItem + 1), cMaxWidth, cxItem); } } /* * If this is the last entry, supply the width. */ if (pMenu->cItems == cItem + (UINT)1) pMenu->cxMenu = temp; } pCurItem->xItem = cxItem; pCurItem->yItem = cyItem; cyItem += pCurItem->cyItem; if (cyItemKeep < cyItem) cyItemKeep = cyItem; } else { /* * This a Top Level menu, not a Pull-Down. */ /* * Adjust right aligned items before testing for multirow */ if (pCurItem->lpstr != NULL) { lpsz = TextPointer(pCurItem->lpstr); if ((lpsz != NULL) && (*lpsz == CH_HELPPREFIX)) { pCurItem->cxItem -= gcxMenuFontChar; } } /* * If this is a new line or a menu break. */ if ((TestMFT(pCurItem, MFT_BREAK)) || (((cxItem + pCurItem->cxItem + gcxMenuFontChar) > pMenu->cxMenu) && (cItem != 0))) { cyItem += cMaxHeight; cxItem = xMenuLeft; cMaxHeight = pCurItem->cyItem; pMenu->fFlags |= MFMULTIROW; } pCurItem->yItem = cyItem; pCurItem->xItem = cxItem; cxItem += pCurItem->cxItem; } if (cMaxWidth < (int)(pCurItem->cxItem)) cMaxWidth = pCurItem->cxItem; if (cMaxHeight != pCurItem->cyItem) { if (cMaxHeight < pCurItem->cyItem) cMaxHeight = pCurItem->cyItem; if (!fPopupMenu) menuHeight = cMaxHeight; } if (!fPopupMenu) cyItemKeep = cyItem + cMaxHeight; pCurItem++; } /* of for loop */ /* * Determine where the strings should be drawn so they are aligned * The alignment is only for popup (vertical) menus (see xxxRealDrawMenuItem) * The actual space depends on the MNS_NOCHECK and MNS_CHECKORBMP styles * Multicolumn menus don't get aligment (now that we have scrollbars, multicolum is out) */ if (!fStringAndBitmapItems || (cItemBegCol != 0)) { pMenu->cxTextAlign = 0; } else if (TestMF(pMenu, MNS_NOCHECK)) { pMenu->cxTextAlign += MNXSPACE; } else if (TestMF(pMenu, MNS_CHECKORBMP)) { pMenu->cxTextAlign = max(pMenu->cxTextAlign, (UINT)gpsi->oembmi[OBI_MENUCHECK].cx); pMenu->cxTextAlign += MNXSPACE; } else { pMenu->cxTextAlign += gpsi->oembmi[OBI_MENUCHECK].cx + MNXSPACE; } /* * Add the left margin */ if (pMenu->cxTextAlign != 0) { pMenu->cxTextAlign += MNLEFTMARGIN; } if (cItemBegCol && pMenu->cItems && TestMFT(((PITEM)&pMenu->rgItems[0]), MFT_RIGHTJUSTIFY)) { // // multi-column, if we are in RtoL mode, reverse the columns // pCurItem = (PITEM)&pMenu->rgItems[0]; for (cItem = 0; cItem < pMenu->cItems; cItem++) { pCurItem->xItem = pMenu->cxMenu - (pCurItem->xItem + pCurItem->cxItem); pCurItem++; } } GreSelectFont(hdc, hOldFont); _ReleaseDC(hdc); pMenu->cyMenu = cyItemKeep - yMenuTop; ret = pMenu->cyMenu; if (lpdwMenuHeight != NULL) *lpdwMenuHeight = menuHeight; return ret; }