/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "stdafx.h" #include "cxdc.h" #include "cntritem.h" #include "intlwin.h" #include "mainfrm.h" #include "npapi.h" #include "np.h" #include "feembed.h" #include "fmabstra.h" #include "custom.h" #include "prefapi.h" #include "feimage.h" #include "il_icons.h" #include "intl_csi.h" #include "prefinfo.h" #include "cxprint.h" #include "edt.h" #if defined(OJI) #include "jvmmgr.h" #elif defined(JAVA) #include "java.h" #endif // These four are all specified in pixels #define IMAGE_SMICON_MARGIN 4 #define IMAGE_SMICON_WIDTH 14 #define IMAGE_SMICON_HEIGHT 16 #define IMAGE_SMICON_TEXT_OFFSET 2 #define IS_SECOND_TO_LAST_LAYER(layer) (CL_GetLayerBelow(layer) && \ CL_GetLayerName(CL_GetLayerBelow(layer)) && \ (strcmp(CL_GetLayerName(CL_GetLayerBelow(layer)), \ LO_BACKGROUND_LAYER_NAME) == 0)) #define LOADBITMAP(id) \ ::LoadBitmap(AfxGetResourceHandle(), MAKEINTRESOURCE(id)) CDCCX::CDCCX() { // Purpose: Constructor for DC Context // Arguments: void // Returns: none // Comments: Sets the context type basically // Revision History: // 05-27-95 created GAB // m_cxType = DeviceContext; m_bOwnDC = FALSE; m_bClassDC = FALSE; // Our mapping mode will be anisotropic unless those which derive // set otherwise. m_MM = MM_ANISOTROPIC; m_pPal = NULL; m_lWidth = 0; m_lHeight = 0; m_iOffset = 0; CString csNo(SZ_NO); m_pImageDC = NULL; curColorSpace = 0; // As a default starting background color, use that of the button face. m_rgbBackgroundColor = sysInfo.m_clrBtnFace; m_rgbDarkColor = sysInfo.m_clrBtnShadow; m_rgbLightColor = sysInfo.m_clrBtnHilite; Set3DColors(m_rgbBackgroundColor); // Set that we have no document, and we currently // won't autodelete what may get assigned in. m_pDocument = NULL; m_bAutoDeleteDocument = FALSE; // No previously selected font. m_pSelectedCachedFont = NULL; m_lastDCWithCachedFont = NULL; // Document has no substance. m_lDocWidth = 0; m_lDocHeight = 0; m_lOrgX = m_lOrgY = 0; // Start out with some default values in the conversions from pix 2 twips. m_lConvertX = 1; m_lConvertY = 1; GetContext()->convertPixX = 1; GetContext()->convertPixY = 1; // Assume the driver doesn't support 565 mode for 16 bpp DIBs m_bRGB565 = FALSE; // Allow resolving of layout elements. m_bResolveElements = TRUE; // We're not in an OLE server. m_bOleServer = FALSE; // Form text entry box font m_pFormFixFont = NULL; m_pFormPropFont = NULL; m_iFormFixCSID = CS_LATIN1; m_iFormPropCSID = CS_LATIN1; m_bLoadImagesNow = FALSE; m_bNexttimeLoadImagesNow = FALSE; GetContext()->XpixelsPerPoint = 0; GetContext()->YpixelsPerPoint = 0; } CDCCX::~CDCCX() { // Purpose: Destructor for DC Context // Arguments: void // Returns: none // Comments: // Revision History: // 05-27-95 created GAB // // If we've got a document, let it know we're gone now. if(GetDocument() != NULL) { TRACE("Clearing document context\n"); GetDocument()->ClearContext(); } if(m_pImageDC != NULL) { if (!IsGridCell()) { // only delete the temporary DC if we are the parent. if (m_bUseDibPalColors) ::SelectPalette(m_pImageDC, (HPALETTE)::GetStockObject(DEFAULT_PALETTE), TRUE); VERIFY(::DeleteDC( m_pImageDC)); } } // Do not delete the default palette. if(m_pPal && m_pPal != WFE_GetUIPalette(NULL)) { VERIFY(::DeleteObject(m_pPal)); } if(m_pDocument != NULL && m_bAutoDeleteDocument == TRUE) { // We call OnCloseDocument here, to delete the document. // If we do this here, it basically indicates that we created the // document ourselves (probably a print context), and it // wasn't made in the MFC framework. m_pDocument->OnCloseDocument(); } if (curColorSpace) IL_ReleaseColorSpace(curColorSpace); } void CDCCX::DestroyContext() { if(IsDestroyed() == FALSE) { // Give the document a chance to copy any needed information before // we go down. This helps the OLE server stuff survive while // the context of the view has gone to the twilight zone and back. if(GetDocument()) { GetDocument()->CacheEphemeralData(); } // Get rid of all our fonts. ClearFontCache(); } // Call the base. CStubsCX::DestroyContext(); } BOOL CDCCX::ResolveTextExtent(HDC pDC, LPCTSTR pString, int iLength, LPSIZE pSize, CyaFont *pFont) { return ResolveTextExtent( INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext())) , pDC, pString, iLength, pSize, pFont); } #ifdef XP_WIN32 static BOOL SupportsRGB565(HDC pDC) { BITMAPINFO *lpBMInfo = NULL; int iFlags; int nSize = sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD); LPDWORD lpMasks; // Use the QUERYDIBSUPPORT escape to determine if the driver // supports RGB565 format DIBs lpBMInfo = (BITMAPINFO *)XP_ALLOC(nSize); if (!lpBMInfo) return FALSE; memset(lpBMInfo, 0, nSize); lpBMInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); lpBMInfo->bmiHeader.biWidth = 10; lpBMInfo->bmiHeader.biHeight = 10; lpBMInfo->bmiHeader.biPlanes = 1; lpBMInfo->bmiHeader.biBitCount = 16; lpBMInfo->bmiHeader.biCompression = BI_BITFIELDS; // Define the color masks for a RGB565 DIB lpMasks = (LPDWORD)lpBMInfo->bmiColors; lpMasks[0] = 0xF800; // red color mask lpMasks[1] = 0x07E0; // green color mask lpMasks[2] = 0x001F; // blue color mask // Ask the driver ::Escape(pDC, QUERYDIBSUPPORT, nSize, (LPCSTR)lpBMInfo, &iFlags); XP_FREE(lpBMInfo); return (iFlags & (QDI_SETDIBITS | QDI_DIBTOSCREEN | QDI_STRETCHDIB)) != 0; } #endif void CDCCX::PrepareDraw() { if (m_pImageDC) { if (m_bUseDibPalColors && m_pPal) ::SelectPalette(m_pImageDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE); ::DeleteDC(m_pImageDC); } m_pImageDC = ::CreateCompatibleDC(GetContextDC()); if (m_bUseDibPalColors && m_pPal) { ::SelectPalette(m_pImageDC, m_pPal, FALSE); } } void CDCCX::EndDraw() { if (m_pImageDC) { if (m_bUseDibPalColors && m_pPal) ::SelectPalette(m_pImageDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE); ::DeleteDC(m_pImageDC); } m_pImageDC = 0; } void CDCCX::Initialize(BOOL bOwnDC, RECT *pRect, BOOL bInitialPalette, BOOL bNewMemDC) { // First thing, we need to create a document // if no one has bothered assigning us one. if(m_pDocument == NULL) { m_pDocument = new CGenericDoc(); m_bAutoDeleteDocument = TRUE; // We clean up. } // There exists a document. // Let it know which context it can manipulate. GetDocument()->SetContext(this); HDC hdc = GetContextDC(); // Initialize some values which are used in CDC contexts // for drawing purposes. SetMappingMode(hdc); ::SetBkMode(hdc, TRANSPARENT); // Figure out the depth of the CDC. m_iBitsPerPixel = sysInfo.m_iBitsPerPixel; // Now, if the bits per pixel are less than 16, and this device doesn't support // a palette, then we need to set the bits per pixel to a very high value // to emulate true color (so that we don't attempt to use the palette // function later on). // This is the Epson Stylus Color Printer bug fix on Win16. if(m_iBitsPerPixel < 16 && (::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == 0) { // 24 is the largest common denominator which we should be able to set // in order to avoid palette operations. // Uped to 24 from 16 as the Hewlett Packard Laserjet 5L bug fix on Win32. m_iBitsPerPixel = 24; } // Detect if we are going to be using DibPalColors. We only do this if the device // is a palette device and we never do this when printing m_bUseDibPalColors = !IsPrintContext() && (::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE); // Do some stretch blit setup. #ifndef WIN32 ::SetStretchBltMode(hdc, STRETCH_DELETESCANS); #else ::SetStretchBltMode(hdc, COLORONCOLOR); #endif JMCException* exc = NULL; IMGCB* imageLibObj = IMGCBFactory_Create(&exc); m_pImageGroupContext = IL_NewGroupContext(GetContext(), (IMGCBIF *)imageLibObj); GetContext()->img_cx = m_pImageGroupContext; // Need this to be cross platform. IL_AddGroupObserver(m_pImageGroupContext, ImageGroupObserver, (void*)GetContext()); COLORREF rgbColor = prefInfo.m_rgbBackgroundColor; SetTransparentColor(GetRValue(rgbColor), GetGValue(rgbColor), GetBValue(rgbColor)); if (!IsGridCell()) { if(m_iBitsPerPixel < 16) { // Set the transparency to a default color. // This may change below. SetTransparentColor(192, 192, 192); // Set up the per-context palette. // This is per-window since not everything goes to the screen, and therefore // won't always have the screen's attributes. (printing, metafiles DCs, etc). IL_ColorMap * defaultColorMap = IL_NewCubeColorMap(NULL, 0, MAX_IMAGE_PALETTE_ENTRIES+1); if (bInitialPalette) m_pPal = CDCCX::InitPalette(hdc); else // If we don't want to initialize the Palette, use the default palette. m_pPal = WFE_GetUIPalette(NULL); CDCCX::SetColormap(hdc, defaultColorMap, rgbTransparentColor, m_pPal); curColorSpace = IL_CreatePseudoColorSpace(defaultColorMap, MAX_IMAGE_PALETTE_ENTRIES+1, m_iBitsPerPixel); HPALETTE hOldPal = NULL; if(m_pPal) { if ( bInitialPalette) hOldPal = (HPALETTE) ::SelectPalette(hdc, m_pPal, FALSE); else hOldPal = (HPALETTE) ::SelectPalette(hdc, m_pPal, TRUE); int error = RealizePalette(hdc); // In with the new } #ifdef DEBUG_mhwang HWND hwnd = ::GetFocus(); #endif } else { // use RGB value IL_RGBBits colorRGBBits; // Enable true color. if(m_iBitsPerPixel >= 16) { if(m_iBitsPerPixel == 16) { #ifdef XP_WIN32 // If this is Win95 we need to do rounding during quantization of // 24 bpp RGB values to 16 bpp RGB values if (sysInfo.IsWin4_32() == TRUE && SupportsRGB565(hdc) != FALSE && IsPrintContext() == FALSE) { // Metafiles can't handle this hack. // Also, the image lib will force metafiles to share the // same image even though the settings would be slightly different. // Pump us up to 24 bit images in this case. if(GetContextType() == MetaFile) { colorRGBBits.red_shift = 16; colorRGBBits.red_bits = 8; /* Offset for red channel bits. */ colorRGBBits.green_shift = 8; /* Number of bits assigned to green channel. */ colorRGBBits.green_bits = 8; /* Offset for green channel bits. */ colorRGBBits.blue_shift = 0; /* Number of bits assigned to blue channel. */ colorRGBBits.blue_bits = 8; /* Offset for blue channel bits. */ curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24); } else { m_bRGB565 = TRUE; // remember this when building BITMAPINFO struct colorRGBBits.red_shift = 11; colorRGBBits.red_bits = 5; /* Offset for red channel bits. */ colorRGBBits.green_shift = 5; /* Number of bits assigned to green channel. */ colorRGBBits.green_bits = 6; /* Offset for green channel bits. */ colorRGBBits.blue_shift = 0; /* Number of bits assigned to blue channel. */ colorRGBBits.blue_bits = 5; /* Offset for blue channel bits. */ curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 16); } } else { colorRGBBits.red_shift = 10; colorRGBBits.red_bits = 5; /* Offset for red channel bits. */ colorRGBBits.green_shift = 5; /* Number of bits assigned to green channel. */ colorRGBBits.green_bits = 5; /* Offset for green channel bits. */ colorRGBBits.blue_shift = 0; /* Number of bits assigned to blue channel. */ colorRGBBits.blue_bits = 5; /* Offset for blue channel bits. */ curColorSpace =IL_CreateTrueColorSpace(&colorRGBBits, 16); } #else // 16 bpp DIB format isn't supported by all drivers in Win 3.1 colorRGBBits.red_shift = 16; colorRGBBits.red_bits = 8; /* Offset for red channel bits. */ colorRGBBits.green_shift = 8; /* Number of bits assigned to green channel. */ colorRGBBits.green_bits = 8; /* Offset for green channel bits. */ colorRGBBits.blue_shift = 0; /* Number of bits assigned to blue channel. */ colorRGBBits.blue_bits = 8; /* Offset for blue channel bits. */ curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24); #endif } else { colorRGBBits.red_shift = 16; colorRGBBits.red_bits = 8; /* Offset for red channel bits. */ colorRGBBits.green_shift = 8; /* Number of bits assigned to green channel. */ colorRGBBits.green_bits = 8; /* Offset for green channel bits. */ colorRGBBits.blue_shift = 0; /* Number of bits assigned to blue channel. */ colorRGBBits.blue_bits = 8; /* Offset for blue channel bits. */ curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24); } } } GetContext()->color_space = curColorSpace; // Need this to be cross platform. } else { MWContext* cxtx = GetParentContext(); GetContext()->color_space = cxtx->color_space; curColorSpace =cxtx->color_space; IL_AddRefToColorSpace(curColorSpace); m_bRGB565 = CXDC(cxtx)->m_bRGB565; } IL_AddRefToColorSpace(GetContext()->color_space); // Get image prefs on a per context basis. IL_DitherMode ditherMode = IL_Auto; char * prefStr=NULL; PREF_CopyCharPref("images.dither",&prefStr); // Images if (prefStr) { if(!strcmpi(prefStr,"yes")) { ditherMode = IL_Dither; } else if(!strcmpi(prefStr,"no")) { // closest ditherMode = IL_ClosestColor; } else { ditherMode = IL_Auto; } XP_FREE(prefStr); } PRBool bIncremental = ResolveIncrementalImages(); IL_DisplayData displayData; displayData.dither_mode = IL_Auto; if (IsPrintContext()) displayData.display_type = IL_Printer; else displayData.display_type = IL_Console; displayData.color_space = curColorSpace; displayData.progressive_display= bIncremental; IL_SetDisplayMode(m_pImageGroupContext, IL_PROGRESSIVE_DISPLAY | IL_DITHER_MODE | IL_COLOR_SPACE | IL_DISPLAY_TYPE, &displayData); if (bNewMemDC) { if (!IsGridCell()) { // only create the tempary CD only for gird parent. // Ensure our memory DC exists for speedy image draws. m_pImageDC = ::CreateCompatibleDC(hdc); if (m_bUseDibPalColors && m_pPal) { ::SelectPalette(m_pImageDC, m_pPal, FALSE); } } else { MWContext *parentContext = GetParentContext(); m_pImageDC = CXDC(parentContext)->m_pImageDC; } } GetContext()->XpixelsPerPoint = ((double)GetDeviceCaps (GetAttribDC(), LOGPIXELSX)) / 72.0 ; GetContext()->YpixelsPerPoint = ((double)GetDeviceCaps (GetAttribDC(), LOGPIXELSY)) / 72.0 ; #ifdef DEBUG_aliu double dd = ((double)GetDeviceCaps (hdc, LOGPIXELSX)) / 72.0 ; dd = ((double)GetDeviceCaps (hdc, LOGPIXELSY)) / 72.0 ; #endif ReleaseContextDC(hdc); // We optimize those DCs which we know are persistant (don't change or reset // their values) for font caching and other stuff. // As a default, consider all such DC classes as persistent, if not, then // set this value otherwise. // This needs to go at the end of this function, since the mapping mode should // now be correctly set, et al.... m_bOwnDC = bOwnDC; #ifdef LAYERS GetContext()->compositor = NULL; #endif // LAYERS } // Default implementation of incremental image display switch. PRBool CDCCX::ResolveIncrementalImages() { XP_Bool bRetval = prefInfo.m_bAutoLoadImages; return (bRetval) ? PR_TRUE : PR_FALSE; } HPALETTE CDCCX::GetPalette() const { // Return our palette. return(m_pPal); } void CDCCX::ClearFontCache() { // If we're a persistant DC, we need to select a stock object before we release // all the fonts. if(IsClassDC() || IsOwnDC()) { HDC hdc = GetContextDC(); ::SelectObject(hdc, ::GetStockObject(ANSI_FIXED_FONT)); ReleaseContextDC(hdc); // We have no previously selected font. m_pSelectedCachedFont = NULL; m_lastDCWithCachedFont = NULL; } #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else // Tell layout to get rid of all of it's cached FE font data // in the LO_TextAttr. LO_InvalidateFontData(GetDocumentContext()); #endif // Go through our context list of cached fonts and get rid of them all. POSITION rIndexnew = m_cplCachedFontList.GetHeadPosition(); CyaFont *pCachedFont = NULL; while(rIndexnew) { pCachedFont = (CyaFont *)m_cplCachedFontList.GetNext(rIndexnew); if(pCachedFont) { delete pCachedFont; } } // Remove them all from the list. if(!m_cplCachedFontList.IsEmpty()) { m_cplCachedFontList.RemoveAll(); } // Get rid of widget fonts. if(m_pFormFixFont) { VERIFY(::DeleteObject(m_pFormFixFont)); m_pFormFixFont = NULL; } if(m_pFormPropFont) { VERIFY(::DeleteObject(m_pFormPropFont)); m_pFormPropFont = NULL; } } void CDCCX::ClearAllFontCaches() { MWContext *pTraverseContext = NULL; CAbstractCX *pTraverseCX = NULL; XP_List *pTraverse = XP_GetGlobalContextList(); while (pTraverseContext = (MWContext *)XP_ListNextObject(pTraverse)) { if(pTraverseContext != NULL && ABSTRACTCX(pTraverseContext) != NULL) { pTraverseCX = ABSTRACTCX(pTraverseContext); if(pTraverseCX->IsDCContext() == TRUE) { CDCCX *pDCCX = VOID2CX(pTraverseCX, CDCCX); pDCCX->ClearFontCache(); } } } } // size is the size of the font from layout // iBaseSize is the users font size from the encoding // iOffset is the offset based on increment and decrement font double CDCCX::CalcFontPointSize(int size, int iBaseSize, int iOffset) { double dFontSize; if( iBaseSize <=0 ) iBaseSize = 10; /* size += iOffset;*/ if(size < 0) size = 0; if(size > 8) size = 8; switch(size) { case 0: dFontSize = iBaseSize / 2; break; case 1: dFontSize = 7 * iBaseSize / 10; break; case 2: dFontSize = 85 * iBaseSize / 100; break; case 4: dFontSize = 12 * iBaseSize / 10; break; case 5: dFontSize = 3 * iBaseSize / 2; break; case 6: dFontSize = 2 * iBaseSize; break; case 7: dFontSize = 3 * iBaseSize; break; case 8: dFontSize = 4 * iBaseSize; break; case 3: default: dFontSize = iBaseSize; } //if(MMIsText() != TRUE) // for printer scaling to pointsize interface. // dFontSize *= 2.8; //todo this is a hack!! if(GetContext()) dFontSize *= GetContext()->fontScalingPercentage; return dFontSize; } // CalcFontPointSize // Manage DC level font cache: If font is selected into dc, don't do anything. // Otherwise, call SelectNetscapeFont() and cache it into dc. // return 1 if we miss any font in pAttr->font_face list. int CDCCX::SelectNetscapeFontWithCache( HDC hdc, LO_TextAttr *pAttr, CyaFont *& pMyFont ) { // Purpose: Font selector // Arguments: pDC The DC in which to select the font // pAttr Layout attributes by which we select the font. // pSelected This is more of a return value. It sets the reference of // the pointer value ot the font actually selected. // Returns: no meaning, old font is saved in CyaFont. // Comments: // Determine the size of the font and other stuff. // Get the font out of the cache. int returnCode = 0; // assuming we don't miss any font. // #ifdef nofontcache CyaFont *pCachedFont = (CyaFont *)pAttr->FE_Data; pMyFont = pCachedFont; // See if we've already got this font selected if we're a persistant DC. // We'll assume it's in the font cache if so. if(IsOwnDC() == TRUE && m_lastDCWithCachedFont == hdc && m_pSelectedCachedFont) { if( m_pSelectedCachedFont == pCachedFont) { // Simply return, already selected. return( 0 ); } else { // relase the selected font. ReleaseNetscapeFont( hdc, m_pSelectedCachedFont ); m_pSelectedCachedFont = NULL; m_lastDCWithCachedFont = NULL; // fall through to select a font. } } // create font (or use FE_Data cached font) for the text returnCode = SelectNetscapeFont( hdc, pAttr, pMyFont ); if( ! pMyFont->IsEmptyFont() ) { // If this is a persistant DC, then we mark the font currently selected so that // we don't select it again if the same request comes in. // We don't want to do this if this was the memory DC we're dealing with. if(IsOwnDC() == TRUE) { m_lastDCWithCachedFont = hdc; m_pSelectedCachedFont = pMyFont; // pSelectThis; } } //#else // returnCode = SelectNetscapeFont( hdc, pAttr, pMyFont ); //#endif // nofontcache return( returnCode ); } // SelectNetscapeFont() does: // always select the font into dc. // manage FE_Data level cache. // Create the font if not cached, // follow font list and use default font at last. // return 1 if the any font in list not found. // After creation, // cache it into FE_Data, and calculate meanwidth. // link-list the font, so it can be deleted when destroy document. int CDCCX::SelectNetscapeFont( HDC hdc, LO_TextAttr *pAttr, CyaFont *& pMyFont ) { #ifdef MOZ_NGLAYOUT XP_ASSERT(0); return 0; #else // create font for the text and cache it in pAttr->FE_Data. EncodingInfo *pEncoding = theApp.m_pIntlFont->GetEncodingInfo(GetContext()); BOOL bItalic = FALSE; BOOL bFixed = FALSE; int iFontWeight = FW_NORMAL; double dFontSize; int iBaseSize; int iCharset = DEFAULT_CHARSET; // used for Win95 font selection char aFontName[MAXFONTFACENAME]; char * pCharsetStr; int reCode; int returnCode = 0; // assuming we don't miss any font. CyaFont *pCachedFont = (CyaFont *)pAttr->FE_Data; if(pCachedFont != NULL && ! pCachedFont->IsEmptyFont() ) { // It's cached. // use the old font, and select the font. pMyFont = pCachedFont; pMyFont->PrepareDrawText( hdc ); // actually, select the font into hdc return( 0 ); // we don't miss this font. } // retrieve face-name-independent attributes first. if(pAttr->fontmask & LO_FONT_BOLD) { iFontWeight = FW_BOLD; } // font_weight has the highest priority. if( pAttr->font_weight > 0 ) iFontWeight = pAttr->font_weight; if(pAttr->fontmask & LO_FONT_ITALIC) { bItalic = TRUE; } if(pAttr->fontmask & LO_FONT_FIXED) { bFixed = TRUE; } if( bFixed) { iBaseSize = pEncoding->iFixSize; iCharset = pEncoding->iFixCharset; } else { // ! bFixed iBaseSize = pEncoding->iPropSize; iCharset = pEncoding->iPropCharset; } // Map the base size to the real font size. dFontSize = CalcFontPointSize(pAttr->size, iBaseSize, m_iOffset); // pAttr->point_size has the highest priority. if( pAttr->point_size > 0 ) { dFontSize = pAttr->point_size; } // save the encording flag in font, so it will use textOutW() for Unicode. // refer to BOOL CIntlWin::TextOut() in file intlwin.cpp // INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext)) char *pEncordingStr = NULL; int isUnicode = 0; #ifdef XP_WIN32 if ( CIntlWin::UseUnicodeFontAPI( pEncoding->iCSID )) { // set the encording to use ::TextOutW() pEncordingStr = "Unicode"; isUnicode = 1; } #endif int nUnderline = nfUnderlineDontCare ; if(pAttr->attrmask & LO_ATTR_ANCHOR) { XP_Bool prefBool = prefInfo.m_bUnderlineAnchors; // ? prefInfo.m_bUnderlineAnchors->m_Value.xp_bool : TRUE; if(prefBool) nUnderline = nfUnderlineYes; } if(pAttr->attrmask & LO_ATTR_UNDERLINE) { nUnderline = nfUnderlineYes; } pMyFont = new CyaFont(); // If a font name is listed, use that instead. BOOL bUseDefault = TRUE; if(pAttr->font_face) { // Go through the comma delimeted list, and find one that we have. char wantedFontName[MAXFONTFACENAME]; char *pFontName = NULL; int offSet = 0; do { offSet = FEU_ExtractCommaDilimetedFontName(pAttr->font_face, offSet, wantedFontName ); // for(int iTraverse = 1; pExtracted = FEU_ExtractCommaDilimetedString(pAttr->font_face, iTraverse); iTraverse++) if( offSet > 0 && *wantedFontName != 0) { pFontName = theGlobalNSFont.converGenericFont(wantedFontName); strcpy(aFontName, pFontName); if(CIntlWin::UseUnicodeFontAPI(pEncoding->iCSID)) { iCharset = DEFAULT_CHARSET; } // On Win95, charset info is important for Wingdings font if (sysInfo.m_bWin4 && (strcmpi(aFontName, "wingdings") == 0)) iCharset = DEFAULT_CHARSET; // web font use string for charSet pCharsetStr = theGlobalNSFont.convertToFmiCharset( iCharset ); if (isUnicode == 0 ) { pEncordingStr = pCharsetStr; } // Create the font. reCode = pMyFont->CreateNetscapeFont( GetContext(), hdc, // HDC hDC, aFontName, // char *FmiName, pCharsetStr, // char *FmiCharset, pEncordingStr, // char *FmiEncoding, iFontWeight, // int FmiWeight, bFixed?nfSpacingMonospaced:nfSpacingProportional, // int FmiPitch, bItalic?nfStyleItalic:nfStyleNormal, // int FmiStyle, nUnderline, // int FmiUnderline, (pAttr->attrmask & LO_ATTR_STRIKEOUT) ? nfStrikeOutYes : nfStrikeOutDontCare, // int FmiStrikeOut, 0, // int FmiResolutionX, ::GetDeviceCaps(GetAttribDC(), LOGPIXELSY), // int FmiResolutionY, dFontSize // int fontHeight // not a fmi field ); //if( theGlobalNSFont.HasFaceName( hdc, pExtracted)) // Use this. if( reCode == FONTERR_OK ) { bUseDefault = FALSE; // we got the font! } else { // remenber there is font face name not found, returnCode = 1; } } // Our responsibility to clean this up. // XP_FREE(pExtracted); // If we've set that we're using a font, get out. if(!bUseDefault) { break; } } while ( offSet > 0 ); // do offSet = FEU_ExtractCommaDilimetedFontName() ... } // if(pAttr->font_face) if(bUseDefault) { if( bFixed) strcpy(aFontName, pEncoding->szFixName); else // ! bFixed strcpy(aFontName, pEncoding->szPropName); if(CIntlWin::UseUnicodeFontAPI(pEncoding->iCSID)) { iCharset = DEFAULT_CHARSET; } // On Win95, charset info is important for Wingdings font if (sysInfo.m_bWin4 && (strcmpi(aFontName, "wingdings") == 0)) iCharset = DEFAULT_CHARSET; // web font use string for charSet pCharsetStr = theGlobalNSFont.convertToFmiCharset( iCharset ); if (isUnicode == 0 ) { pEncordingStr = pCharsetStr; } // Create the font. reCode = pMyFont->CreateNetscapeFont( GetContext(), hdc, // HDC hDC, aFontName, // char *FmiName, pCharsetStr, // char *FmiCharset, pEncordingStr, // char *FmiEncoding, iFontWeight, // int FmiWeight, bFixed?nfSpacingMonospaced:nfSpacingProportional, // int FmiPitch, bItalic?nfStyleItalic:nfStyleNormal, // int FmiStyle, nUnderline, // int FmiUnderline, (pAttr->attrmask & LO_ATTR_STRIKEOUT) ? nfStrikeOutYes : nfStrikeOutDontCare, // int FmiStrikeOut, 0, // int FmiResolutionX, ::GetDeviceCaps(GetAttribDC(), LOGPIXELSY), // int FmiResolutionY, dFontSize // int fontHeight // not a fmi field ); } if( FONTERR_OK != reCode ) { // user selected default font failed, use hardcoded default font iCharset = DEFAULT_CHARSET; // web font use string for charSet pCharsetStr = theGlobalNSFont.convertToFmiCharset( iCharset ); if (isUnicode == 0 ) { pEncordingStr = pCharsetStr; } // get the face name #ifdef _WIN32 LOGFONT theLogFont; CFont *pCFont= CFont::FromHandle((HFONT)GetStockObject(bFixed?ANSI_FIXED_FONT:ANSI_VAR_FONT)); pCFont->GetLogFont( &theLogFont ); strncpy(aFontName, theLogFont.lfFaceName,LF_FACESIZE); #else strncpy(aFontName, ( bFixed? "Courier New" : "Times New Roman" ) ,LF_FACESIZE); #endif // Create the font. reCode = pMyFont->CreateNetscapeFont( GetContext(), hdc, // HDC hDC, aFontName, // char *FmiName, pCharsetStr, // char *FmiCharset, pEncordingStr, // char *FmiEncoding, iFontWeight, // int FmiWeight, bFixed?nfSpacingMonospaced:nfSpacingProportional, // int FmiPitch, bItalic?nfStyleItalic:nfStyleNormal, // int FmiStyle, nUnderline, // int FmiUnderline, (pAttr->attrmask & LO_ATTR_STRIKEOUT) ? nfStrikeOutYes : nfStrikeOutDontCare, // int FmiStrikeOut, 0, // int FmiResolutionX, ::GetDeviceCaps(GetAttribDC(), LOGPIXELSY), // int FmiResolutionY, dFontSize // int fontHeight // not a fmi field ); } // if( FONTERR_OK != reCode ) real problem, todo show dialog to user!!! // Select the font. pMyFont->PrepareDrawText( hdc ); // actually, select the font into hdc pMyFont->CalculateMeanWidth( hdc, isUnicode); // and cache it in pAttr->FE_Data. // Cache this font for future usage. // First, make sure that the text attribute points to it. pAttr->FE_Data = (void *)pMyFont; // Second, add it to our context list of fonts (so we know to delete it later). m_cplCachedFontList.AddTail((void *)pMyFont); // pSelectThis return( returnCode ); #endif /* MOZ_NGLAYOUT */ } // HFONT CDCCX::SelectNetscapeFont() void CDCCX::ReleaseNetscapeFontWithCache(HDC hdc, CyaFont * pNetscapeFont) { //#ifdef nofontcache if( IsOwnDC() == TRUE ) return; m_pSelectedCachedFont = NULL; m_lastDCWithCachedFont = NULL; //#endif ReleaseNetscapeFont(hdc, pNetscapeFont); } void CDCCX::ReleaseNetscapeFont(HDC hdc, CyaFont * pNetscapeFont) { #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else pNetscapeFont->EndDrawText( hdc ); // restore the old font. #endif /* MOZ_NGLAYOUT */ } // m_iOffset can be at most 8 or at least -8 based on the values in // CalcFontPointSize; void CDCCX::ChangeFontOffset(int iIncrementor) { /* BOOL bDontReload = (m_iOffset == 8 && iIncrementor >= 0) || (m_iOffset == -8 && iIncrementor <= 0); m_iOffset += iIncrementor; if(m_iOffset < -8) m_iOffset = -8; else if(m_iOffset > 8) m_iOffset = 8; if(!bDontReload)*/ m_iOffset += iIncrementor; if(GetContext()){ #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else GetContext()->fontScalingPercentage = LO_GetScalingFactor(m_iOffset); #endif } NiceReload(); } void CDCCX::ExtendCoord(LTRB& Rect) { int32 lOrgX, lOrgY; GetDrawingOrigin(&lOrgX, &lOrgY); Rect.left += lOrgX; Rect.top += lOrgY; Rect.right += lOrgX; Rect.bottom += lOrgY; } BOOL CDCCX::ResolveElement(LTRB& Rect, int32 x, int32 y, int32 x_offset, int32 y_offset, int32 width, int32 height) { BOOL bRetval = TRUE; // First, figure the coordinates. Rect.left = x + x_offset - m_lOrgX; Rect.top = y + y_offset - m_lOrgY; Rect.right = Rect.left + width; Rect.bottom = Rect.top + height; ExtendCoord(Rect); // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } return bRetval; } BOOL CDCCX::ResolveElement(LTRB& Rect, LO_TextStruct *pText, int iLocation, int32 lStartPos, int32 lEndPos, int iClear) { #ifdef MOZ_NGLAYOUT XP_ASSERT(0); return FALSE; #else BOOL bRetval = TRUE; // Subtext, in order to be considered at all, must first pass the text resolution. if(ResolveElement(Rect, pText->x, pText->y, pText->x_offset, pText->y_offset,pText->width, pText->height)) { // Adjust the coordinates further for the specific subtext we're going to be // drawing. // This means we actually have to size the text.... HDC hdc = GetContextDC(); CyaFont *pMyFont; SelectNetscapeFontWithCache( hdc, pText->text_attr, pMyFont ); CSize sz; ResolveTextExtent(hdc, (const char *)pText->text, CASTINT(lStartPos), &sz, pMyFont); Rect.left += sz.cx; ResolveTextExtent(hdc, (const char *)pText->text + lStartPos, CASTINT(lEndPos - lStartPos + 1), &sz, pMyFont); Rect.right = Rect.left + sz.cx; Rect.bottom = Rect.top + sz.cy; ReleaseNetscapeFontWithCache( hdc, pMyFont ); ReleaseContextDC(hdc); // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } } else if(CanBlockDisplay()) { // Didn't pass even the normal text filter. bRetval = FALSE; } return(bRetval); #endif /* MOZ_NGLAYOUT */ } /* * Note that this was brought back, since form element positions are * expressed in document coordinates, not layer coordinates, so the * standard ResolveElement techniques will not work. */ BOOL CDCCX::ResolveElement(LTRB& Rect, LO_FormElementStruct *pFormElement) { BOOL bRetval = TRUE; // First, figure the coordinates. Rect.left = pFormElement->x + pFormElement->x_offset - m_lOrgX; Rect.top = pFormElement->y + pFormElement->y_offset - m_lOrgY; Rect.right = Rect.left + pFormElement->width; Rect.bottom = Rect.top + pFormElement->height; /* Don't call ExtendCoord() for forms. Form element positions are in document coordinates, not layer coordinates. */ // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } return(bRetval); } BOOL CDCCX::ResolveElement(LTRB& Rect, NI_Pixmap *pImage, int32 lX, int32 lY, int32 orgx, int32 orgy, uint32 ulWidth, uint32 ulHeight, int32 lScaleWidth, int32 lScaleHeight) { BOOL bRetval = TRUE; /* Use the size of the image if size not provided. */ if(ulWidth == 0) { ulWidth = pImage->header.width; } if(ulHeight == 0) { ulHeight = pImage->header.height; } /* Scaled size overrides further if this is a print context.*/ if(IsPrintContext()) { if(lScaleWidth) { ulWidth = (uint32)lScaleWidth; } if(lScaleHeight) { ulHeight = (uint32)lScaleHeight; } } Rect.left = orgx + lX - m_lOrgX; Rect.top = orgy + lY - m_lOrgY; ExtendCoord(Rect); if (Rect.top < 0 && lX) Rect.top = 0; if (Rect.left < 0 && lY) Rect.left = 0; Rect.right = Rect.left + ulWidth; Rect.bottom = Rect.top + ulHeight; return(bRetval); } BOOL CDCCX::ResolveElement(LTRB& Rect, LO_TableStruct *pTable, int iLocation) { BOOL bRetval = TRUE; // First, figure the coordinates. Rect.left = pTable->x + pTable->x_offset - m_lOrgX; Rect.top = pTable->y + pTable->y_offset - m_lOrgY; Rect.right = Rect.left + pTable->width; Rect.bottom = Rect.top + pTable->height; // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } return(bRetval); } BOOL CDCCX::ResolveElement(LTRB& Rect, LO_SubDocStruct *pSubDoc, int iLocation) { BOOL bRetval = TRUE; // First, figure the coordinates. Rect.left = pSubDoc->x + pSubDoc->x_offset - m_lOrgX; Rect.top = pSubDoc->y + pSubDoc->y_offset - m_lOrgY; Rect.right = Rect.left + pSubDoc->width; Rect.bottom = Rect.top + pSubDoc->height; // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } return(bRetval); } BOOL CDCCX::ResolveElement(LTRB& Rect, LO_CellStruct *pCell, int iLocation) { BOOL bRetval = TRUE; // First, figure the coordinates. Rect.left = pCell->x + pCell->x_offset - m_lOrgX; Rect.top = pCell->y + pCell->y_offset - m_lOrgY; Rect.right = Rect.left + pCell->width; Rect.bottom = Rect.top + pCell->height; // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } return(bRetval); } BOOL CDCCX::ResolveElement(LTRB& Rect, LO_EmbedStruct *pEmbed, int iLocation, Bool bWindowed) { BOOL bRetval = TRUE; // First, figure the coordinates. Rect.left = -m_lOrgX; Rect.top = -m_lOrgY; // For windowed embeds, we only need the position of the embed, // and we ignore the layer origin. For windowless embeds, we only // need the layer origin, and not the position of the embed. if (bWindowed) { Rect.left += pEmbed->objTag.x + pEmbed->objTag.x_offset + pEmbed->objTag.border_width; Rect.top += pEmbed->objTag.y + pEmbed->objTag.y_offset + pEmbed->objTag.border_width; } Rect.right = Rect.left + pEmbed->objTag.width; Rect.bottom = Rect.top + pEmbed->objTag.height; if (!bWindowed) ExtendCoord(Rect); // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } return(bRetval); } BOOL CDCCX::ResolveElement(LTRB& Rect, LO_LinefeedStruct *pLineFeed, int iLocation) { BOOL bRetval = TRUE; // First, figure the coordinates. Rect.left = pLineFeed->x + pLineFeed->x_offset - m_lOrgX; Rect.top = pLineFeed->y + pLineFeed->y_offset - m_lOrgY; Rect.right = Rect.left + pLineFeed->width; Rect.bottom = Rect.top + pLineFeed->height; // Return FALSE if this doesn't fall into view of the context. if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) { if(CanBlockDisplay()) { bRetval = FALSE; } } return(bRetval); } inline BOOL CDCCX::ResolveLineSolid() { // Don't default to all solid lines. return(FALSE); } COLORREF CDCCX::ResolveTextColor(LO_TextAttr *pAttr) { // Purpose: Determine the Forground color of the attribute. // Arguments: pAttr The attributes from which we will obtain the color. // Returns: COLORREF The color. // Comments: Override this if you need finer control over the selections // of color such as printing. // Revision History: // 06-09-95 created GAB // Default implementation simply returns the color requested. Make sure that // we get the closest match in the palette and not one of the static system // colors. or'ing 0x02000000L in here is easier than finding every occurence // of SetTextColor downstream if(pAttr != NULL) { return(0x02000000L | RGB(pAttr->fg.red, pAttr->fg.green, pAttr->fg.blue)); } else { return(RGB(0,0,0)); } } // // if we are not in true-color mode snap the color to the palette // otherwise they will get dithered to the windows 16-color palette // in the view's EraseBackground method // COLORREF CDCCX::ResolveBGColor(unsigned uRed, unsigned uGreen, unsigned uBlue) { int index = 0; if ((m_iBitsPerPixel <= 8) && m_pPal) { index = ::GetNearestPaletteIndex(m_pPal, RGB(uRed, uGreen, uBlue)); PALETTEENTRY palEntry; ::GetPaletteEntries(m_pPal, index, 1, &palEntry); uRed = palEntry.peRed; uGreen = palEntry.peGreen; uBlue = palEntry.peBlue; } return(RGB(uRed, uGreen, uBlue)); } BOOL CDCCX::ResolveHRSolid(LO_HorizRuleStruct *pHorizRule) { // Determine if an HR is to be solid or 3D. // Override this if you need to specifically control the display of // HRs. if((pHorizRule->ele_attrmask & LO_ELE_SHADED) == LO_ELE_SHADED && pHorizRule->thickness > 1) { return(FALSE); } return(TRUE); } inline COLORREF CDCCX::ResolveDarkLineColor() { // By default, return the dark color. // Override if you need to control HR colors. return(m_rgbDarkColor); } inline COLORREF CDCCX::ResolveLightLineColor() { // By default, return the light color. // Override if you need to control HR colors. return(m_rgbLightColor); } COLORREF CDCCX::ResolveBorderColor(LO_TextAttr *pAttr) { // Default is to simply return the color requested. // Override if you need to control border display. if(pAttr != NULL) { return(RGB(pAttr->fg.red, pAttr->fg.green, pAttr->fg.blue)); } else { return(RGB(0,0,0)); } } COLORREF CDCCX::ResolveLOColor(LO_Color *color) { // Default is to simply return the color requested. // Override if you need to control border display. if(color != NULL) { return(RGB(color->red, color->green, color->blue)); } else { return(RGB(0,0,0)); } } void CDCCX::ResolveTransparentColor(unsigned uRed, unsigned uGreen, unsigned uBlue) { // Sets the transparency color of images. // This in most cases is the same as the background color. // Override this if you take special interest in controlling the background color. int iIndex = 0; IL_IRGB *rgbTransparent = GetContext()->transparent_pixel; if ((m_iBitsPerPixel <= 8) && m_pPal) { iIndex = ::GetNearestPaletteIndex(m_pPal, m_rgbBackgroundColor); curColorSpace->cmap.index[MAX_IMAGE_PALETTE_ENTRIES] = iIndex; } // Simply let the image lib know what's up. if (!rgbTransparent) { rgbTransparent = XP_NEW_ZAP(IL_IRGB); GetContext()->transparent_pixel = rgbTransparent; } rgbTransparent->index = MAX_IMAGE_PALETTE_ENTRIES; rgbTransparent->red = uRed; rgbTransparent->green = uGreen; rgbTransparent->blue = uBlue; } // rgbLight is used to render the top/left edges, and rgbDark is used to // render the bottom/right edges void CDCCX::Display3DBox(LTRB& Rect, COLORREF rgbLight, COLORREF rgbDark, int32 lWidth, BOOL bAdjust) { HDC hDC = GetContextDC(); // Adjust the y value by half the height. We'll need to move it back // to the original position, since we have a reference to the rect. int32 lAdjust = 0; if(bAdjust == TRUE) { // This should only happen with HRs! lAdjust = Rect.Height() / 2; if(MMIsText() == FALSE) { Rect.top -= lAdjust; Rect.bottom -= lAdjust; } } else { // When bAdjust is false, this means we are dealing with a table/cell/subdoc. // To properly draw these, we need to shrink the rect on the right and bottom // by the width. lAdjust = lWidth; Rect.right -= lAdjust; Rect.bottom -= lAdjust; } // If there's a thick border then miter the join where the different // colors meet if(lWidth > Pix2TwipsX(1) && ResolveLineSolid() == FALSE) { HPEN hOldPen = (HPEN)::SelectObject(hDC, GetStockObject(NULL_PEN)); POINT aPoints[6]; HBRUSH hbDark, hbLight, hOldBrush; // Make sure that in 256 color mode we get a PALETTE RGB color hbDark = ::CreateSolidBrush(0x02000000L | rgbDark); hbLight = ::CreateSolidBrush(0x02000000L | rgbLight); // Map all the points. // Left and top. aPoints[0].x = CASTINT(Rect.left + lWidth); aPoints[0].y = CASTINT(Rect.top + lWidth); aPoints[1].x = CASTINT(Rect.left + lWidth); aPoints[1].y = CASTINT(Rect.bottom); aPoints[2].x = CASTINT(Rect.left); aPoints[2].y = CASTINT(Rect.bottom + lWidth); aPoints[3].x = CASTINT(Rect.left); aPoints[3].y = CASTINT(Rect.top); aPoints[4].x = CASTINT(Rect.right + lWidth); aPoints[4].y = CASTINT(Rect.top); aPoints[5].x = CASTINT(Rect.right); aPoints[5].y = CASTINT(Rect.top + lWidth); hOldBrush = (HBRUSH)::SelectObject(hDC, hbLight); ::Polygon(hDC, aPoints, 6); // Right and bottom. aPoints[0].x = CASTINT(Rect.right); aPoints[0].y = CASTINT(Rect.bottom); aPoints[3].x = CASTINT(Rect.right + lWidth); aPoints[3].y = CASTINT(Rect.bottom + lWidth); ::SelectObject(hDC, hbDark); ::Polygon(hDC, aPoints, 6); ::SelectObject(hDC, hOldPen); ::SelectObject(hDC, hOldBrush); VERIFY(::DeleteObject(hbDark)); VERIFY(::DeleteObject(hbLight)); } else { HBRUSH hbLight, hbDark, hOldBrush; // Left/top edges hbLight = ::CreateSolidBrush(0x02000000L | rgbLight); hOldBrush = (HBRUSH)::SelectObject(hDC, hbLight); ::PatBlt(hDC, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right - Rect.left), lWidth, PATCOPY); ::PatBlt(hDC, CASTINT(Rect.left), CASTINT(Rect.top), lWidth, CASTINT(Rect.bottom - Rect.top), PATCOPY); ::SelectObject(hDC, hOldBrush); VERIFY(::DeleteObject(hbLight)); // Bottom/right edges hbDark = ::CreateSolidBrush(0x02000000L | rgbDark); hOldBrush = (HBRUSH)::SelectObject(hDC, hbDark); ::PatBlt(hDC, CASTINT(Rect.left), CASTINT(Rect.bottom), CASTINT(Rect.right - Rect.left), lWidth, PATCOPY); ::PatBlt(hDC, CASTINT(Rect.right), CASTINT(Rect.top), lWidth, CASTINT(Rect.bottom - Rect.top) + 1, PATCOPY); ::SelectObject(hDC, hOldBrush); VERIFY(::DeleteObject(hbDark)); } // Reposition. if(bAdjust == TRUE) { // HRs if(MMIsText() == FALSE) { Rect.top += lAdjust; Rect.bottom += lAdjust; } } else { // Table/cell/subdoc Rect.right += lAdjust; Rect.bottom += lAdjust; } ReleaseContextDC(hDC); } static HPEN CreateStyledPen(COLORREF color, int nWidth, int nPenStyle) { #ifdef _WIN32 LOGBRUSH lb; DWORD dwPenStyle; #endif #ifdef _WIN32 lb.lbStyle = 0; // ignored lb.lbColor = 0x02000000L | color; lb.lbStyle = 0; // ignored dwPenStyle = PS_GEOMETRIC | PS_ENDCAP_SQUARE | PS_JOIN_MITER; return ::ExtCreatePen(dwPenStyle | nPenStyle, nWidth, &lb, 0, NULL); #else return ::CreatePen(nPenStyle, nWidth, 0x02000000L | color); #endif } static void DisplaySpecialBorder(HDC hDC, RECT &r, COLORREF color, int iWidth, BOOL bSolid) { HPEN hPen = ::CreatePen(PS_DOT, 1, 0x02000000L | color); HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); HBRUSH hOldBrush = (HBRUSH) ::SelectObject(hDC, ::GetStockObject(NULL_BRUSH)); ::SetBkMode(hDC, TRANSPARENT); for( int i = 0; i < iWidth; i++ ) { ::Rectangle(hDC, r.left, r.top, r.right, r.bottom); ::InflateRect(&r, -1, -1); } ::SelectObject(hDC, hOldPen); ::SelectObject(hDC, hOldBrush); VERIFY(::DeleteObject(hPen)); } static void DisplaySolidBorder(HDC hDC, RECT &r, COLORREF color, LTRB &widths) { // See if all border edges are the same width if (widths.left == widths.top && widths.left == widths.right && widths.left == widths.bottom) { HPEN hPen = ::CreatePen(PS_INSIDEFRAME, widths.left, 0x02000000L | color); HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); HBRUSH hOldBrush = (HBRUSH) ::SelectObject(hDC, ::GetStockObject(NULL_BRUSH)); // Draw it using a single rectangle call ::Rectangle(hDC, r.left, r.top, r.right, r.bottom); ::SelectObject(hDC, hOldPen); ::SelectObject(hDC, hOldBrush); VERIFY(::DeleteObject(hPen)); } else { HBRUSH hBrush = ::CreateSolidBrush(0x02000000L | color); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush); // Draw each of the individual edges using PatBlt if (widths.left > 0) ::PatBlt(hDC, r.left, r.top, widths.left, r.bottom - r.top, PATCOPY); if (widths.top > 0) ::PatBlt(hDC, r.left, r.top, r.right - r.left, widths.top, PATCOPY); if (widths.right > 0) ::PatBlt(hDC, r.right - widths.right, r.top, widths.right, r.bottom - r.top, PATCOPY); if (widths.bottom > 0) ::PatBlt(hDC, r.left, r.bottom - widths.bottom, r.right - r.left, widths.bottom, PATCOPY); ::SelectObject(hDC, hOldBrush); VERIFY(::DeleteObject(hBrush)); } } static void DisplayDoubleBorder(HDC hDC, RECT &r, COLORREF color, LTRB &widths) { LTRB strokeWidths; // Compute the stroke width for each of the edges strokeWidths.left = (widths.left + 1) / 3; strokeWidths.top = (widths.top + 1) / 3; strokeWidths.right = (widths.right + 1) / 3; strokeWidths.bottom = (widths.bottom + 1) / 3; // Draw the outer lines DisplaySolidBorder(hDC, r, color, strokeWidths); // Adjust the rectangle to be the inner rectangle r.left += CASTINT(widths.left - strokeWidths.left); r.top += CASTINT(widths.top - strokeWidths.top); r.right -= CASTINT(widths.right - strokeWidths.right); r.bottom -= CASTINT(widths.bottom - strokeWidths.bottom); // Draw the inner lines DisplaySolidBorder(hDC, r, color, strokeWidths); } // rgbLight is used to render the top/left edges, and rgbDark is used to // render the bottom/right edges void CDCCX::Display3DBorder(LTRB& Rect, COLORREF rgbLight, COLORREF rgbDark, LTRB &widths) { if (widths.left == widths.top && widths.left == widths.right && widths.left == widths.bottom) { // This routine is faster especially for one-pixel thick lines Display3DBox(Rect, rgbLight, rgbDark, widths.left, FALSE); } else { HDC hDC = GetContextDC(); HPEN hOldPen = (HPEN)::SelectObject(hDC, GetStockObject(NULL_PEN)); POINT aPoints[6]; HBRUSH hbDark, hbLight, hOldBrush; // Make sure that in 256 color mode we get a PALETTE RGB color hbDark = ::CreateSolidBrush(0x02000000L | rgbDark); hbLight = ::CreateSolidBrush(0x02000000L | rgbLight); // Map all the points. Draw it inside of the rect. Draw the left // and top edges first aPoints[0].x = CASTINT(Rect.left + widths.left); aPoints[0].y = CASTINT(Rect.top + widths.top); aPoints[1].x = CASTINT(Rect.left + widths.left); aPoints[1].y = CASTINT(Rect.bottom - widths.bottom); aPoints[2].x = CASTINT(Rect.left); aPoints[2].y = CASTINT(Rect.bottom); aPoints[3].x = CASTINT(Rect.left); aPoints[3].y = CASTINT(Rect.top); aPoints[4].x = CASTINT(Rect.right); aPoints[4].y = CASTINT(Rect.top); aPoints[5].x = CASTINT(Rect.right - widths.right); aPoints[5].y = CASTINT(Rect.top + widths.top); hOldBrush = (HBRUSH)::SelectObject(hDC, hbLight); ::Polygon(hDC, aPoints, 6); // Right and bottom. aPoints[0].x = CASTINT(Rect.right - widths.right); aPoints[0].y = CASTINT(Rect.bottom - widths.bottom); aPoints[3].x = CASTINT(Rect.right); aPoints[3].y = CASTINT(Rect.bottom); ::SelectObject(hDC, hbDark); ::Polygon(hDC, aPoints, 6); ::SelectObject(hDC, hOldPen); ::SelectObject(hDC, hOldBrush); VERIFY(::DeleteObject(hbDark)); VERIFY(::DeleteObject(hbLight)); ReleaseContextDC(hDC); } } // Adjust border for selection feedback of table or cell // Returns width used in excess of table border (into space between cells) // because that will have to be restored to background when removing selection int32 SetSelectionBorder(int32 *pWidth, int32 iCellSpacing) { int32 iOldWidth = *pWidth; int32 iExcess = 0; // Allow wider selection if border is very large int32 iMaxWidth = 2*ED_SELECTION_BORDER; // *pWidth = min(*pWidth,iMaxWidth); // Also use spacing between cells if less than maximum if( *pWidth < 6 ) { iExcess = min(iCellSpacing, 6-*pWidth); *pWidth += iExcess; } return iExcess; } int32 CDCCX::DisplayTableBorder(LTRB& Rect, LO_TableStruct *pTable) { COLORREF rgbBorder = ResolveLOColor(&pTable->border_color); COLORREF rgbLight, rgbDark; HDC hDC; RECT r = {CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)}; LTRB insetRect; LTRB borderWidths(pTable->border_left_width, pTable->border_top_width, pTable->border_right_width, pTable->border_bottom_width); //TRACE0("DisplayTableBorder\n"); // Only the Editor sets table elements as selected, so we don't need EDT_IS_EDITOR if( pTable->ele_attrmask & LO_ELE_SELECTED ) { // Use the selection background color to draw a solid border COLORREF rgbBorder; wfe_GetSelectionColors(m_rgbBackgroundColor, NULL, &rgbBorder); hDC = GetContextDC(); // Use same border thickness for all sides - use the minimum Table border thickness // and the space between cells if available int32 iBorderWidth = min(borderWidths.bottom,min(borderWidths.top,min(borderWidths.left, borderWidths.right))); SetSelectionBorder(&iBorderWidth, pTable->inter_cell_space); borderWidths.left = borderWidths.right = borderWidths.top = borderWidths.bottom = iBorderWidth; // Show a solid border up to twice default selection border as the selection feedback DisplaySolidBorder(hDC, r, rgbBorder, borderWidths); ReleaseContextDC(hDC); // Return actual border width used return iBorderWidth; } else { if (pTable->border_style == BORDER_GROOVE || pTable->border_style == BORDER_RIDGE || pTable->border_style == BORDER_INSET || pTable->border_style == BORDER_OUTSET) { // Compute the 3D colors to use. If the border color is the same as the background // color then just use the light/dark colors we've already computed if (rgbBorder == m_rgbBackgroundColor) { rgbLight = m_rgbLightColor; rgbDark = m_rgbDarkColor; } else { Compute3DColors(rgbBorder, rgbLight, rgbDark); } } hDC = GetContextDC(); switch (pTable->border_style) { case BORDER_NONE: break; case BORDER_DOTTED: case BORDER_DASHED: case BORDER_SOLID: // hDC = GetContextDC(); DisplaySolidBorder(hDC, r, rgbBorder, borderWidths); // ReleaseContextDC(hDC); break; case BORDER_DOUBLE: // hDC = GetContextDC(); DisplayDoubleBorder(hDC, r, rgbBorder, borderWidths); // ReleaseContextDC(hDC); break; case BORDER_GROOVE: // This is done as a sunken outer border with a raised inner // border. Windows group boxes have this appearance borderWidths.left /= 2; borderWidths.top /= 2; borderWidths.right /= 2; borderWidths.bottom /= 2; Display3DBorder(Rect, rgbDark, rgbLight, borderWidths); insetRect.left = Rect.left + borderWidths.left; insetRect.top = Rect.top + borderWidths.top; insetRect.right = Rect.right - borderWidths.right; insetRect.bottom = Rect.bottom - borderWidths.bottom; Display3DBorder(insetRect, rgbLight, rgbDark, borderWidths); break; case BORDER_RIDGE: // This is done as a raised outer border with a sunken inner border borderWidths.left /= 2; borderWidths.top /= 2; borderWidths.right /= 2; borderWidths.bottom /= 2; Display3DBorder(Rect, rgbLight, rgbDark, borderWidths); insetRect.left = Rect.left + borderWidths.left; insetRect.top = Rect.top + borderWidths.top; insetRect.right = Rect.right - borderWidths.right; insetRect.bottom = Rect.bottom - borderWidths.bottom; Display3DBorder(insetRect, rgbDark, rgbLight, borderWidths); break; case BORDER_INSET: // This is what Windows refers to as a sunken border Display3DBorder(Rect, rgbDark, rgbLight, borderWidths); break; case BORDER_OUTSET: // This is what Windows refers to as a raised border Display3DBorder(Rect, rgbLight, rgbDark, borderWidths); break; default: ASSERT(FALSE); break; } } return 0; } void CDCCX::EditorDisplayZeroWidthBorder(LTRB& Rect, BOOL bSelected){ // Show a 1-pixel dotted border. Used in the editor // Use the same color we would use for a selection background, // but use the opposite color if we will be selecting, // so NOT opperation yields a contrasting color relative to background COLORREF rgbColor; wfe_GetSelectionColors(m_rgbBackgroundColor, NULL, &rgbColor); HDC hdc = GetContextDC(); // Use dotted line if not selected, or solid if selecting HPEN pPen = ::CreatePen(bSelected ? PS_SOLID : PS_DOT, 1, rgbColor); HPEN pOldPen = (HPEN)::SelectObject(hdc, pPen); HBRUSH hOldBrush = (HBRUSH) ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); ::Rectangle(hdc, Rect.left, Rect.top, Rect.right, Rect.bottom); ::SelectObject(hdc, hOldBrush); ::SelectObject(hdc, pOldPen); ReleaseContextDC(hdc); VERIFY(::DeleteObject(pPen)); } void CDCCX::DrawRectBorder(LTRB& Rect, COLORREF rgbColor, int32 lWidth) { // This should only be called for display of the border for images, and embeds. HDC hdc = GetContextDC(); // The border goes outside of the rectangle, so we need to adjust the // rectangle accordingly int32 lAdjust = lWidth / 2; int32 rAdjust = lAdjust; if(lWidth % 2) { lAdjust += Pix2TwipsX(1); } rAdjust += Pix2TwipsX(1); LTRB rect(Rect.left - lAdjust, Rect.top - lAdjust, Rect.right + rAdjust, Rect.bottom + rAdjust); SafeSixteen(rect); HPEN hBorder = ::CreatePen(PS_SOLID, CASTINT(lWidth), rgbColor); HPEN hOldPen = (HPEN)::SelectObject(hdc, hBorder); HBRUSH hOldBrush = (HBRUSH) ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); // Draw it. ::Rectangle(hdc, CASTINT(rect.left), CASTINT(rect.top), CASTINT(rect.right), CASTINT(rect.bottom)); ::SelectObject(hdc, hOldBrush); ::SelectObject(hdc, hOldPen); VERIFY(::DeleteObject(hBorder)); ReleaseContextDC(hdc); } void CDCCX::DisplaySelectionFeedback(uint16 ele_attrmask, const LTRB& rect) { BOOL bSelect = ele_attrmask & LO_ELE_SELECTED; // Don't do anything if unselecting any other objects // since these will be completely redrawn. if ( !bSelect || !EDT_IS_EDITOR(GetContext()) ) { return; } LTRB Rect(rect.left, rect.top, rect.right, rect.bottom); SafeSixteen(Rect); // Draw selection feedback. It has to fit entirely within rect, because // when it's turned off, all that will happen is that it won't be drawn. HDC hdc = GetContextDC(); int32 rWidth = Rect.right - Rect.left; int32 rHeight = Rect.bottom - Rect.top; if ( rWidth <= (ED_SELECTION_BORDER*2) || rHeight <= (ED_SELECTION_BORDER*2) ) { // Too narrow to draw frame. Draw solid. RECT r; ::SetRect(&r, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); ::InvertRect(hdc, &r); } else { // Frame. LTRB inner(Rect.left + ED_SELECTION_BORDER, Rect.top + ED_SELECTION_BORDER, Rect.right - ED_SELECTION_BORDER, Rect.bottom - ED_SELECTION_BORDER); SafeSixteen(inner); RECT SelRect; ::SetRect(&SelRect, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(inner.top)); ::InvertRect(hdc, &SelRect); ::SetRect(&SelRect, CASTINT(Rect.left), CASTINT(inner.top), CASTINT(inner.left), CASTINT(inner.bottom)); ::InvertRect(hdc, &SelRect); ::SetRect(&SelRect, CASTINT(inner.right), CASTINT(inner.top), CASTINT(Rect.right), CASTINT(inner.bottom)); ::InvertRect(hdc, &SelRect); ::SetRect(&SelRect, CASTINT(Rect.left), CASTINT(inner.bottom), CASTINT(Rect.right), CASTINT(Rect.bottom)); ::InvertRect(hdc, &SelRect); } ReleaseContextDC(hdc); } void CDCCX::EraseToBackground(const LTRB& rect, int32 borderWidth) { if(!EDT_IS_EDITOR(GetContext())){ return; } LTRB Rect(rect.left - borderWidth, rect.top - borderWidth, rect.right + borderWidth, rect.bottom + borderWidth); // The editor draws selection feedback. Touch all the pixels so that // any pre-existing selection feedback is erased. HDC hdc = GetContextDC(); RECT destRect; ::SetRect(&destRect, CASTINT(Twips2PixX(Rect.left)), CASTINT(Twips2PixY(Rect.top)), CASTINT(Twips2PixX(Rect.right)), CASTINT(Twips2PixX(Rect.bottom))); // Is this really true? (Troy thinks conversion is only needed for // memory DC) // Coordinates to _EraseBkgnd() must be in device units // NOTE: _EraseBkgnd() call will use m_pImageDC, that's why we // aren't using it _EraseBkgnd(hdc,destRect, Twips2PixX(GetOriginX() ), Twips2PixY(GetOriginY() ), NULL); ReleaseContextDC(hdc); } #ifdef LAYERS // Erase the background at the given rect. x, y, width and height are // in document coordinates. void CDCCX::EraseBackground(MWContext *pContext, int iLocation, int32 x, int32 y, uint32 width, uint32 height, LO_Color *pColor) { #ifdef EDITOR if( EDT_IS_EDITOR(pContext) ) WFE_HideEditCaret(pContext); #endif HDC hdc = GetContextDC(); int32 orgX = GetOriginX(); int32 orgY = GetOriginY(); int32 lDrawingOrgX, lDrawingOrgY; RECT eraseRect; int32 x0, y0; x0 = (x > orgX) ? x - orgX : orgX - x; y0 = (y > orgY) ? y - orgY : orgY - y; ::SetRect(&eraseRect, CASTINT(x0), CASTINT(y0), CASTINT(x0+width), CASTINT(y0+height)); GetDrawingOrigin(&lDrawingOrgX, &lDrawingOrgY); _EraseBkgnd(hdc, eraseRect, orgX-lDrawingOrgX, orgY-lDrawingOrgY, pColor); ReleaseContextDC(hdc); #ifdef EDITOR if( EDT_IS_EDITOR(pContext) ) WFE_ShowEditCaret(pContext); #endif } #endif /* LAYERS */ static BOOL CanCreateBrush(HBITMAP hBitmap) { BITMAP bitmap; // We can create a brush if the bitmap is exacly 8x8 ::GetObject(hBitmap, sizeof(bitmap), &bitmap); return bitmap.bmWidth == 8 && bitmap.bmHeight == 8; } // orgX, orgY, and crRect are interpreted in the logical coordinates // of pDC // // Note: The caller is responsible for having selected the logical palette // before calling this routine. If not, the call to CreateSolidBrush() will // get mapped to the nearest system color (probably not the desired behavior) BOOL CDCCX::_EraseBkgnd(HDC pDC, RECT& crRect, int32 orgX, int32 orgY, LO_Color* bg) { // The order of priority is as follows: // 1. passed in image // 2. passed in color // 3. document backdrop image // 4. document solid color COLORREF bgColor = bg ? RGB(bg->red, bg->green, bg->blue) : m_rgbBackgroundColor; HBRUSH hBrush = NULL; if (m_iBitsPerPixel == 16) // We don't want a dithered brush hBrush = ::CreateSolidBrush(::GetNearestColor(pDC,bgColor)); else hBrush = ::CreateSolidBrush(0x02000000L | bgColor); ::FillRect(pDC, &crRect, hBrush); #ifdef DDRAW if (GetPrimarySurface()) { ::FillRect(GetDispDC(), &crRect, hBrush); } #if 0 //DEBUG_mhwang TRACE("CDCCX::_EraseBkgnd, %d,%d,%d,%d(ltrb)\n", crRect.left, crRect.top, crRect.right, crRect.bottom); #endif #endif VERIFY(::DeleteObject(hBrush)); return TRUE; } struct iconMap{ int iIconNum; int x; int y; unsigned int bitmapID; unsigned int maskID; } #define SMIME_ICON_CX 50 #define SMIME_ICON_CY 30 #define SECADV_ICON_CX 51 #define SECADV_ICON_CY 30 #define ICONMAPSIZE 31 static iconMap[ICONMAPSIZE] = { IL_IMAGE_DELAYED, IMAGE_SMICON_WIDTH, IMAGE_SMICON_HEIGHT,IDB_SMIMAGE_DELAYED, IDB_SMIMAGE_MASK, IL_IMAGE_NOT_FOUND, IMAGE_ICON_SIZE, IMAGE_ICON_SIZE, IDB_IMAGE_NOTFOUND,IDB_IMAGE_MASK, IL_IMAGE_BAD_DATA, IMAGE_ICON_SIZE, IMAGE_ICON_SIZE, IDB_IMAGE_BAD, IDB_IMAGE_BAD_MASK, IL_IMAGE_INSECURE, IMAGE_ICON_SIZE, IMAGE_ICON_SIZE, IDB_IMAGE_SEC_REPLACE,IDB_IMAGE_MASK, IL_GOPHER_FOLDER,GOPHER_ICON_SIZE, GOPHER_ICON_SIZE + 1, IDB_GOPHER_FOLDER,IDB_GOPHER_FOLDER_MASK, IL_GOPHER_IMAGE, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE + 1, IDB_GOPHER_IMAGE,IDB_GOPHER_AUDIO_MASK, IL_GOPHER_TEXT, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_TEXT, IDB_GOPHER_AUDIO_MASK, IL_GOPHER_BINARY, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_BINARY, IDB_GOPHER_AUDIO_MASK, IL_GOPHER_SOUND, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_AUDIO, IDB_GOPHER_AUDIO_MASK, IL_GOPHER_MOVIE, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_FIND, IDB_GOPHER_FIND_MASK, IL_GOPHER_TELNET, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_TELNET,IDB_GOPHER_TELNET_MASK, IL_GOPHER_UNKNOWN, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_GENERIC, IDB_GOPHER_AUDIO_MASK, IL_EDIT_NAMED_ANCHOR, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_NAMED_ANCHOR, IDB_EDIT_NAMED_ANCHOR_MASK, IL_EDIT_FORM_ELEMENT, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_FORM_ELEMENT,IDB_EDIT_FORM_ELEMENT_MASK, IL_EDIT_UNSUPPORTED_TAG, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_UNSUPPORTED_TAG, IDB_EDIT_UNSUPPORTED_TAG_MASK, IL_EDIT_UNSUPPORTED_END_TAG, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_UNSUPPORTED_END_TAG, IDB_EDIT_UNSUPPORTED_END_TAG_MASK, IL_EDIT_JAVA, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_JAVA, IDB_EDIT_JAVA_MASK, IL_EDIT_PLUGIN, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_PLUGIN,IDB_EDIT_PLUGIN_MASK, IL_SA_SIGNED, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SASIGNED, IDB_SASIGNED_MASK, IL_SA_ENCRYPTED, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SAENCRYPTED, IDB_SAENCRYPTED_MASK, IL_SA_NONENCRYPTED, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SAUNENCRYPTED, IDB_SAUNENCRYPTED_MASK, IL_SA_SIGNED_BAD, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SASIGNED, IDB_SASIGNED_MASK, IL_SA_ENCRYPTED_BAD, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SASIGNEDBAD, IDB_SASIGNEDBAD_MASK, IL_SMIME_ATTACHED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGATTACHED, IDB_MSGSTAMPMASK, IL_SMIME_SIGNED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNED, IDB_MSGSTAMPMASK, IL_SMIME_ENCRYPTED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGENCRYPTED, IDB_MSGSTAMPMASK, IL_SMIME_ENC_SIGNED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNEDENCRYPTED, IDB_MSGSTAMPMASK, IL_SMIME_SIGNED_BAD, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNEDBAD, IDB_MSGSTAMPMASK, IL_SMIME_ENCRYPTED_BAD, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGENCRYPTEDBAD, IDB_MSGSTAMPMASK, IL_SMIME_ENC_SIGNED_BAD, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNEDENCRYPTEDBAD, IDB_MSGSTAMPMASK, IL_MSG_ATTACH, 24, 29, IDB_MSGATTACHBUTTON, IDB_MSGATTACHBUTTONMASK }; void CDCCX::GetIconDimensions(int32* width, int32* height, int iconNumber) { unsigned int bitmapID; // resource ID of bitmap to load unsigned int maskID = 0; // resource ID of mask (if any) if (iconNumber < 0) return; int x, y; for (int i = 0; i < ICONMAPSIZE ; i++) { if (iconMap[i].iIconNum == iconNumber) { x = iconMap[i].x; y = iconMap[i].y; bitmapID = iconMap[i].bitmapID; maskID = iconMap[i].maskID; break; } } if (i == ICONMAPSIZE) { // used default icon here. x = GOPHER_ICON_SIZE; y = GOPHER_ICON_SIZE + 1; bitmapID = IDB_FILE; maskID = IDB_GOPHER_AUDIO_MASK; } *width = CASTINT(x); *height = CASTINT(y); } #ifndef XP_WIN32 /* Quaternary raster codes */ #define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore)) #endif static BOOL AlterBackgroundColor(HDC pSrcDC, int width, int height, HBITMAP hMask, HBRUSH hBrush) { HDC memDC; // Create a memory DC for holding the mask if (!(memDC = ::CreateCompatibleDC(NULL))) { TRACE("AlterBackgroundColor() can't create compatible memory DC!\n"); return FALSE; } // Select the mask into the memory DC HBITMAP hOldMaskBitmap = (HBITMAP)::SelectObject(memDC, hMask); // Change the transparent bits of the source bitmap to the desired background // color by doing an AND raster op // // The mask is monochrome and will be converted to color to match the depth of // the destination. The foreground pixels in the mask are set to 1, and the // background pixels to 0. When converting to a color bitmap, white pixels (1) // are set to the background color of the DC, and black pixels (0) are set to // the text color of the DC // // Select the brush HBRUSH hOldBrush = (HBRUSH)::SelectObject(pSrcDC, hBrush); // Draw the brush where the mask is 0 ::BitBlt(pSrcDC, 0, 0, width, height, memDC, 0, 0, // ROP_PSDPxax); MAKEROP4(SRCPAINT, R2_COPYPEN)); // Restore the DCs ::SelectObject(memDC, hOldMaskBitmap); ::SelectObject(pSrcDC, hOldBrush); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // equivalent to LoadBitmap(), except uses pDC for // correct color mapping of BMP into pDC's palette. BOOL CDCCX::cxLoadBitmap(LPCSTR pszBmName, char** bits, BITMAPINFOHEADER** myBitmapInfo) { HINSTANCE hResHandle = AfxGetResourceHandle(); // get the resource from the file HBITMAP hBmp = (HBITMAP)FindResource(hResHandle, pszBmName, RT_BITMAP); if(NULL == hBmp) { ASSERT(0); return FALSE; } HGLOBAL hRes = LoadResource(hResHandle, (HRSRC)hBmp); ASSERT(hRes != NULL); if(!hRes) return FALSE; LPBITMAPINFO pPackedDib = (LPBITMAPINFO)(LockResource(hRes)); ASSERT(pPackedDib != NULL); if(!pPackedDib) return FALSE; // build a DDB header for pDC // create the DDB int iColorTableSize = (1 << pPackedDib->bmiHeader.biBitCount) * sizeof(RGBQUAD); LPBITMAPINFOHEADER bitmapInfo; bitmapInfo = (LPBITMAPINFOHEADER)calloc(sizeof(BITMAPINFOHEADER) + iColorTableSize, 1);; memcpy(bitmapInfo, pPackedDib, sizeof(BITMAPINFOHEADER) + iColorTableSize); bitmapInfo->biBitCount = m_iBitsPerPixel; bitmapInfo->biClrUsed = 0; bitmapInfo->biClrImportant = 0; *myBitmapInfo = bitmapInfo; void* pBits = ((char*)pPackedDib) + pPackedDib->bmiHeader.biSize + iColorTableSize; int widthBytes = (((bitmapInfo->biWidth * bitmapInfo->biBitCount) + 31) && ~31) >> 3; *bits =(char*) CDCCX::HugeAlloc(widthBytes * bitmapInfo->biHeight, 1); memcpy(bits, pBits, widthBytes * bitmapInfo->biHeight); // done, clean up UnlockResource(hRes); BOOL bResult = FreeResource(hRes); return TRUE; } void CDCCX::DisplayIcon(int32 x0, int32 y0, int icon_number) { unsigned int bitmapID; // resource ID of bitmap to load unsigned int maskID = 0; // resource ID of mask (if any) if (icon_number < 0) return; int x, y; LTRB Rect; for (int i = 0; i < ICONMAPSIZE ; i++) { if (iconMap[i].iIconNum == icon_number) { x = iconMap[i].x; y = iconMap[i].y; bitmapID = iconMap[i].bitmapID; maskID = iconMap[i].maskID; break; } } if (i == ICONMAPSIZE) { // used default icon here. x = GOPHER_ICON_SIZE; y = GOPHER_ICON_SIZE + 1; bitmapID = IDB_FILE; maskID = IDB_GOPHER_AUDIO_MASK; } int width = CASTINT(Pix2TwipsX(x)); int height = CASTINT(Pix2TwipsY(y)); if (ResolveElement(Rect, x0, y0, 0, 0, width, height)) { SafeSixteen(Rect); HBITMAP hBitmap = NULL; HDC hdc = GetContextDC(); #ifdef XP_WIN32 if (icon_number == IL_IMAGE_DELAYED) { static HICON hIcon=NULL; // The icon is represented as a small icon resource which is 16x16 pixels if(!hIcon) hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_IMAGE_DELAYED), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); VERIFY(::DrawIconEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top), hIcon, Pix2TwipsX(16), Pix2TwipsY(16), 0, NULL, DI_NORMAL)); /* don't destroy hIcon because it's static */ // return; } else #endif { // load the bitmap out of the resource file HBITMAP mask; if (!IsPrintContext()) { hBitmap = LOADBITMAP(bitmapID); if(maskID) mask = LOADBITMAP(maskID); HBITMAP hOldBitmap = NULL; if(maskID) { if (IsPrintContext()) { HBITMAP hOldBitmap = (HBITMAP)::SelectObject(m_pImageDC, hBitmap); // filled in the background color for transparent bitmap. AlterBackgroundColor(m_pImageDC, x, y, mask, (HBRUSH)::GetStockObject(WHITE_BRUSH)); ::StretchBlt(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(width), CASTINT(height), m_pImageDC, CASTINT(0), CASTINT(0), CASTINT(x), CASTINT(y), SRCCOPY); ::SelectObject(m_pImageDC, hOldBitmap); } else { // load the mask out of the resource file StretchMaskBlt(hdc, hBitmap, mask, Rect.left, Rect.top, width, height, 0, 0, x, y); } VERIFY(::DeleteObject(mask)); } else { // load the bitmap into the cached image CDC hOldBitmap = (HBITMAP) ::SelectObject(m_pImageDC, hBitmap); ::StretchBlt(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(width), CASTINT(height), m_pImageDC, CASTINT(0), CASTINT(0), CASTINT(x), CASTINT(y), SRCCOPY); ::SelectObject(m_pImageDC, hOldBitmap); } // restore the old bitmap VERIFY(::DeleteObject(hBitmap)); } else { // printing icon char* image_bits = NULL; BITMAPINFOHEADER* imageInfo = NULL; char* mask_bits = NULL; BITMAPINFOHEADER* maskInfo = NULL; if (cxLoadBitmap(MAKEINTRESOURCE(bitmapID), &image_bits, &imageInfo)) { if(maskID) { BOOL fillBack = TRUE; #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else #ifdef XP_WIN32 CPrintCX* pPrintCx = (CPrintCX*)this; fillBack = pPrintCx->IsPrintingBackground() ? FALSE : TRUE; #endif #endif cxLoadBitmap(MAKEINTRESOURCE(maskID), &mask_bits, &maskInfo); WFE_StretchDIBitsWithMask(hdc,TRUE, m_pImageDC, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(width), CASTINT(height), CASTINT(0), CASTINT(0), CASTINT(x), CASTINT(y), image_bits, (BITMAPINFO*)imageInfo, mask_bits, m_bUseDibPalColors, fillBack); } else { ::StretchDIBits(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(width), CASTINT(height), CASTINT(0), CASTINT(0), CASTINT(x), CASTINT(y), image_bits, (BITMAPINFO*)imageInfo, DIB_RGB_COLORS, SRCCOPY); } } if (image_bits) delete image_bits; if (imageInfo) delete imageInfo; if(maskID) { if (mask_bits) delete mask_bits; if (maskInfo) delete maskInfo; } } } ReleaseContextDC(hdc); } } int CDCCX::GetUrl(URL_Struct *pUrl, FO_Present_Types iFormatOut, BOOL bReallyLoading, BOOL bForceNew) { // Save the location of the current document, if not at the very top. // Reset to top, then see if we need to change more.... SHIST_SetPositionOfCurrentDoc(&(GetContext()->hist), 0); #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else if(GetOriginX() || GetOriginY()) { #ifdef LAYERS LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(GetDocumentContext(), GetOriginX(), GetOriginY(), NULL); #else LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(GetDocumentContext(), GetOriginX(), GetOriginY()); #endif /* LAYERS */ if(pAny != NULL) { TRACE("Remembering document position at element id %ld\n", pAny->ele_id); SHIST_SetPositionOfCurrentDoc(&(GetContext()->hist), pAny->ele_id); } } #endif /* MOZ_NGLAYOUT */ // Handle forced image loading. m_csForceLoadImage = m_csNexttimeForceLoadImage; m_csNexttimeForceLoadImage.Empty(); m_bLoadImagesNow = m_bNexttimeLoadImagesNow; m_bNexttimeLoadImagesNow = FALSE; // Call the base. return(CStubsCX::GetUrl(pUrl, iFormatOut, bReallyLoading, bForceNew)); } // rewrite the BULLET_BASIC and BULLET_DISC part // the origional "o" approach cause a lot of problem in non-LATIN page void CDCCX::DisplayBullet(MWContext *pContext, int iLocation, LO_BullettStruct *pBullet) { // Figure the coordinates. LTRB Rect; int reduce; // if(ResolveElement(Rect, pBullet, iLocation) == TRUE) { if (ResolveElement(Rect, pBullet->x, pBullet->y, pBullet->x_offset, pBullet->y_offset, pBullet->width, pBullet->height) == TRUE) { SafeSixteen(Rect); COLORREF rgbBullet = ResolveTextColor(pBullet->text_attr); HDC hdc = GetContextDC(); int w; if( pBullet->bullet_type == BULLET_MQUOTE || pBullet->bullet_type == BULLET_SQUARE ) { w = 1; } else { w = CASTINT( (Rect.bottom - Rect.top) / 10); if(w < 1) w = 1; } HPEN hpen = ::CreatePen(PS_SOLID,w,rgbBullet); HPEN oldPen = (HPEN)::SelectObject(hdc,hpen); // draw_bullet_with_Ellipse HBRUSH hBrush = ::CreateSolidBrush(rgbBullet); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush); switch(pBullet->bullet_type) { case BULLET_MQUOTE: // BUG#61210 draw quote as one pixel bar on the left #if defined (WIN32) ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top), NULL); #else ::MoveTo(hdc, CASTINT(Rect.left), CASTINT(Rect.top)); #endif ::LineTo(hdc,CASTINT(Rect.left), CASTINT(Rect.bottom)); break; case BULLET_SQUARE: // Size of square is too large relative to solid and open circle, // so reduce a little Rect.top++; Rect.bottom--; Rect.left++; Rect.right--; ::Rectangle(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); break; case BULLET_NONE: // Do nothing break; case BULLET_BASIC: // solid bullet case BULLET_ROUND : // todo ::RoundRect()? default : // Circle if( BULLET_BASIC != pBullet->bullet_type ) { // Circle // don't touch hOldBrush, put hOldBrush back after draw. ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); } reduce = (Rect.bottom - Rect.top ) / 4; ::Ellipse(hdc, CASTINT(Rect.left+reduce), CASTINT(Rect.top+reduce), CASTINT(Rect.right-reduce), CASTINT(Rect.bottom-reduce)); break; } ::SelectObject(hdc, hOldBrush); VERIFY(::DeleteObject( hBrush )); ::SelectObject(hdc,oldPen); ::DeleteObject(hpen); // end of draw_bullet_with_Ellipse ReleaseContextDC(hdc); } } #ifdef Frank_code void CDCCX::DisplayBullet(MWContext *pContext, int iLocation, LO_BullettStruct *pBullet) { // Figure the coordinates. LTRB Rect; // if(ResolveElement(Rect, pBullet, iLocation) == TRUE) { if (ResolveElement(Rect, pBullet->x, pBullet->y, pBullet->x_offset, pBullet->y_offset, pBullet->width, pBullet->height) == TRUE) { SafeSixteen(Rect); COLORREF rgbBullet = ResolveTextColor(pBullet->text_attr); HDC hdc = GetContextDC(); Rect.top++; Rect.bottom--; Rect.left++; Rect.right--; switch(pBullet->bullet_type) { case BULLET_MQUOTE: case BULLET_SQUARE: { HBRUSH hBrush = ::CreateSolidBrush(rgbBullet); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush); ::Rectangle(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); ::SelectObject(hdc, hOldBrush); VERIFY(::DeleteObject( hBrush )); break; } case BULLET_BASIC: { HBRUSH hBrush = ::CreateSolidBrush(rgbBullet); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush); ::Ellipse(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); ::SelectObject(hdc, hOldBrush); VERIFY(::DeleteObject( hBrush )); break; } default: { int w = CASTINT( (Rect.bottom - Rect.top) / 10); if(w < 1) w = 1; HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH); HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush); HPEN hStrike = ::CreatePen(PS_SOLID, CASTINT( w ), rgbBullet); HPEN hOldStrike = (HPEN)::SelectObject(hdc, hStrike); ::Ellipse(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); ::SelectObject(hdc, hOldBrush); // Don't delete hBrush since it is a stock object ::SelectObject(hdc, hOldStrike); VERIFY(::DeleteObject( hStrike )); break; } } ReleaseContextDC(hdc); } } #endif // Display a border of the specified size and color. x, y, width and height // refer to the outside perimeter of the border. void CDCCX::DisplayBorder(MWContext *pContext, int iLocation, int x, int y, int width, int height, int bw, LO_Color *color, LO_LineStyle style) { LTRB Rect; if (bw) { // Adjust the input parameters so that they describe the inside // perimeter of the border. Don't do this for 3D borders since // Draw3DBox does this for us. if (style != LO_BEVEL) { x += bw; y += bw; width -= 2 * bw; height -= 2 * bw; } if (ResolveElement(Rect, x, y, 0, 0, width, height)) { SafeSixteen(Rect); // Call the method which really draws the border. switch(style) { case LO_SOLID: DrawRectBorder(Rect, ResolveLOColor(color), bw); break; case LO_BEVEL: Display3DBox(Rect, ResolveDarkLineColor(), ResolveLightLineColor(), Pix2TwipsX(bw), FALSE); break; default: break; } } } } void CDCCX::DisplayImageFeedback(MWContext *pContext, int iLocation, LO_Element *pElement, lo_MapAreaRec * theArea, uint32 drawFlag ) { if (pElement->lo_any.type == LO_IMAGE) { LO_ImageStruct *pImage = (LO_ImageStruct *)pElement; LTRB Rect; int borderWidth = CASTINT(pImage->border_width); int x = CASTINT(pImage->x + pImage->x_offset + borderWidth); int y = CASTINT(pImage->y + pImage->y_offset + borderWidth); if (ResolveElement(Rect, x, y, 0, 0, pImage->width, pImage->height)) { SafeSixteen(Rect); DisplaySelectionFeedback(pImage->ele_attrmask, Rect); //#ifndef NO_TAB_NAVIGATION if((FE_DRAW_TAB_FOCUS & drawFlag) && pImage->suppress_mode != LO_SUPPRESS) { // use the Rect from code above. if( theArea != NULL) { // It is a focused area in map, draw a focus border. DrawMapAreaBorder( CASTINT(Rect.left), CASTINT(Rect.top), theArea ); } else { // draw a focus border for the whole image lo_MapAreaRec area; int32 coord[4]; area.coords = coord; area.type = AREA_SHAPE_RECT ; area.coord_cnt = 4; area.coords[0] = Rect.left; area.coords[1] = Rect.top; area.coords[2] = Rect.right; area.coords[3] = Rect.bottom; DrawMapAreaBorder( 0, 0, &area ); } } //#endif /* NO_TAB_NAVIGATION */ } } } BOOL CDCCX::IsPluginFullPage(LO_EmbedStruct *pLayoutData) { // 1x1 size is signal that plugin is full page, not embedded if((pLayoutData->objTag.width == Pix2TwipsX(1)) && (pLayoutData->objTag.height == Pix2TwipsX(1))) return TRUE; return FALSE; } // returns TRUE if there is a plugin on the page and that plugin // is of pluginType == NPWFE_FULL_PAGE. There can be only one // plugin on a page that contains a NPWFE_FULL_PAGE plugin. BOOL CDCCX::ContainsFullPagePlugin() { NPEmbeddedApp* pEmbeddedApp = GetContext()->pluginList; if(pEmbeddedApp) { if(pEmbeddedApp->pagePluginType == NP_FullPage) return TRUE; } return FALSE; } // Determine location of plugin rect, convert from TWIPS to PIXELS void CDCCX::GetPluginRect(MWContext *pContext, LO_EmbedStruct *pLayoutData, RECT &rect, int iLocation, BOOL windowed) { if(IsPluginFullPage(pLayoutData)) { ::GetClientRect(PANECX(pContext)->GetPane(), &rect); } else // plugin embedded in page { // get the display area and clamp it LTRB Rect; ResolveElement(Rect, pLayoutData, iLocation, windowed); SafeSixteen(Rect); rect.left = (int)Rect.left; rect.top = (int)Rect.top; rect.right = (int)Rect.right; rect.bottom = (int)Rect.bottom; } } void CDCCX::DisplayWindowlessPlugin(MWContext *pContext, LO_EmbedStruct *pEmbed, NPEmbeddedApp *pEmbeddedApp, int iLocation) { RECT rect; NPWindow* pAppWin = pEmbeddedApp->wdata; HDC hDC = GetContextDC(); NPEvent event; FE_Region clip; // Get the coordinates of where it should be positioned GetPluginRect(pContext, pEmbed, rect, iLocation, FALSE); if ((pAppWin->window != (void *)hDC) || (pAppWin->x != (uint32) rect.left) || (pAppWin->y != (uint32) rect.top) || (pAppWin->width != (uint32) (rect.right - rect.left)) || (pAppWin->height != (uint32) (rect.bottom - rect.top))) { pAppWin->window = (void *)hDC; pAppWin->x = rect.left; pAppWin->y = rect.top; pAppWin->width = rect.right - rect.left; pAppWin->height = rect.bottom - rect.top; pAppWin->type = NPWindowTypeDrawable; #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else NPL_EmbedSize(pEmbeddedApp); #endif } #ifdef LAYERS clip = GetDrawingClip(); if (clip) { XP_Rect xprect; FE_GetRegionBoundingBox(clip, &xprect); rect.left = CASTINT(xprect.left); rect.top = CASTINT(xprect.top); rect.right = CASTINT(xprect.right); rect.bottom = CASTINT(xprect.bottom); } #endif /* LAYERS */ event.event = WM_PAINT; event.wParam = (uint32)hDC; event.lParam = (uint32)▭ #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else NPL_HandleEvent(pEmbeddedApp, (void *)&event, pAppWin->window); #endif ReleaseContextDC(hDC); } // create a window and pass its offset/size to the plugin void CDCCX::DisplayPlugin(MWContext *pContext, LO_EmbedStruct *pEmbed, NPEmbeddedApp* pEmbeddedApp, int iLocation) { RECT rect; NPWindow* pAppWin = pEmbeddedApp->wdata; if(pAppWin->window == NULL) return; if (::IsWindowVisible((HWND)pAppWin->window) && (pEmbed->objTag.ele_attrmask & LO_ELE_INVISIBLE)) ::ShowWindow((HWND)pAppWin->window, SW_HIDE); // If the plugin is embedded we need to make sure the window is // positioned properly if (!IsPluginFullPage(pEmbed)) { RECT curRect; // Get the coordinates of where it should be positioned GetPluginRect(pContext, pEmbed, rect, iLocation, TRUE); // Get the current coordinates relative to the parent window's // client area ::GetWindowRect((HWND)pAppWin->window, &curRect); MapWindowPoints(NULL, ::GetParent((HWND)pAppWin->window), (POINT FAR *)&curRect, 2); // Only move/size the window if necessary if ((rect.left != curRect.left) || (rect.right != curRect.right) || (rect.top != curRect.top) || (rect.bottom != curRect.bottom)){ ::SetWindowPos((HWND)pAppWin->window, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE); } // Update the NPWindow rect pAppWin->x = rect.left; pAppWin->y = rect.top; pAppWin->width = rect.right - rect.left; pAppWin->height = rect.bottom - rect.top; } if (!::IsWindowVisible((HWND)pAppWin->window) && !(pEmbed->objTag.ele_attrmask & LO_ELE_INVISIBLE)) ::ShowWindow((HWND)pAppWin->window, SW_SHOW); } #ifndef MOZ_NGLAYOUT void CDCCX::DisplayEmbed(MWContext *pContext, int iLocation, LO_EmbedStruct *pEmbed) { NPEmbeddedApp* pEmbeddedApp = (NPEmbeddedApp*)pEmbed->objTag.FE_Data; if(pEmbeddedApp == NULL) return; if(wfe_IsTypePlugin(pEmbeddedApp)) { if (NPL_IsEmbedWindowed(pEmbeddedApp)) { DisplayPlugin(pContext, pEmbed, pEmbeddedApp, iLocation); (void)NPL_EmbedSize(pEmbeddedApp); } else DisplayWindowlessPlugin(pContext, pEmbed, pEmbeddedApp, iLocation); if(IsPluginFullPage(pEmbed)) pEmbeddedApp->pagePluginType = NP_FullPage; else pEmbeddedApp->pagePluginType = NP_Embedded; return; } // else must be an OLE display LTRB Rect; if(ResolveElement(Rect, pEmbed, iLocation, FALSE) == TRUE) { int32 lOrgX, lOrgY; GetDrawingOrigin(&lOrgX, &lOrgY); SafeSixteen(Rect); // Draw a border around the embed if needed. if(pEmbed->objTag.border_width != 0) { DrawRectBorder(Rect, ResolveBorderColor(NULL), pEmbed->objTag.border_width); } // Get the embedded item CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data; if(pItem == NULL) { DisplayIcon(Rect.left, Rect.top, IL_IMAGE_BAD_DATA); return; } // Handle delayed, broken, and currently loading items. else if(pItem->m_bDelayed == TRUE) { DisplayIcon(Rect.left - lOrgX, Rect.top - lOrgY, IL_IMAGE_DELAYED); return; } else if(pItem->m_bBroken == TRUE) { DisplayIcon(Rect.left - lOrgX, Rect.top - lOrgY, IL_IMAGE_BAD_DATA); } else if(pItem->m_bLoading == TRUE) { // Can't draw if still loading. return; } // Okay to draw. HDC hdc = GetContextDC(); RECT crRect; ::SetRect(&crRect, (int)Rect.left,(int)Rect.top,(int)Rect.right,(int)Rect.bottom); CDC dc; dc.Attach(hdc); COLORREF backgroundColor = (COLORREF)GetSysColor(COLOR_WINDOW); HBRUSH tempBrush = ::CreateSolidBrush(backgroundColor); ::FillRect(dc.GetSafeHdc(), &crRect,tempBrush); ::DeleteObject(tempBrush); if (pItem->IsInPlaceActive()) { if (!pItem->m_bSetExtents) { pItem->m_bSetExtents = TRUE; SIZEL temp1; temp1.cx = Twips2MetricX(crRect.right - crRect.left); temp1.cy = Twips2MetricY(crRect.bottom - crRect.top); HRESULT sc = pItem->m_lpObject->SetExtent(DVASPECT_CONTENT, &temp1); sc = pItem->m_lpObject->Update(); } crRect.left += sysInfo.m_iScrollWidth + sysInfo.m_iBorderWidth; crRect.top += sysInfo.m_iScrollHeight + sysInfo.m_iBorderHeight; crRect.right -= sysInfo.m_iScrollWidth + sysInfo.m_iBorderWidth; crRect.bottom -= sysInfo.m_iScrollHeight + sysInfo.m_iBorderHeight; pItem->SetItemRects(&crRect); } pItem->Draw(&dc, &crRect); dc.Detach(); ReleaseContextDC(hdc); } } #endif /* MOZ_NGLAYOUT */ void CDCCX::DisplayHR(MWContext *pContext, int iLocation, LO_HorizRuleStruct *pHorizRule) { // Figure out the coordinates of where to draw the HR. LTRB Rect; // if(ResolveElement(Rect, pHorizRule, iLocation) == TRUE) { if(ResolveElement(Rect, pHorizRule->x,pHorizRule->y, pHorizRule->x_offset, pHorizRule->y_offset, pHorizRule->width, pHorizRule->height) == TRUE) { SafeSixteen(Rect); #ifdef EDITOR // Don't draw the editor's end-of-document hrule unless we're // displaying paragraph marks. if ( pHorizRule->edit_offset < 0 && ! EDT_DISPLAY_PARAGRAPH_MARKS(pContext) ) { return; } // Increase height of selection rect if it is very small LTRB SelRect = Rect; if( SelRect.Height() < 6 ) { SelRect.top -= (6 - SelRect.Height())/2; SelRect.bottom = SelRect.top + 6; } // EraseToBackground(SelRect); #endif /* EDITOR */ // Find out if we are doing a solid or 3D HR. if(ResolveHRSolid(pHorizRule) == TRUE) { HDC hdc = GetContextDC(); // Draw a solid HR. // We'll be using the darker color to do this. COLORREF rgbColor = ResolveDarkLineColor(); HPEN cpHR = ::CreatePen(PS_SOLID, CASTINT(Pix2TwipsY(pHorizRule->thickness)), rgbColor); HPEN pOldPen = (HPEN)::SelectObject(hdc, cpHR); if(MMIsText() == TRUE) { ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top + Rect.Height() / 2), NULL); ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.top + Rect.Height() / 2)); // use top, or diagonal. } else { ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top), NULL); ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.top)); // use top, or diagonal. } ::SelectObject(hdc, pOldPen); VERIFY(::DeleteObject(cpHR)); ReleaseContextDC(hdc); } else { Display3DBox(Rect, ResolveDarkLineColor(), ResolveLightLineColor(), Pix2TwipsX(1), TRUE); } #ifdef EDITOR DisplaySelectionFeedback(pHorizRule->ele_attrmask, SelRect); #endif //EDITOR } } // Common algorithm for setting contrasting background and text colors void wfe_GetSelectionColors( COLORREF rgbBackgroundColor, COLORREF* pTextColor, COLORREF* pBackColor) { //CLM: Always use Blue text on white or white text on blue if selecting // Test intensity of real background so entire selection uses same colors // This algorithm favors using dark // Possible problem: If we have relatively bright text on a dark background image BOOL bDarkBackground = (GetRValue(rgbBackgroundColor) + GetGValue(rgbBackgroundColor) + GetBValue(rgbBackgroundColor)) < 192; if( pTextColor ){ *pTextColor = bDarkBackground ? RGB(0,0,128) : RGB(255,255,255); } if( pBackColor ){ *pBackColor = bDarkBackground ? RGB(255,255,255) : RGB(0,0,128); } } void CDCCX::DisplayLineFeed(MWContext *pContext, int iLocation, LO_LinefeedStruct *pLineFeed, XP_Bool clear) { LTRB Rect; Bool bElementResolved; Bool bSpecialDrawing = EDT_IS_EDITOR(pContext) && pLineFeed->break_type; #ifdef EDITOR // Allow selection feedback and display of end-of-paragraph marks in the editor. // We do nothing if we're not in the editor. // We do nothing if this isn't an end-of-paragraph or hard break. // If we're displaying the marks, then we display them as little squares. // Otherwise we just do the selection feedback. // The selection feedback is a rectangle the height of the linefeed 1/2 of the rectangle's height. // located at the left edge of the linefeed's range. // We need to expand the linefeed's width here so that ResolveElement thinks it's at least as wide // as we're going to draw it. Bool bExpanded = FALSE; int32 expandedWidth; int32 expandedHeight; if ( bSpecialDrawing ) { const int32 kMinimumWidth = 7; const int32 kMinimumHeight = 12; int32 originalWidth = pLineFeed->width; int32 originalHeight= pLineFeed->height; expandedWidth = originalWidth; expandedHeight = originalHeight; if ( expandedWidth < kMinimumWidth ) { expandedWidth = kMinimumWidth; bExpanded = TRUE; } if ( expandedHeight < kMinimumHeight ) { expandedHeight = kMinimumHeight; bExpanded = TRUE; } pLineFeed->width = expandedWidth; pLineFeed->height = expandedHeight; // bElementResolved = ResolveElement(Rect, pLineFeed, iLocation); bElementResolved = ResolveElement(Rect, pLineFeed->x, pLineFeed->y, pLineFeed->x_offset,pLineFeed->y_offset, pLineFeed->width, pLineFeed->height); pLineFeed->width = originalWidth; pLineFeed->height = originalHeight; } else { // bElementResolved = ResolveElement(Rect, pLineFeed, iLocation); bElementResolved = ResolveElement(Rect, pLineFeed->x, pLineFeed->y, pLineFeed->x_offset, pLineFeed->y_offset, pLineFeed->width, pLineFeed->height); } #else // bElementResolved = ResolveElement(Rect, pLineFeed, iLocation); bElementResolved = ResolveElement(Rect, pLineFeed->x, pLineFeed->y, pLineFeed->x_offset, pLineFeed->y_offset, pLineFeed->width, pLineFeed->height); #endif if (bElementResolved) { SafeSixteen(Rect); if ( ! EDT_IS_EDITOR(pContext) || ! pLineFeed->break_type ) { // If the linefeed has a solid background color, then use it. // To Be Done: If we're selected, use the fg color instead of the bg color. #ifndef LAYERS // For layers, we don't want to draw the background if (pLineFeed->text_attr->no_background == FALSE && !IsPrintContext()) { HBRUSH hBrush; CRect cRect(CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); HDC hdc = GetContextDC(iLocation); if (m_iBitsPerPixel == 16) // We don't want a dithered brush hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, RGB(pLineFeed->text_attr->bg.red, pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue))); else hBrush = ::CreateSolidBrush(0x02000000L | ResolveBGColor(pLineFeed->text_attr->bg.red, pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue)); HBRUSH hOldBrush; hOldBrush = ::SelectObject(hdc, hBrush); ::FillRect(hdc, &cRect, hBrush); ::SelectObject(hdc, hOldBrush); VERIFY(::DeleteObject(hBrush)); ReleaseContextDC(hdc, iLocation); } #endif // LAYERS return; } HDC hdc = GetContextDC(); RECT r; ::SetRect(&r, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); // Need to look up the text color. LO_TextAttr * attr = pLineFeed->text_attr; // Determine the color. COLORREF rgbColor = ResolveTextColor(attr); COLORREF textBackColor; Bool selected = pLineFeed->ele_attrmask & LO_ELE_SELECTED; if ( selected ) { wfe_GetSelectionColors(m_rgbBackgroundColor, &rgbColor, &textBackColor); } if (clear & ! selected) { #ifdef EDITOR // If the linefeed has a solid background color, then use it if (pLineFeed->text_attr->no_background == FALSE && !IsPrintContext()) { HBRUSH hBrush; RECT cRect; ::SetRect(&cRect, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); if (m_iBitsPerPixel == 16) // We don't want a dithered brush hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, RGB(pLineFeed->text_attr->bg.red, pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue))); else hBrush = ::CreateSolidBrush(0x02000000L | ResolveBGColor(pLineFeed->text_attr->bg.red, pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue)); ::FillRect(hdc, &cRect, hBrush); VERIFY(::DeleteObject(hBrush)); } else { EraseToBackground(Rect); } // If this linefeed draws outside it bounds, then // EraseToBackground could have // smashed a nearby element. // So invalidate this portion. (The main examples of this are // linefeeds in tables.) if ( bExpanded && IsWindowContext()) { ::InvalidateRect(PANECX(pContext)->GetPane(), &r, FALSE); } #endif } #ifdef EDITOR // Limit the size of the drawn paragraph marker. const int32 kMaxHeight = 30; if ( expandedHeight > kMaxHeight ){ expandedHeight = kMaxHeight; } int32 desiredWidth = expandedHeight / 2; if ( expandedWidth > desiredWidth ) { expandedWidth = desiredWidth; } r.right = CASTINT(r.left + expandedWidth); r.bottom = CASTINT(r.top + expandedHeight); #endif if (selected) { HBRUSH cbBrush = ::CreateSolidBrush(textBackColor); ::FillRect(hdc, &r, cbBrush); VERIFY(::DeleteObject(cbBrush)); } if ( EDT_DISPLAY_PARAGRAPH_MARKS(pContext) && (! pLineFeed->prev // Don't draw mark after end-of-doc mark || pLineFeed->prev->lo_any.edit_offset >= 0 ) ) { HBRUSH cbBrush = ::CreateSolidBrush(rgbColor); if ( r.right - r.left > 5 ) { r.left += 2; r.right -= 2; } if ( r.bottom - r.top > 5 ) { r.top += 2; r.bottom -= 2; } // draw line breaks at 1/3 height of paragraph marks if ( pLineFeed->break_type == LO_LINEFEED_BREAK_HARD ){ r.top += (r.bottom - r.top) * 2 / 3; } ::FillRect(hdc, &r, cbBrush); VERIFY(::DeleteObject(cbBrush)); } ReleaseContextDC(hdc); } } void CDCCX::DisplaySubDoc(MWContext *pContext, int iLocation, LO_SubDocStruct *pSubDoc) { LTRB Rect; // if(ResolveElement(Rect, pSubDoc, iLocation) == TRUE) { if(ResolveElement(Rect, pSubDoc->x, pSubDoc->y, pSubDoc->x_offset, pSubDoc->y_offset, pSubDoc->width, pSubDoc->height) == TRUE) { SafeSixteen(Rect); if(pSubDoc->border_width > 0) { Display3DBox(Rect, ResolveLightLineColor(), ResolveDarkLineColor(), pSubDoc->border_width); } } } void CDCCX::DisplayCell(MWContext *pContext, int iLocation, LO_CellStruct *pCell) { LTRB Rect; if(ResolveElement(Rect, pCell->x, pCell->y, pCell->x_offset, pCell->y_offset, pCell->width, pCell->height) == TRUE) { SafeSixteen(Rect); #ifndef LAYERS // With layers, the background color is done with a layer // If the cell has a background color, then use it if (pCell->bg_color && !IsPrintContext()) { HBRUSH hBrush; RECT cRect; ::SetRect(&cRect, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); HDC hdc = GetContextDC(iLocation); if (m_iBitsPerPixel == 16) // We don't want a dithered brush hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, RGB(pCell->bg_color->red, pCell->bg_color->green, pCell->bg_color->blue))); else hBrush = ::CreateSolidBrush(0x02000000L | ResolveBGColor(pCell->bg_color->red, pCell->bg_color->green, pCell->bg_color->blue)); ::FillRect(hdc, &cRect, hBrush); VERIFY(::DeleteObject(hBrush)); ReleaseContextDC(pDC, iLocation); } // If we decide to allow nested table cells to have the // background show through then we need this code #endif /* LAYERS */ #ifdef EDITOR if( EDT_IS_EDITOR(pContext) ) { if( pCell->border_width == 0 || LO_IsEmptyCell(pCell) ) { // If we do this, image background doesn't show up //EraseToBackground(Rect); } int32 iExtraSpace = 0; int32 iBorder = pCell->border_width; // Cell highlightin is thicker int32 iMaxWidth = 2 * ED_SELECTION_BORDER; BOOL bSelected = pCell->ele_attrmask & LO_ELE_SELECTED; BOOL bSelectedSpecial = pCell->ele_attrmask & LO_ELE_SELECTED_SPECIAL; COLORREF rgbBorder; HDC hDC = 0; if( bSelected || bSelectedSpecial ) { // Use the selection background color to draw a solid border wfe_GetSelectionColors(m_rgbBackgroundColor, NULL, &rgbBorder); hDC = GetContextDC(); RECT r; ::SetRect(&r, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); if( iBorder > 0 ) { // If there is inter-cell spacing, // draw selection in that region as much as possible if( pCell->inter_cell_space > 0 && iBorder < iMaxWidth ) { iExtraSpace = min(iMaxWidth - iBorder, pCell->inter_cell_space / 2); iBorder += iExtraSpace; ::InflateRect(&r, iExtraSpace, iExtraSpace); } LTRB borderWidths(iBorder, iBorder, iBorder, iBorder); if( bSelectedSpecial ) { // Show a solid DASHED border as the special selection feedback DisplaySpecialBorder(hDC, r, rgbBorder, iBorder, TRUE); } else { // Show a solid border as the selection feedback DisplaySolidBorder(hDC, r, rgbBorder, borderWidths); } } } if( pCell->border_width == 0 || LO_IsEmptyCell(pCell) ) { // Draw zero-border and empty cells with the dotted line // (Navigator will not display borders of empty cells) // Don't bother testing (EDT_DISPLAY_TABLE_BORDERS) // since we don't support turning borders off now EditorDisplayZeroWidthBorder(Rect, bSelected | bSelectedSpecial ); } else if( !bSelected ) { Display3DBox(Rect, ResolveDarkLineColor(), ResolveLightLineColor(), pCell->border_width); } // If directly-drawn selection border is narrower than minimum selection width (ED_SELECTION_BORDER) // add inverse highlighting whose width is ED_SELECTION_BORDER // Thus total selection effect will always be between // ED_SELECTION_BORDER and (2*ED_SELECTION_BORDER) in thickness if( hDC && (bSelected || bSelectedSpecial) && iBorder < ED_SELECTION_BORDER ) { // TODO: IMAGES THAT FILL CELL WILL OVERWRITE THIS SELECTION - Especially bad when iBorder = 0 LTRB CellRect = Rect; // Draw inside the border rect CellRect.Inflate(-1); if( bSelectedSpecial ) { RECT r; ::SetRect(&r, CASTINT(CellRect.left), CASTINT(CellRect.top), CASTINT(CellRect.right), CASTINT(CellRect.bottom)); // Show an inverted DASHED border as the special selection feedback DisplaySpecialBorder(hDC, r, rgbBorder, ED_SELECTION_BORDER, FALSE); } else { DisplaySelectionFeedback(LO_ELE_SELECTED, CellRect); } } if( hDC ) ReleaseContextDC(hDC); } else #endif // EDITOR // Normal border drawing for Navigator if( pCell->border_width > 0 ) { Display3DBox(Rect, ResolveDarkLineColor(), ResolveLightLineColor(), pCell->border_width); } } } VOID CALLBACK EXPORT LineDDAProcTabFocus( int x, // x-coordinate of point being evaluated int y, // y-coordinate of point being evaluated LPARAM lpData // address of application-defined data ) { static BOOL flip = FALSE; // HDC hdc = (HDC) lpData; flip = ! flip; #ifdef _WIN32 SetPixelV((HDC)lpData, x, y, flip? COLORREF(RGB(0,0,0)) : COLORREF(RGB(255,255,255)) ); #else SetPixel((HDC)lpData, x, y, flip? COLORREF(RGB(0,0,0)) : COLORREF(RGB(255,255,255)) ); #endif return; } void CDCCX::DrawTabFocusLine( HDC hdc, BOOL supportPixel, int x, int y, int x2, int y2) { if( supportPixel ) { // support SetPixel() LineDDA( x, y, x2, y2, (LINEDDAPROC)LineDDAProcTabFocus, (LPARAM)hdc ); } else { // SetPixel is not supported #ifdef _WIN32 ::MoveToEx(hdc, x, y, NULL); #else ::MoveTo(hdc, x, y ); #endif ::LineTo(hdc, x2, y2); } } // Monochrome brush with every other pixel set struct CAlternateBrush { HBRUSH hBrush; CAlternateBrush(); ~CAlternateBrush(); } alternateBrush; CAlternateBrush::CAlternateBrush() { // Monochrome pattern brush we use for drawing horizontal and vertical alternate // lines (lines with every other pixel set) static const WORD gray50 [] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}; HBITMAP hBitmap = ::CreateBitmap(8, 8, 1, 1, gray50); hBrush = ::CreatePatternBrush(hBitmap); ::DeleteObject(hBitmap); } CAlternateBrush::~CAlternateBrush() { ::DeleteObject(hBrush); } void CDCCX::DrawTabFocusRect( HDC hdc, BOOL supportPixel, int left, int top, int right, int bottom) { RECT rect = {left, top, right, bottom}; DWORD dwOldTextColor, dwOldBkColor; ASSERT(alternateBrush.hBrush); dwOldTextColor = ::SetTextColor(hdc, RGB(0,0,0)); dwOldBkColor = ::SetBkColor(hdc, RGB(255,255,255)); ::FrameRect(hdc, &rect, alternateBrush.hBrush); ::SetTextColor(hdc, dwOldTextColor); ::SetBkColor(hdc, dwOldBkColor); } //#ifndef NO_TAB_NAVIGATION // see function lo_is_location_in_area() in file ns\lib\layout\laymap.c for area types. void CDCCX::DrawMapAreaBorder( int baseX, int baseY, lo_MapAreaRec * theArea ) { int centerX, centerY, radius; int left, top, right, bottom; int oldDrawingMode; int ii; HDC hdc = GetContextDC(); HPEN pTabFocusPen; HPEN pOldPen; HBRUSH hOldBrush; BOOL supportPixel = ::GetDeviceCaps( hdc, RASTERCAPS ) & RC_BITBLT ; if( ! supportPixel || theArea->type == AREA_SHAPE_CIRCLE ) { // todo get color for hi-light oldDrawingMode = SetROP2( hdc, R2_NOT); // R2_NOT reverse the screen color pTabFocusPen = ::CreatePen(PS_DOT, 1, COLORREF( RGB(0,0,0)) ); pOldPen = (HPEN)::SelectObject(hdc, pTabFocusPen); hOldBrush = (HBRUSH) ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); } switch( theArea->type ) { case AREA_SHAPE_RECT: if (theArea->coord_cnt >= 4) { left = (int)(baseX + theArea->coords[0]); // Pix2TwipsY()? top = (int)(baseY + theArea->coords[1]); right = (int)(baseX + theArea->coords[2]); bottom = (int)(baseY + theArea->coords[3]); DrawTabFocusRect(hdc, supportPixel, left, top, right, bottom); if( supportPixel ) DrawTabFocusRect(hdc, supportPixel, left+1, top+1, right-1, bottom-1); // double line } break; case AREA_SHAPE_CIRCLE: if ( theArea->coord_cnt >= 3) { centerX = (int)theArea->coords[0] + baseX; centerY = (int)theArea->coords[1] + baseY; radius = (int)theArea->coords[2]; left = centerX - radius ; top = centerY - radius ; right = centerX + radius ; bottom = centerY + radius ; //todo the NULL_BRUSH may cause problems on some platforms(win3.1, win95). ::Ellipse(hdc, left, top, right, bottom); ::Ellipse(hdc, left+1, top+1, right-1, bottom-1); // double line } break; case AREA_SHAPE_POLY: if (theArea->coord_cnt >= 6) { for( ii=0; ii<= theArea->coord_cnt-4; ii+=2) { DrawTabFocusLine( hdc, supportPixel, (int)theArea->coords[ii] + baseX, (int)theArea->coords[ii+1] + baseY, (int)theArea->coords[ii+2] + baseX, (int)theArea->coords[ii+3] + baseY); } // make it close // work around: for 6 edges, theArea->coord_cnt is 13 !! // Cannot use theArea->coord_cnt-2 for last x. // use ii, which stoped at the last point. DrawTabFocusLine( hdc, supportPixel, (int)theArea->coords[ii] + baseX, (int)theArea->coords[ii+1] + baseY, (int)theArea->coords[0] + baseX, (int)theArea->coords[1] + baseY); } break; case AREA_SHAPE_DEFAULT: // TODO ?????? break; case AREA_SHAPE_UNKNOWN: default: break; } if( ! supportPixel || theArea->type == AREA_SHAPE_CIRCLE ) { ::SelectObject(hdc, hOldBrush); ::SelectObject(hdc, pOldPen); VERIFY(::DeleteObject(pTabFocusPen)); ::SetROP2( hdc, oldDrawingMode ); } ReleaseContextDC(hdc); } //#endif /* NO_TAB_NAVIGATION */ void CDCCX::DisplaySubtext(MWContext *pContext, int iLocation, LO_TextStruct *pText, int32 lStartPos, int32 lEndPos, XP_Bool iClear) { // Figure the coordinates of where to draw the text. LTRB Rect; if(ResolveElement(Rect, pText, iLocation, lStartPos, lEndPos, iClear) == TRUE) { SafeSixteen(Rect); HDC hdc = GetContextDC(); // cache the attribute pointer LO_TextAttr * attr = pText->text_attr; BOOL display_background_color = !attr->no_background; // Determine the color. COLORREF rgbColor = ResolveTextColor(attr); // If the color is the same as the background color, then we are selecting. // Go into opaque mode. COLORREF rgbOldBackgroundColor; // what color does layout think our background color is? COLORREF textBackColor = RGB(attr->bg.red, attr->bg.green, attr->bg.blue); //IMPORTANT! Note that we will get called to draw a sub-part of a text line // with LO_ELE_SELECTED flag set and the selected start-end is // outside of range to be drawn, thus we are really drawing the UNSELECTED // portion of the text. So be sure to test that drawing and selectd start positions match // [ = lStartPos // ] = lEndPos // ( = sel_start // ) = sel_end // selection calls one of these two: // subtext [ ( ) ] // subtext [ ] ( ) // drawtext calls subtext three times: [ ] [( )] [ ] BOOL bSelected = (pText->ele_attrmask & LO_ELE_SELECTED) && (lStartPos >= (int32)pText->sel_start) && ((int32)pText->sel_end >= lEndPos) ; #if 0 XP_TRACE(("DisplaySubtext args: lStartPos(%d) lEndPos(%d)" " iClear(%d) element: selected(%d) sel_start(%d) sel_end(%d) bSelected(%d)\n", lStartPos, lEndPos, iClear, (pText->ele_attrmask & LO_ELE_SELECTED), (int32)pText->sel_start, (int32)pText->sel_end, bSelected )); #endif if (bSelected) { // Note that we do NOT have the "real" text color if selected, // making it impossible to preview new colors in Character Properties dialog wfe_GetSelectionColors(m_rgbBackgroundColor, &rgbColor, &textBackColor); display_background_color = TRUE; } if(display_background_color) { rgbOldBackgroundColor = ::SetBkColor(hdc, textBackColor); ::SetBkMode(hdc, OPAQUE); } // Select the font. CyaFont *pMyFont; SelectNetscapeFontWithCache( hdc, attr, pMyFont); // Set the text color. COLORREF rgbOldColor = ::SetTextColor(hdc, rgbColor); // Originally, we drew just the substring of characters // that we were asked to. But this did not handle kerning // correctly, since kerned characters could intrude into the // area of the substring. Worse, when selecting, the reverse- // video characters were drawn outside their boundaries, which // caused thin vertical strips of selection to remain when the // selection was erased. // // Now we draw the whole string, clipped to the bounds of the // substring. -- jhp LTRB fullRect; ResolveElement(fullRect, pText->x, pText->y, pText->x_offset, pText->y_offset, pText->width, pText->height); SafeSixteen(fullRect); // Output int iOldDC = ::SaveDC(hdc); ::IntersectClipRect(hdc, (int)Rect.left, (int)Rect.top, (int)Rect.right, (int)Rect.bottom); CIntlWin::TextOutWithCyaFont( pMyFont, INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext)), hdc, CASTINT(fullRect.left), CASTINT(fullRect.top), (const char *)pText->text, CASTINT(pText->text_len)); ::RestoreDC(hdc, iOldDC); ::SetTextColor(hdc, rgbOldColor); // Handle strike, under_line, Spell and INLINEINPUT manually DrawTextPostDecoration(hdc, attr, &Rect, rgbColor ); // Normalize our selection if present. if (display_background_color) { ::SetBkColor(hdc, rgbOldBackgroundColor); ::SetBkMode(hdc, TRANSPARENT); } ReleaseNetscapeFontWithCache( hdc, pMyFont ); ReleaseContextDC(hdc); } } // void CDCCX::DisplaySubtext() #define TABLE_HAS_BORDER(pTable) \ ((pTable)->border_top_width > 0 || (pTable)->border_right_width > 0 || \ (pTable)->border_bottom_width > 0 || (pTable)->border_left_width > 0) void CDCCX::DisplayTable(MWContext *pContext, int iLocation, LO_TableStruct *pTable) { LTRB Rect; int32 iSelectionBorder = 0; BOOL bHaveBorder = TABLE_HAS_BORDER(pTable); BOOL bSelected = pTable->ele_attrmask & LO_ELE_SELECTED; if(ResolveElement(Rect, pTable->x, pTable->y, pTable->x_offset, pTable->y_offset, pTable->width, pTable->height) == TRUE) { SafeSixteen(Rect); LTRB TableRect = Rect; #ifdef EDITOR if( EDT_IS_EDITOR(pContext) && bSelected ) { // Adjust the top or bottom of the rect if table is selected // so the selection encloses area with the caption XP_Rect xpRect; xpRect.left = Rect.left; xpRect.top = Rect.top; xpRect.right = Rect.right; xpRect.bottom = Rect.bottom; if( EDT_AdjustTableRectForCaption(pTable, &xpRect) ) { // Note: we don't change the left and right Rect.top = xpRect.top; Rect.bottom = xpRect.bottom; } // We use the larger rect including caption if selected TableRect = Rect; } #endif //TRACE0("DisplayTable\n"); if( bHaveBorder ) { iSelectionBorder = DisplayTableBorder(Rect, pTable); } #ifdef EDITOR else if( EDT_IS_EDITOR(pContext) ) { if( 0 == pTable->inter_cell_space ) { // When no cell spacing, Table border is on top of cell borders, // so increase by 1 pixel so we always have a distinquishable table border TableRect.Inflate(1); iSelectionBorder = 1; } EditorDisplayZeroWidthBorder(TableRect, bSelected); } // Show extra selection if border was not wide enough for clear selection feedback if( EDT_IS_EDITOR(pContext) && bSelected && iSelectionBorder < ED_SELECTION_BORDER ) { // If directly-drawn selection border is too narrow (or none), // add Inverse-Video highlighting to the maximum thickness allowed // Decrease size by amount of solid border used, if( iSelectionBorder ) TableRect.Inflate(-(iSelectionBorder)); DisplaySelectionFeedback(LO_ELE_SELECTED, TableRect); } #endif //EDITOR } } // handle strike , under_line, Spell and INLINEINPUT after text is drawn. void CDCCX::DrawTextPostDecoration( HDC hdc, LO_TextAttr * attr, LTRB *pRect, COLORREF rgbColor ) { #ifdef font_do_it // font handles underline, strikeOut // Handle strike manually if(attr->attrmask & LO_ATTR_STRIKEOUT) { HPEN cpStrike = ::CreatePen(PS_SOLID, CASTINT(pRect->Height() / 10), rgbColor); HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike); ::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top + pRect->Height() / 2), NULL); ::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->top + pRect->Height() / 2)); ::SelectObject(hdc, pOldPen); VERIFY(::DeleteObject(cpStrike)); } // because netscape font module doesn't support under_list, it is handled manually BOOL bUnderline = FALSE; if(attr->attrmask & LO_ATTR_ANCHOR) { /* * if (prefInfo.m_bUnderlineAnchors) * bUnderline = TRUE; */ } if(attr->attrmask & LO_ATTR_UNDERLINE) { bUnderline = TRUE; } if( bUnderline ) { HPEN cpStrike = ::CreatePen(PS_SOLID, CASTINT(pRect->Height() / 10), rgbColor); HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike); ::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top + pRect->Height()-1 ), NULL); ::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->top + pRect->Height()-1 )); ::SelectObject(hdc, pOldPen); VERIFY(::DeleteObject(cpStrike)); } #endif // font handles underline, strikeOut // Handle Spell and INLINEINPUT manually if(attr->attrmask & (LO_ATTR_SPELL | LO_ATTR_INLINEINPUT) ) { HPEN cpStrike = ::CreatePen(PS_DOT, CASTINT(pRect->Height() / 10), RGB(attr->attrmask & LO_ATTR_SPELL ? 255 : 0, 0, attr->attrmask & LO_ATTR_SPELL ? 255 : 0 ) ); HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike); ::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top + pRect->Height()-1 ), NULL); ::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->top + pRect->Height()-1 )); ::SelectObject(hdc, pOldPen); VERIFY(::DeleteObject(cpStrike)); } } // DrawTextPostDecoration() //TODO add uint32 drawFalg to the interface, check all caller to pass in the drawFlag, // C++ default mechanism doesn't work for calling from C. void CDCCX::DisplayText(MWContext *pContext, int iLocation, LO_TextStruct *pText, XP_Bool iClear) { DisplayText(pContext, iLocation, pText, iClear, 0); // use default if calling grom C. } /* cannot use default drawFlag = 0, if this function is called from C */ // an old interface gateway for caller in C. void CDCCX::DisplayText(MWContext *pContext, int iLocation, LO_TextStruct *pText, XP_Bool iClear, uint32 drawFlag ) { // Figure out the coordinates of where to draw the text. LTRB Rect; if(ResolveElement(Rect, pText->x, pText->y, pText->x_offset, pText->y_offset, pText->width, pText->height) == TRUE) { SafeSixteen(Rect); // cache the attribute pointer LO_TextAttr * attr = pText->text_attr; if (attr) // dmb 11/21/96 - w/o this line, we crash on blinking things like the phonebook. { BOOL display_background_color = !attr->no_background; HDC hdc; hdc = GetContextDC(); // Determine the color. COLORREF rgbColor = ResolveTextColor(attr); // what does layout think the background color is? COLORREF textBackColor = RGB(attr->bg.red, attr->bg.green, attr->bg.blue); // If the text is the same color as the background we are selecting text // and need to go into OPAQUE mode so the text will show up on the screen COLORREF rgbOldBackgroundColor; if (pText->ele_attrmask & LO_ELE_SELECTED) { display_background_color = TRUE; wfe_GetSelectionColors(m_rgbBackgroundColor, &rgbColor, &textBackColor); } if(display_background_color) { rgbOldBackgroundColor = ::SetBkColor(hdc, textBackColor); ::SetBkMode(hdc, OPAQUE); } else { ::SetBkMode(hdc, TRANSPARENT); } // Select the font. // CNetscapeFont *pFont; // HFONT pOldFont = SelectFont(hdc, attr, pFont); // Set the text color. COLORREF rgbOldColor = ::SetTextColor(hdc, rgbColor); // #ifndef NO_TAB_NAVIGATION // draw a focus box if pText is current TabFocus if( drawFlag & FE_DRAW_TAB_FOCUS ) { HPEN pTabFocusPen; HPEN pOldPen; BOOL supportPixel = ::GetDeviceCaps( hdc, RASTERCAPS ) & RC_BITBLT ; if( ! supportPixel ) { pTabFocusPen = ::CreatePen(PS_DOT, 1, rgbColor); pOldPen = (HPEN)::SelectObject(hdc, pTabFocusPen); } DrawTabFocusRect(hdc, supportPixel, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)); if( ! supportPixel ) { ::SelectObject(hdc, pOldPen); VERIFY(::DeleteObject(pTabFocusPen)); } } // #endif /* NO_TAB_NAVIGATION */ CyaFont *pMyFont; SelectNetscapeFontWithCache( hdc, attr, pMyFont); #ifdef DEBUG_aliu ASSERT( pMyFont ); #endif if( pMyFont ) { CIntlWin::TextOutWithCyaFont( pMyFont, INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext)), hdc, CASTINT(Rect.left), CASTINT(Rect.top), (char *)pText->text, CASTINT(pText->text_len) ); } ::SetTextColor(hdc, rgbOldColor); // Handle strike, under_line, Spell and INLINEINPUT manually DrawTextPostDecoration(hdc, attr, &Rect, rgbColor ); #if 0 moved into DrawTextPostDecoration() // Handle Spell and INLINEINPUT manually if(attr->attrmask & (LO_ATTR_SPELL | LO_ATTR_INLINEINPUT) ) { HPEN cpStrike = ::CreatePen(PS_DOT, CASTINT(Rect.Height() / 10), RGB(attr->attrmask & LO_ATTR_SPELL ? 255 : 0, 0, attr->attrmask & LO_ATTR_INLINEINPUT ? 255 : 0 ) ); HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike); ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top + Rect.Height()-1 ), NULL); ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.top + Rect.Height()-1 )); ::SelectObject(hdc, pOldPen); VERIFY(::DeleteObject(cpStrike)); } #endif // Normalize our selection if present. if (display_background_color) { ::SetBkColor(hdc, rgbOldBackgroundColor); ::SetBkMode(hdc, TRANSPARENT); } // ReleaseFont(hdc, pOldFont); ReleaseNetscapeFontWithCache(hdc, pMyFont); ReleaseContextDC(hdc); } } } // void CDCCX::DisplayText() #ifndef MOZ_NGLAYOUT void CDCCX::FreeEmbedElement(MWContext *pContext, LO_EmbedStruct *pEmbed) { // We have our OLE document handle this. GetDocument()->FreeEmbedElement(pContext, pEmbed); } void CDCCX::GetEmbedSize(MWContext *pContext, LO_EmbedStruct *pEmbed, NET_ReloadMethod bReload) { // We have our OLE document handle this. GetDocument()->GetEmbedSize(pContext, pEmbed, bReload); } #endif /* MOZ_NGLAYOUT */ #ifdef LAYERS void CDCCX::GetTextFrame(MWContext *pContext, LO_TextStruct *pText, int32 lStartPos, int32 lEndPos, XP_Rect *frame) { frame->left = pText->x + pText->x_offset; frame->top = pText->y + pText->y_offset; HDC pDC = GetContextDC(); CyaFont *pMyFont; SelectNetscapeFontWithCache( pDC, pText->text_attr, pMyFont ); CSize sz; ResolveTextExtent(pDC, (const char *)pText->text, CASTINT(lStartPos), &sz, pMyFont); frame->left += sz.cx; ResolveTextExtent(pDC, (const char *)pText->text + lStartPos, CASTINT(lEndPos - lStartPos + 1), &sz, pMyFont); frame->right = frame->left + sz.cx; frame->bottom = frame->top + sz.cy; ReleaseNetscapeFontWithCache( pDC, pMyFont ); ReleaseContextDC(pDC); } #endif /* LAYERS */ int CDCCX::GetTextInfo(MWContext *pContext, LO_TextStruct *pText, LO_TextInfo *pTextInfo) { #ifdef MOZ_NGLAYOUT XP_ASSERT(0); return FALSE; #else HDC hdc = GetAttribDC(); // Determine and select the font. CyaFont *pMyFont; SelectNetscapeFontWithCache( hdc, pText->text_attr, pMyFont ); // Get the information regarding the size of the font for layout. SIZE sExtent; ResolveTextExtent( INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext)) , hdc, (const char *)pText->text, pText->text_len, &sExtent, pMyFont); pTextInfo->max_width = sExtent.cx; pTextInfo->ascent = pMyFont->GetAscent(); pTextInfo->descent = pMyFont->GetDescent(); pTextInfo->lbearing = pTextInfo->rbearing = 0; ReleaseNetscapeFontWithCache( hdc, pMyFont ); ReleaseContextDC(hdc); return(TRUE); #endif /* MOZ_NGLAYOUT */ } BOOL CDCCX::ResolveTextExtent(int16 wincsid, HDC pDC, LPCTSTR pString, int iLength, LPSIZE pSize, CyaFont *pMyFont) { // Always measure it because the bytes * mean width algorithm // won't work for many code point. Expecially UTF8 which 3 byte // could be one character which takes 1 or 2 columns. return CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, wincsid, pDC, pString, iLength, pSize); #if 0 BOOL bRetval; // if(pMyFont->GetMeanWidth() == 0 ) { if( ! pMyFont->IsFixedFont() ) { bRetval = CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, wincsid, pDC, pString, iLength, pSize); return(bRetval); } else { // fixed size. pSize->cx = (int) ((long)pMyFont->GetMeanWidth() * (long)iLength); pSize->cy = pMyFont->GetHeight(); bRetval = TRUE; } return(bRetval); #endif } #ifdef TRANSPARENT_APPLET // // This function is called only when applet are windowless and force a // paint on the java side // void CDCCX::DrawJavaApp(MWContext *pContext, int iLocation, LO_JavaAppStruct *pJava) { #if defined(OJI) || defined(JAVA) RECT rect; HDC hDC = GetContextDC(); NPEvent event; FE_Region clip; #ifdef LAYERS clip = GetDrawingClip(); if (clip) { XP_Rect xprect; FE_GetRegionBoundingBox(clip, &xprect); rect.left = CASTINT(xprect.left); rect.top = CASTINT(xprect.top); rect.right = CASTINT(xprect.right); rect.bottom = CASTINT(xprect.bottom); } #endif /* LAYERS */ event.event = WM_PAINT; event.wParam = (uint32)hDC; event.lParam = (uint32)▭ #if defined(OJI) // XXX help #elif defined(JAVA) LJ_HandleEvent(pContext, pJava, (void *)&event); #endif ReleaseContextDC(hDC); #endif } #endif