home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / cxdc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  126.2 KB  |  3,801 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "stdafx.h"
  20. #include "cxdc.h"
  21. #include "cntritem.h"
  22. #include "intlwin.h"
  23. #include "mainfrm.h"
  24. #include "npapi.h"
  25. #include "np.h"
  26. #include "feembed.h"
  27. #include "fmabstra.h"
  28. #include "custom.h"
  29. #include "prefapi.h"
  30. #include "feimage.h"
  31. #include "il_icons.h"
  32. #include "intl_csi.h"
  33. #include "prefinfo.h"
  34. #include "cxprint.h"
  35.  
  36. #ifdef JAVA
  37. #include "java.h"
  38. #endif
  39.  
  40. // These four are all specified in pixels
  41. #define IMAGE_SMICON_MARGIN    4
  42.  
  43. #define IMAGE_SMICON_WIDTH    14
  44. #define IMAGE_SMICON_HEIGHT    16
  45.  
  46. #define IMAGE_SMICON_TEXT_OFFSET    2
  47.  
  48.  
  49. #define IS_SECOND_TO_LAST_LAYER(layer) (CL_GetLayerBelow(layer) &&           \
  50.                 CL_GetLayerName(CL_GetLayerBelow(layer)) &&  \
  51.          (strcmp(CL_GetLayerName(CL_GetLayerBelow(layer)),           \
  52.                  LO_BACKGROUND_LAYER_NAME) == 0))
  53.  
  54. #define LOADBITMAP(id) \
  55.     ::LoadBitmap(AfxGetResourceHandle(), MAKEINTRESOURCE(id))                         
  56.  
  57. CDCCX::CDCCX()    {
  58. //    Purpose:    Constructor for DC Context
  59. //    Arguments:    void 
  60. //    Returns:    none
  61. //    Comments:    Sets the context type basically
  62. //    Revision History:
  63. //        05-27-95    created GAB
  64. //
  65.     m_cxType = DeviceContext;
  66.     m_bOwnDC = FALSE;
  67.     m_bClassDC = FALSE;
  68.  
  69.     //    Our mapping mode will be anisotropic unless those which derive
  70.     //        set otherwise.
  71.     m_MM = MM_ANISOTROPIC;
  72.  
  73.     m_pPal = NULL;
  74.     m_lWidth = 0;
  75.     m_lHeight = 0;
  76.     m_iOffset = 0;
  77.     CString csNo(SZ_NO);
  78.  
  79.     m_pImageDC = NULL;
  80.     curColorSpace = 0;
  81.  
  82.     //    As a default starting background color, use that of the button face.
  83.     m_rgbBackgroundColor = sysInfo.m_clrBtnFace;
  84.     m_rgbDarkColor = sysInfo.m_clrBtnShadow;
  85.     m_rgbLightColor = sysInfo.m_clrBtnHilite;
  86.     Set3DColors(m_rgbBackgroundColor);
  87.  
  88.     //    Set that we have no document, and we currently
  89.     //        won't autodelete what may get assigned in.
  90.     m_pDocument = NULL;
  91.     m_bAutoDeleteDocument = FALSE;
  92.  
  93.     //    No previously selected font.
  94.     m_pSelectedCachedFont = NULL;
  95.     m_lastDCWithCachedFont = NULL;
  96.     
  97.     //    Document has no substance.
  98.     m_lDocWidth = 0;
  99.     m_lDocHeight = 0;
  100.     m_lOrgX = m_lOrgY = 0;
  101.  
  102.  
  103.     //    Start out with some default values in the conversions from pix 2 twips.
  104.     m_lConvertX = 1;
  105.     m_lConvertY = 1;
  106.     GetContext()->convertPixX = 1;
  107.     GetContext()->convertPixY = 1;
  108.  
  109.     // Assume the driver doesn't support 565 mode for 16 bpp DIBs
  110.     m_bRGB565 = FALSE;
  111.  
  112.     //    Allow resolving of layout elements.
  113.     m_bResolveElements = TRUE;
  114.  
  115.     //    We're not in an OLE server.
  116.     m_bOleServer = FALSE;
  117.  
  118.     // Form text entry box font
  119.     m_pFormFixFont = NULL;
  120.     m_pFormPropFont = NULL;
  121.     m_iFormFixCSID = CS_LATIN1;
  122.     m_iFormPropCSID = CS_LATIN1;
  123.  
  124.     m_bLoadImagesNow = FALSE;
  125.     m_bNexttimeLoadImagesNow = FALSE;   
  126.     
  127.     GetContext()->XpixelsPerPoint = 0;        
  128.     GetContext()->YpixelsPerPoint = 0;        
  129. }
  130.  
  131. CDCCX::~CDCCX()    {
  132. //    Purpose:    Destructor for DC Context
  133. //    Arguments:    void
  134. //    Returns:    none
  135. //    Comments:
  136. //    Revision History:
  137. //        05-27-95    created GAB
  138. //
  139.  
  140.     //    If we've got a document, let it know we're gone now.
  141.     if(GetDocument() != NULL)    {
  142.         TRACE("Clearing document context\n");
  143.         GetDocument()->ClearContext();
  144.     }
  145.  
  146.     if(m_pImageDC != NULL)    {
  147.         if (!IsGridCell()) { // only delete the temporary DC if we are the parent.
  148.             if (m_bUseDibPalColors)    
  149.             ::SelectPalette(m_pImageDC, (HPALETTE)::GetStockObject(DEFAULT_PALETTE), TRUE);
  150.             VERIFY(::DeleteDC( m_pImageDC));
  151.         }
  152.     }
  153.  
  154.     // Do not delete the default palette.
  155.     if(m_pPal && m_pPal != WFE_GetUIPalette(NULL))    {
  156.         VERIFY(::DeleteObject(m_pPal));
  157.     }
  158.     if(m_pDocument != NULL && m_bAutoDeleteDocument == TRUE)    {
  159.         //    We call OnCloseDocument here, to delete the document.
  160.         //    If we do this here, it basically indicates that we created the
  161.         //        document ourselves (probably a print context), and it
  162.         //        wasn't made in the MFC framework.
  163.         m_pDocument->OnCloseDocument();
  164.     }
  165.  
  166.     if (curColorSpace)
  167.         IL_ReleaseColorSpace(curColorSpace);
  168. }
  169.  
  170. void CDCCX::DestroyContext()    {
  171.     if(IsDestroyed() == FALSE)  {
  172.         //    Give the document a chance to copy any needed information before
  173.         //        we go down.  This helps the OLE server stuff survive while
  174.         //        the context of the view has gone to the twilight zone and back.
  175.         if(GetDocument())    {
  176.             GetDocument()->CacheEphemeralData();
  177.         }
  178.  
  179.         //    Get rid of all our fonts.
  180.         ClearFontCache();
  181.     }
  182.  
  183.  
  184.     //    Call the base.
  185.     CStubsCX::DestroyContext();
  186. }
  187.  
  188. BOOL CDCCX::ResolveTextExtent(HDC pDC, LPCTSTR pString, int iLength, LPSIZE pSize, CyaFont *pFont)    
  189. {
  190.     return ResolveTextExtent(
  191.         INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()))
  192.         , pDC, pString, iLength, pSize, pFont);
  193. }
  194.  
  195. #ifdef XP_WIN32
  196. static BOOL
  197. SupportsRGB565(HDC pDC)
  198. {
  199.     BITMAPINFO *lpBMInfo = NULL;
  200.     int            iFlags;
  201.     int            nSize = sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD);
  202.     LPDWORD     lpMasks;
  203.  
  204.     // Use the QUERYDIBSUPPORT escape to determine if the driver
  205.     // supports RGB565 format DIBs
  206.     lpBMInfo = (BITMAPINFO *)XP_ALLOC(nSize);
  207.     if (!lpBMInfo)
  208.         return FALSE;
  209.     
  210.     memset(lpBMInfo, 0, nSize);    
  211.     lpBMInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  212.     lpBMInfo->bmiHeader.biWidth = 10;
  213.     lpBMInfo->bmiHeader.biHeight = 10;
  214.     lpBMInfo->bmiHeader.biPlanes = 1;
  215.     lpBMInfo->bmiHeader.biBitCount = 16;
  216.     lpBMInfo->bmiHeader.biCompression = BI_BITFIELDS;
  217.  
  218.     // Define the color masks for a RGB565 DIB
  219.     lpMasks = (LPDWORD)lpBMInfo->bmiColors;
  220.     lpMasks[0] = 0xF800;  // red color mask
  221.     lpMasks[1] = 0x07E0;  // green color mask
  222.     lpMasks[2] = 0x001F;  // blue color mask
  223.  
  224.     // Ask the driver
  225.     ::Escape(pDC, QUERYDIBSUPPORT, nSize, (LPCSTR)lpBMInfo, &iFlags);
  226.     XP_FREE(lpBMInfo);
  227.  
  228.     return (iFlags & (QDI_SETDIBITS | QDI_DIBTOSCREEN | QDI_STRETCHDIB)) != 0;
  229. }
  230. #endif
  231.  
  232. void CDCCX::PrepareDraw()
  233. {
  234.     if (m_pImageDC) {
  235.         if (m_bUseDibPalColors && m_pPal) 
  236.             ::SelectPalette(m_pImageDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
  237.         ::DeleteDC(m_pImageDC);
  238.     }
  239.     m_pImageDC = ::CreateCompatibleDC(GetContextDC());
  240.     if (m_bUseDibPalColors && m_pPal)    {
  241.         ::SelectPalette(m_pImageDC, m_pPal, FALSE);
  242.     }
  243.  
  244. }
  245.  
  246. void CDCCX::EndDraw()
  247. {
  248.     if (m_pImageDC) {
  249.         if (m_bUseDibPalColors && m_pPal) 
  250.             ::SelectPalette(m_pImageDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
  251.         ::DeleteDC(m_pImageDC);
  252.     }
  253.     m_pImageDC = 0;
  254. }
  255.  
  256.  
  257. void CDCCX::Initialize(BOOL bOwnDC, RECT *pRect, BOOL bInitialPalette, BOOL bNewMemDC)    {
  258.     //    First thing, we need to create a document
  259.     //        if no one has bothered assigning us one.
  260.     if(m_pDocument == NULL)    {
  261.         m_pDocument = new CGenericDoc();
  262.         m_bAutoDeleteDocument = TRUE;    //    We clean up.
  263.     }
  264.  
  265.     //    There exists a document.
  266.     //    Let it know which context it can manipulate.
  267.     GetDocument()->SetContext(this);
  268.  
  269.     HDC hdc = GetContextDC();
  270.  
  271.     //    Initialize some values which are used in CDC contexts
  272.     //        for drawing purposes.
  273.     SetMappingMode(hdc);
  274.     ::SetBkMode(hdc, TRANSPARENT);
  275.  
  276.     //    Figure out the depth of the CDC.
  277.     m_iBitsPerPixel = sysInfo.m_iBitsPerPixel;
  278.  
  279.     //    Now, if the bits per pixel are less than 16, and this device doesn't support
  280.     //        a palette, then we need to set the bits per pixel to a very high value
  281.     //        to emulate true color (so that we don't attempt to use the palette
  282.     //        function later on).
  283.     //    This is the Epson Stylus Color Printer bug fix on Win16.
  284.     if(m_iBitsPerPixel < 16 && (::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == 0)    {
  285.         //  24 is the largest common denominator which we should be able to set
  286.         //      in order to avoid palette operations.
  287.         //  Uped to 24 from 16 as the Hewlett Packard Laserjet 5L bug fix on Win32.
  288.             m_iBitsPerPixel = 24;
  289.     }
  290.  
  291.     //    Detect if we are going to be using DibPalColors. We only do this if the device
  292.     // is a palette device and we never do this when printing
  293.     m_bUseDibPalColors = !IsPrintContext() && (::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE);
  294.  
  295.  
  296.     //    Do some stretch blit setup.
  297. #ifndef WIN32
  298.     ::SetStretchBltMode(hdc, STRETCH_DELETESCANS);
  299. #else
  300.     ::SetStretchBltMode(hdc, COLORONCOLOR);
  301. #endif
  302.  
  303.     JMCException* exc = NULL;
  304.     IMGCB* imageLibObj = IMGCBFactory_Create(&exc);
  305.  
  306.     m_pImageGroupContext = IL_NewGroupContext(GetContext(), (IMGCBIF *)imageLibObj);
  307.     GetContext()->img_cx = m_pImageGroupContext; // Need this to be cross platform.
  308.     IL_AddGroupObserver(m_pImageGroupContext, ImageGroupObserver, (void*)GetContext());
  309.  
  310.     COLORREF rgbColor = prefInfo.m_rgbBackgroundColor;
  311.     SetTransparentColor(GetRValue(rgbColor), GetGValue(rgbColor), GetBValue(rgbColor));
  312.     if (!IsGridCell()) {
  313.         if(m_iBitsPerPixel < 16) {
  314.  
  315.             //    Set the transparency to a default color.
  316.             //    This may change below.
  317.             SetTransparentColor(192, 192, 192);
  318.  
  319.             //    Set up the per-context palette.
  320.             //    This is per-window since not everything goes to the screen, and therefore
  321.             //        won't always have the screen's attributes. (printing, metafiles DCs, etc).
  322.             IL_ColorMap * defaultColorMap =  IL_NewCubeColorMap(NULL, 0,
  323.                            MAX_IMAGE_PALETTE_ENTRIES+1);
  324.             if (bInitialPalette)
  325.                 m_pPal = CDCCX::InitPalette(hdc);
  326.             else // If we don't want to initialize the Palette, use the default palette.
  327.                 m_pPal = WFE_GetUIPalette(NULL);
  328.             CDCCX::SetColormap(hdc, defaultColorMap, rgbTransparentColor, m_pPal);
  329.             curColorSpace = IL_CreatePseudoColorSpace(defaultColorMap, MAX_IMAGE_PALETTE_ENTRIES+1,
  330.                               m_iBitsPerPixel);
  331.             HPALETTE hOldPal = NULL;
  332.             if(m_pPal)    {
  333.                 if ( bInitialPalette) 
  334.                     hOldPal = (HPALETTE) ::SelectPalette(hdc, m_pPal, FALSE);
  335.                 else
  336.                     hOldPal = (HPALETTE) ::SelectPalette(hdc, m_pPal, TRUE);
  337.                 int error = RealizePalette(hdc);      // In with the new
  338.             }
  339. #ifdef DEBUG_mhwang
  340.             HWND hwnd = ::GetFocus();
  341. #endif
  342.  
  343.         }
  344.         else { // use RGB value
  345.             IL_RGBBits colorRGBBits;
  346.         //    Enable true color.
  347.             if(m_iBitsPerPixel >= 16)    {
  348.                 if(m_iBitsPerPixel == 16)    {
  349.         #ifdef XP_WIN32
  350.                     // If this is Win95 we need to do rounding during quantization of
  351.                     // 24 bpp RGB values to 16 bpp RGB values
  352.                     if (sysInfo.IsWin4_32() == TRUE &&
  353.                         SupportsRGB565(hdc) != FALSE &&
  354.                         IsPrintContext() == FALSE) {
  355.  
  356.                         //    Metafiles can't handle this hack.
  357.                         //    Also, the image lib will force metafiles to share the
  358.                         //        same image even though the settings would be slightly different.
  359.                         //    Pump us up to 24 bit images in this case.
  360.                         if(GetContextType() == MetaFile)    {
  361.                             colorRGBBits.red_shift = 16;  
  362.                             colorRGBBits.red_bits = 8;            /* Offset for red channel bits. */
  363.                             colorRGBBits.green_shift = 8;           /* Number of bits assigned to green channel. */
  364.                             colorRGBBits.green_bits = 8;          /* Offset for green channel bits. */
  365.                             colorRGBBits.blue_shift = 0;            /* Number of bits assigned to blue channel. */
  366.                             colorRGBBits.blue_bits = 8;           /* Offset for blue channel bits. */
  367.                             curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24);
  368.  
  369.                         }
  370.                         else    {
  371.                             m_bRGB565 = TRUE;  // remember this when building BITMAPINFO struct
  372.                             colorRGBBits.red_shift = 11;  
  373.                             colorRGBBits.red_bits = 5;            /* Offset for red channel bits. */
  374.                             colorRGBBits.green_shift = 5;           /* Number of bits assigned to green channel. */
  375.                             colorRGBBits.green_bits = 6;          /* Offset for green channel bits. */
  376.                             colorRGBBits.blue_shift = 0;            /* Number of bits assigned to blue channel. */
  377.                             colorRGBBits.blue_bits = 5;           /* Offset for blue channel bits. */
  378.                             curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 16);
  379.                         }
  380.  
  381.                     } else {
  382.                         colorRGBBits.red_shift = 10;  
  383.                         colorRGBBits.red_bits = 5;            /* Offset for red channel bits. */
  384.                         colorRGBBits.green_shift = 5;           /* Number of bits assigned to green channel. */
  385.                         colorRGBBits.green_bits = 5;          /* Offset for green channel bits. */
  386.                         colorRGBBits.blue_shift = 0;            /* Number of bits assigned to blue channel. */
  387.                         colorRGBBits.blue_bits = 5;           /* Offset for blue channel bits. */
  388.                         curColorSpace =IL_CreateTrueColorSpace(&colorRGBBits, 16);
  389.                     }
  390.         #else
  391.                     // 16 bpp DIB format isn't supported by all drivers in Win 3.1
  392.                     colorRGBBits.red_shift = 16;  
  393.                     colorRGBBits.red_bits = 8;            /* Offset for red channel bits. */
  394.                     colorRGBBits.green_shift = 8;           /* Number of bits assigned to green channel. */
  395.                     colorRGBBits.green_bits = 8;          /* Offset for green channel bits. */
  396.                     colorRGBBits.blue_shift = 0;            /* Number of bits assigned to blue channel. */
  397.                     colorRGBBits.blue_bits = 8;           /* Offset for blue channel bits. */
  398.                     curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24);
  399.         #endif
  400.                 }
  401.                 else  {
  402.                     colorRGBBits.red_shift = 16;  
  403.                     colorRGBBits.red_bits = 8;            /* Offset for red channel bits. */
  404.                     colorRGBBits.green_shift = 8;           /* Number of bits assigned to green channel. */
  405.                     colorRGBBits.green_bits = 8;          /* Offset for green channel bits. */
  406.                     colorRGBBits.blue_shift = 0;            /* Number of bits assigned to blue channel. */
  407.                     colorRGBBits.blue_bits = 8;           /* Offset for blue channel bits. */
  408.                     curColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24);
  409.                 }
  410.             }
  411.         }
  412.         GetContext()->color_space = curColorSpace; // Need this to be cross platform.
  413.     }
  414.     else {
  415.         MWContext* cxtx = GetParentContext();
  416.         GetContext()->color_space = cxtx->color_space;
  417.         curColorSpace =cxtx->color_space; 
  418.         IL_AddRefToColorSpace(curColorSpace);
  419.         m_bRGB565 = CXDC(cxtx)->m_bRGB565;
  420.     }
  421.     
  422.     IL_AddRefToColorSpace(GetContext()->color_space);
  423.     //    Get image prefs on a per context basis.
  424.     IL_DitherMode ditherMode = IL_Auto; 
  425.  
  426.     char * prefStr=NULL;
  427.     PREF_CopyCharPref("images.dither",&prefStr);
  428.     // Images
  429.     if (prefStr) {
  430.         if(!strcmpi(prefStr,"yes")) { 
  431.             ditherMode = IL_Dither;
  432.         } else if(!strcmpi(prefStr,"no")) {   // closest
  433.             ditherMode = IL_ClosestColor;
  434.         } else {
  435.             ditherMode = IL_Auto;
  436.         }
  437.         XP_FREE(prefStr);
  438.     }
  439.  
  440.     PRBool bIncremental = ResolveIncrementalImages();
  441.     IL_DisplayData displayData;
  442.     displayData.dither_mode = IL_Auto;
  443.  
  444.     if (IsPrintContext())
  445.         displayData.display_type = IL_Printer;
  446.     else
  447.         displayData.display_type = IL_Console;
  448.     displayData.color_space = curColorSpace;
  449.     displayData.progressive_display= bIncremental;
  450.     IL_SetDisplayMode(m_pImageGroupContext, IL_PROGRESSIVE_DISPLAY | IL_DITHER_MODE | IL_COLOR_SPACE | IL_DISPLAY_TYPE,
  451.                   &displayData);
  452.  
  453.     if (bNewMemDC) {
  454.         if (!IsGridCell()) {  // only create the tempary CD only for gird parent.
  455.         //    Ensure our memory DC exists for speedy image draws.
  456.             m_pImageDC = ::CreateCompatibleDC(hdc);
  457.             if (m_bUseDibPalColors && m_pPal)    {
  458.                 ::SelectPalette(m_pImageDC, m_pPal, FALSE);
  459.             }
  460.         }
  461.         else {
  462.             MWContext *parentContext = GetParentContext();
  463.             m_pImageDC = CXDC(parentContext)->m_pImageDC; 
  464.         }
  465.     }
  466.     GetContext()->XpixelsPerPoint = ((double)GetDeviceCaps (GetAttribDC(), LOGPIXELSX)) / 72.0 ;
  467.     GetContext()->YpixelsPerPoint = ((double)GetDeviceCaps (GetAttribDC(), LOGPIXELSY)) / 72.0 ;
  468.  
  469. #ifdef DEBUG_aliu
  470.     double dd = ((double)GetDeviceCaps (hdc, LOGPIXELSX)) / 72.0 ;
  471.     dd = ((double)GetDeviceCaps (hdc, LOGPIXELSY)) / 72.0 ;
  472. #endif
  473.  
  474.     ReleaseContextDC(hdc);
  475.  
  476.     //    We optimize those DCs which we know are persistant (don't change or reset
  477.     //        their values) for font caching and other stuff.
  478.     //    As a default, consider all such DC classes as persistent, if not, then
  479.     //        set this value otherwise.
  480.     //    This needs to go at the end of this function, since the mapping mode should
  481.     //        now be correctly set, et al....
  482.     m_bOwnDC = bOwnDC;
  483.  
  484. #ifdef LAYERS
  485.     GetContext()->compositor = NULL;
  486. #endif // LAYERS
  487.  
  488. }
  489.  
  490. //    Default implementation of incremental image display switch.
  491. PRBool CDCCX::ResolveIncrementalImages()
  492. {
  493.     XP_Bool bRetval = prefInfo.m_bAutoLoadImages;
  494.     
  495.     return (bRetval) ? PR_TRUE : PR_FALSE;
  496. }
  497.  
  498. HPALETTE CDCCX::GetPalette() const    {
  499.     //    Return our palette.
  500.     return(m_pPal);
  501. }
  502.  
  503.  
  504. void CDCCX::ClearFontCache()    {
  505.     //    If we're a persistant DC, we need to select a stock object before we release
  506.     //        all the fonts.
  507.     if(IsClassDC() || IsOwnDC())    {
  508.         HDC hdc = GetContextDC();
  509.         ::SelectObject(hdc, ::GetStockObject(ANSI_FIXED_FONT));
  510.         ReleaseContextDC(hdc);
  511.  
  512.         //    We have no previously selected font.
  513.         m_pSelectedCachedFont = NULL;
  514.         m_lastDCWithCachedFont = NULL;
  515.  
  516.     }
  517.  
  518.     //  Tell layout to get rid of all of it's cached FE font data
  519.     //      in the LO_TextAttr.
  520.     LO_InvalidateFontData(GetDocumentContext());
  521.  
  522.  
  523.     //  Go through our context list of cached fonts and get rid of them all.
  524.     POSITION rIndexnew = m_cplCachedFontList.GetHeadPosition();
  525.     CyaFont *pCachedFont = NULL;
  526.     while(rIndexnew)   {
  527.         pCachedFont = (CyaFont *)m_cplCachedFontList.GetNext(rIndexnew);
  528.         if(pCachedFont) {
  529.             delete pCachedFont;
  530.         }
  531.     }
  532.     //  Remove them all from the list.
  533.     if(!m_cplCachedFontList.IsEmpty())   {
  534.         m_cplCachedFontList.RemoveAll();
  535.     }
  536.  
  537.     //  Get rid of widget fonts.
  538.     if(m_pFormFixFont) {
  539.         VERIFY(::DeleteObject(m_pFormFixFont));
  540.         m_pFormFixFont = NULL;
  541.     }
  542.     if(m_pFormPropFont)    {
  543.         VERIFY(::DeleteObject(m_pFormPropFont));
  544.         m_pFormPropFont = NULL;
  545.     }
  546. }
  547.  
  548. void CDCCX::ClearAllFontCaches()    {
  549.     MWContext *pTraverseContext = NULL;
  550.     CAbstractCX *pTraverseCX = NULL;
  551.     XP_List *pTraverse = XP_GetGlobalContextList();
  552.     while (pTraverseContext = (MWContext *)XP_ListNextObject(pTraverse)) {
  553.         if(pTraverseContext != NULL && ABSTRACTCX(pTraverseContext) != NULL)    {
  554.             pTraverseCX = ABSTRACTCX(pTraverseContext);
  555.  
  556.             if(pTraverseCX->IsDCContext() == TRUE)    {
  557.                 CDCCX *pDCCX = VOID2CX(pTraverseCX, CDCCX);
  558.                 pDCCX->ClearFontCache();
  559.             }
  560.         }
  561.     }
  562. }
  563.  
  564.  
  565. // size is the size of the font from layout
  566. // iBaseSize is the users font size from the encoding
  567. // iOffset is the offset based on increment and decrement font
  568. double CDCCX::CalcFontPointSize(int size, int iBaseSize, int iOffset)
  569. {
  570.     double dFontSize;
  571.  
  572.     if( iBaseSize <=0 )
  573.            iBaseSize = 10;
  574.  
  575. /*    size += iOffset;*/
  576.     if(size < 0)
  577.         size = 0;
  578.  
  579.     if(size  > 8)
  580.         size = 8;
  581.  
  582.     switch(size)    {
  583.     case 0:
  584.         dFontSize = iBaseSize / 2;
  585.         break;
  586.     case 1:
  587.         dFontSize = 7 * iBaseSize / 10;
  588.         break;
  589.     case 2:
  590.         dFontSize = 85 * iBaseSize / 100;
  591.         break;
  592.     case 4:
  593.         dFontSize = 12 * iBaseSize / 10;
  594.         break;
  595.     case 5:
  596.         dFontSize = 3 * iBaseSize / 2;
  597.         break;
  598.     case 6:
  599.         dFontSize = 2 * iBaseSize;
  600.         break;
  601.     case 7:
  602.         dFontSize = 3 * iBaseSize;
  603.         break;
  604.     case 8:
  605.         dFontSize = 4 * iBaseSize;
  606.         break;
  607.     case 3:
  608.     default:
  609.         dFontSize = iBaseSize;
  610.     }
  611.  
  612.     //if(MMIsText() != TRUE)      // for printer scaling to pointsize interface.
  613. //        dFontSize *= 2.8;            //todo  this is a hack!!
  614.  
  615.     if(GetContext())
  616.         dFontSize *= GetContext()->fontScalingPercentage;
  617.  
  618.     return dFontSize;
  619.  
  620. }    // CalcFontPointSize
  621.  
  622.  
  623. // Manage DC level font cache: If font is selected into dc, don't do anything.
  624. // Otherwise, call SelectNetscapeFont() and cache it into dc.
  625. // return 1 if we miss any font in pAttr->font_face list.
  626. int CDCCX::SelectNetscapeFontWithCache( HDC hdc, LO_TextAttr *pAttr, CyaFont *& pMyFont )    
  627. {
  628. //    Purpose:    Font selector
  629. //    Arguments:    pDC    The DC in which to select the font
  630. //                pAttr    Layout attributes by which we select the font.
  631. //                pSelected    This is more of a return value.  It sets the reference of
  632. //                    the pointer value ot the font actually selected.
  633. //    Returns:    no meaning, old font is saved in CyaFont.
  634. //    Comments:
  635.  
  636.     //    Determine the size of the font and other stuff.
  637.     //    Get the font out of the cache.
  638.     int        returnCode = 0;        // assuming we don't miss any font.
  639. // #ifdef nofontcache
  640.     CyaFont *pCachedFont = (CyaFont *)pAttr->FE_Data;
  641.     pMyFont = pCachedFont;
  642.     //    See if we've already got this font selected if we're a persistant DC.
  643.     //    We'll assume it's in the font cache if so.
  644.     if(IsOwnDC() == TRUE && m_lastDCWithCachedFont == hdc && m_pSelectedCachedFont) {
  645.         if(  m_pSelectedCachedFont == pCachedFont)   {
  646.             //    Simply return, already selected.
  647.             return( 0 );
  648.         } else { 
  649.             // relase the selected font.
  650.             ReleaseNetscapeFont( hdc, m_pSelectedCachedFont );
  651.             m_pSelectedCachedFont = NULL;
  652.             m_lastDCWithCachedFont = NULL;
  653.             // fall through to select a font.
  654.         }
  655.     } 
  656.  
  657.     // create font (or use FE_Data cached font) for the text 
  658.     returnCode = SelectNetscapeFont( hdc, pAttr, pMyFont );
  659.  
  660.     if( ! pMyFont->IsEmptyFont() ) {
  661.  
  662.         //    If this is a persistant DC, then we mark the font currently selected so that
  663.         //        we don't select it again if the same request comes in.
  664.         //    We don't want to do this if this was the memory DC we're dealing with.
  665.         if(IsOwnDC() == TRUE)    {
  666.             m_lastDCWithCachedFont = hdc;
  667.             m_pSelectedCachedFont = pMyFont;        // pSelectThis;
  668.         }
  669.     }
  670. //#else 
  671. //    returnCode = SelectNetscapeFont( hdc, pAttr, pMyFont );
  672. //#endif // nofontcache
  673.  
  674.     return( returnCode );
  675.  
  676. }
  677.  
  678. // SelectNetscapeFont() does:
  679. // always select the font into dc.
  680. // manage FE_Data level cache.
  681. // Create the font if not cached, 
  682. // follow font list and use default font at last.
  683. // return 1 if the any font in list not found.
  684. // After creation, 
  685. //    cache it into FE_Data, and calculate meanwidth.
  686. //    link-list the font, so it can be deleted when destroy document.
  687. int CDCCX::SelectNetscapeFont( HDC hdc, LO_TextAttr *pAttr, CyaFont *& pMyFont )
  688. {
  689.     // create font for the text and cache it in pAttr->FE_Data.
  690.     EncodingInfo *pEncoding = theApp.m_pIntlFont->GetEncodingInfo(GetContext());
  691.     BOOL bItalic = FALSE;
  692.     BOOL bFixed = FALSE;
  693.     int iFontWeight = FW_NORMAL;
  694.     double    dFontSize;
  695.     int iBaseSize;
  696.     int iCharset = DEFAULT_CHARSET;  // used for Win95 font selection
  697.     char aFontName[MAXFONTFACENAME];
  698.     char        * pCharsetStr;
  699.     int            reCode;
  700.     int        returnCode = 0;        // assuming we don't miss any font.
  701.  
  702.     CyaFont *pCachedFont = (CyaFont *)pAttr->FE_Data;
  703.     if(pCachedFont != NULL && ! pCachedFont->IsEmptyFont() )    {
  704.         //    It's cached.
  705.  
  706.         //    use the old font, and select the font.
  707.         pMyFont = pCachedFont;
  708.         pMyFont->PrepareDrawText( hdc );               // actually, select the font into hdc
  709.         return( 0 );                                   // we don't miss this font.
  710.     }
  711.  
  712.     // retrieve face-name-independent attributes first.
  713.  
  714.     if(pAttr->fontmask & LO_FONT_BOLD)    { 
  715.         iFontWeight = FW_BOLD;
  716.     }
  717.  
  718.     // font_weight has the highest priority.
  719.     if( pAttr->font_weight > 0 )
  720.         iFontWeight = pAttr->font_weight;
  721.  
  722.     if(pAttr->fontmask & LO_FONT_ITALIC)    {
  723.         bItalic = TRUE;
  724.     }
  725.  
  726.     if(pAttr->fontmask & LO_FONT_FIXED)    {
  727.         bFixed = TRUE;
  728.     }
  729.  
  730.     if( bFixed)    {
  731.         iBaseSize = pEncoding->iFixSize;
  732.         iCharset = pEncoding->iFixCharset;
  733.     } else {  // ! bFixed 
  734.         iBaseSize = pEncoding->iPropSize;
  735.         iCharset = pEncoding->iPropCharset;
  736.     }
  737.  
  738.     //    Map the base size to the real font size.
  739.     dFontSize = CalcFontPointSize(pAttr->size, iBaseSize, m_iOffset);
  740.  
  741.     // pAttr->point_size has the highest priority.
  742.     if( pAttr->point_size > 0 ) {   
  743.         dFontSize = pAttr->point_size;
  744.      }
  745.     
  746.     // save the encording flag in font, so it will use textOutW() for Unicode.
  747.     // refer to BOOL CIntlWin::TextOut() in file intlwin.cpp
  748.     // INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext))
  749.     char *pEncordingStr = NULL;
  750.     int        isUnicode = 0;
  751. #ifdef XP_WIN32
  752.     if ( CIntlWin::UseUnicodeFontAPI( pEncoding->iCSID ) &&
  753.          ! ( pEncoding->iCSID == CS_UTF8  && CIntlWin::UseVirtualFont()) ) {
  754.         // set the encording to use ::TextOutW()
  755.         pEncordingStr    = "Unicode";
  756.         isUnicode        = 1;
  757.     }
  758. #endif
  759.  
  760.     int nUnderline = nfUnderlineDontCare ;
  761.     if(pAttr->attrmask & LO_ATTR_ANCHOR) { 
  762.         XP_Bool prefBool = prefInfo.m_bUnderlineAnchors; //  ? prefInfo.m_bUnderlineAnchors->m_Value.xp_bool : TRUE;
  763.         if(prefBool)
  764.             nUnderline = nfUnderlineYes;
  765.     }
  766.     if(pAttr->attrmask & LO_ATTR_UNDERLINE)    {
  767.         nUnderline = nfUnderlineYes;
  768.     }
  769.     
  770.     pMyFont = new CyaFont();
  771.  
  772.     //  If a font name is listed, use that instead.
  773.     BOOL bUseDefault = TRUE;
  774.  
  775.     if(pAttr->font_face)    {
  776.         //  Go through the comma delimeted list, and find one that we have.
  777.         char wantedFontName[MAXFONTFACENAME];
  778.         char *pFontName    = NULL;
  779.         int     offSet = 0;
  780.         do {
  781.             offSet = FEU_ExtractCommaDilimetedFontName(pAttr->font_face, offSet, wantedFontName );
  782.  
  783.             // for(int iTraverse = 1; pExtracted = FEU_ExtractCommaDilimetedString(pAttr->font_face, iTraverse); iTraverse++)    
  784.             if( offSet > 0 && *wantedFontName != 0)  {
  785.                 pFontName = theGlobalNSFont.converGenericFont(wantedFontName);
  786.  
  787.                 strcpy(aFontName, pFontName);
  788.                 if(CIntlWin::UseUnicodeFontAPI(pEncoding->iCSID))    {
  789.                     iCharset = DEFAULT_CHARSET;
  790.                 }
  791.                 // On Win95, charset info is important for Wingdings font
  792.                 if (sysInfo.m_bWin4 && (strcmpi(aFontName, "wingdings") == 0))
  793.                     iCharset = DEFAULT_CHARSET;
  794.                 // web font use string for charSet
  795.                 pCharsetStr  = theGlobalNSFont.convertToFmiCharset( iCharset );
  796.  
  797.                 if (isUnicode == 0 )
  798.                 {
  799.                     pEncordingStr = pCharsetStr;
  800.                 }
  801.  
  802.                 //    Create the font.
  803.                 reCode = pMyFont->CreateNetscapeFont(
  804.                     GetContext(),
  805.                     hdc,                                    // HDC        hDC, 
  806.                     aFontName,                                // char    *FmiName,
  807.                     pCharsetStr,                            // char    *FmiCharset,
  808.                     pEncordingStr,                            // char    *FmiEncoding,
  809.                     iFontWeight,                            // int     FmiWeight,
  810.                     bFixed?nfSpacingMonospaced:nfSpacingProportional,            // int     FmiPitch,
  811.                     bItalic?nfStyleItalic:nfStyleNormal,    // int     FmiStyle,    
  812.                     nUnderline,                                // int        FmiUnderline,
  813.                     (pAttr->attrmask & LO_ATTR_STRIKEOUT) ? nfStrikeOutYes : nfStrikeOutDontCare, // int     FmiStrikeOut,
  814.                     0,                                        // int     FmiResolutionX,
  815.                     ::GetDeviceCaps(GetAttribDC(), LOGPIXELSY),        // int     FmiResolutionY,
  816.                     dFontSize                                // int        fontHeight        // not a fmi field
  817.                 ); 
  818.                 
  819.                 //if( theGlobalNSFont.HasFaceName( hdc, pExtracted)) 
  820.                     //  Use this.
  821.                 if( reCode == FONTERR_OK ) {
  822.                     bUseDefault = FALSE;        // we got the font!
  823.                 } else {
  824.                     // remenber there is font face name not found, 
  825.                     returnCode = 1;
  826.                 }
  827.             }
  828.  
  829.             //  Our responsibility to clean this up.
  830.             // XP_FREE(pExtracted);
  831.  
  832.             //  If we've set that we're using a font, get out.
  833.             if(!bUseDefault) {
  834.                 break;
  835.             }
  836.         }    while ( offSet > 0 );  // do  offSet = FEU_ExtractCommaDilimetedFontName() ...
  837.     }    // if(pAttr->font_face)
  838.  
  839.     if(bUseDefault)  {
  840.         if( bFixed)    
  841.             strcpy(aFontName, pEncoding->szFixName);
  842.         else   // ! bFixed 
  843.             strcpy(aFontName, pEncoding->szPropName);
  844.  
  845.         if(CIntlWin::UseUnicodeFontAPI(pEncoding->iCSID))    {
  846.             iCharset = DEFAULT_CHARSET;
  847.         }
  848.         // On Win95, charset info is important for Wingdings font
  849.         if (sysInfo.m_bWin4 && (strcmpi(aFontName, "wingdings") == 0))
  850.             iCharset = DEFAULT_CHARSET;
  851.         // web font use string for charSet
  852.         pCharsetStr  = theGlobalNSFont.convertToFmiCharset( iCharset );
  853.         if (isUnicode == 0 )
  854.         {
  855.             pEncordingStr = pCharsetStr;
  856.         }
  857.  
  858.         //    Create the font.
  859.         reCode = pMyFont->CreateNetscapeFont(
  860.             GetContext(),
  861.             hdc,                                    // HDC        hDC, 
  862.             aFontName,                                // char    *FmiName,
  863.             pCharsetStr,                            // char    *FmiCharset,
  864.             pEncordingStr,                            // char    *FmiEncoding,
  865.             iFontWeight,                            // int     FmiWeight,
  866.             bFixed?nfSpacingMonospaced:nfSpacingProportional,            // int     FmiPitch,
  867.             bItalic?nfStyleItalic:nfStyleNormal,    // int     FmiStyle,    
  868.             nUnderline,                                // int        FmiUnderline,
  869.             (pAttr->attrmask & LO_ATTR_STRIKEOUT) ? nfStrikeOutYes : nfStrikeOutDontCare, // int     FmiStrikeOut,
  870.             0,                                        // int     FmiResolutionX,
  871.             ::GetDeviceCaps(GetAttribDC(), LOGPIXELSY),        // int     FmiResolutionY,
  872.             dFontSize                                // int        fontHeight        // not a fmi field
  873.         ); 
  874.     }
  875.  
  876.     if( FONTERR_OK != reCode ) {
  877.         // user selected default font failed, use hardcoded default font
  878.         iCharset = DEFAULT_CHARSET;
  879.         
  880.         // web font use string for charSet
  881.         pCharsetStr  = theGlobalNSFont.convertToFmiCharset( iCharset );
  882.         if (isUnicode == 0 )
  883.         {
  884.             pEncordingStr = pCharsetStr;
  885.         }
  886.  
  887.         // get the face name
  888. #ifdef _WIN32
  889.         LOGFONT   theLogFont;
  890.         CFont    *pCFont= CFont::FromHandle((HFONT)GetStockObject(bFixed?ANSI_FIXED_FONT:ANSI_VAR_FONT));
  891.         pCFont->GetLogFont( &theLogFont );
  892.         strncpy(aFontName, theLogFont.lfFaceName,LF_FACESIZE);
  893. #else
  894.         strncpy(aFontName, ( bFixed? "Courier New" : "Times New Roman" ) ,LF_FACESIZE);
  895. #endif
  896.         //    Create the font.
  897.         reCode = pMyFont->CreateNetscapeFont(
  898.             GetContext(),
  899.             hdc,                                    // HDC        hDC, 
  900.             aFontName,                            // char    *FmiName,
  901.             pCharsetStr,                            // char    *FmiCharset,
  902.             pEncordingStr,                            // char    *FmiEncoding,
  903.             iFontWeight,                            // int     FmiWeight,
  904.             bFixed?nfSpacingMonospaced:nfSpacingProportional,            // int     FmiPitch,
  905.             bItalic?nfStyleItalic:nfStyleNormal,    // int     FmiStyle,    
  906.             nUnderline,                                // int        FmiUnderline,
  907.             (pAttr->attrmask & LO_ATTR_STRIKEOUT) ? nfStrikeOutYes : nfStrikeOutDontCare, // int     FmiStrikeOut,
  908.             0,                                        // int     FmiResolutionX,
  909.             ::GetDeviceCaps(GetAttribDC(), LOGPIXELSY),        // int     FmiResolutionY,
  910.             dFontSize                                // int        fontHeight        // not a fmi field
  911.         ); 
  912.     }
  913.  
  914.     //     if( FONTERR_OK != reCode )    real problem, todo show dialog to user!!!
  915.  
  916.     //    Select the font.
  917.     pMyFont->PrepareDrawText( hdc );               // actually, select the font into hdc
  918.  
  919.     pMyFont->CalculateMeanWidth( hdc, isUnicode);
  920.  
  921.     // and cache it in pAttr->FE_Data.
  922.     //    Cache this font for future usage.
  923.     //  First, make sure that the text attribute points to it.
  924.     pAttr->FE_Data = (void *)pMyFont;
  925.  
  926.     //  Second, add it to our context list of fonts (so we know to delete it later).
  927.     m_cplCachedFontList.AddTail((void *)pMyFont);  // pSelectThis
  928.  
  929.     return( returnCode );
  930. }    // HFONT CDCCX::SelectNetscapeFont()
  931.  
  932. void CDCCX::ReleaseNetscapeFontWithCache(HDC hdc, CyaFont * pNetscapeFont)    
  933. {
  934. //#ifdef nofontcache
  935.     if( IsOwnDC() == TRUE )
  936.         return;
  937.     m_pSelectedCachedFont = NULL;
  938.     m_lastDCWithCachedFont = NULL;
  939.  
  940. //#endif
  941.     ReleaseNetscapeFont(hdc, pNetscapeFont);
  942. }
  943.  
  944. void CDCCX::ReleaseNetscapeFont(HDC hdc, CyaFont * pNetscapeFont)
  945. {    
  946.     pNetscapeFont->EndDrawText( hdc );                    // restore the old font.
  947. }
  948.  
  949. // m_iOffset can be at most 8 or at least -8 based on the values in
  950. // CalcFontPointSize;
  951. void CDCCX::ChangeFontOffset(int iIncrementor)
  952. {
  953. /*    BOOL bDontReload = (m_iOffset == 8 && iIncrementor >= 0) || (m_iOffset == -8 && iIncrementor <= 0);
  954.  
  955.     m_iOffset += iIncrementor;
  956.     if(m_iOffset < -8)
  957.         m_iOffset = -8;
  958.     else if(m_iOffset > 8)
  959.         m_iOffset = 8;
  960.     
  961.     if(!bDontReload)*/
  962.  
  963.     m_iOffset += iIncrementor;
  964.     if(GetContext()){
  965.         GetContext()->fontScalingPercentage = LO_GetScalingFactor(m_iOffset);
  966.     }
  967.  
  968.     NiceReload();
  969. }
  970.  
  971.  
  972.  
  973. void CDCCX::ExtendCoord(LTRB& Rect)
  974. {
  975.     int32 lOrgX, lOrgY;
  976.  
  977.     GetDrawingOrigin(&lOrgX, &lOrgY);
  978.  
  979.     Rect.left += lOrgX;
  980.     Rect.top += lOrgY;
  981.     Rect.right += lOrgX;
  982.     Rect.bottom += lOrgY;
  983. }
  984.  
  985. BOOL CDCCX::ResolveElement(LTRB& Rect, int32 x, int32 y, int32 x_offset, int32 y_offset,
  986.                                 int32 width, int32 height)
  987. {
  988.     BOOL bRetval = TRUE;
  989.     //    First, figure the coordinates.
  990.     Rect.left = x + x_offset - m_lOrgX;
  991.     Rect.top = y + y_offset - m_lOrgY;
  992.     Rect.right = Rect.left + width;
  993.     Rect.bottom = Rect.top + height;
  994.  
  995.     ExtendCoord(Rect);
  996.  
  997.     //    Return FALSE if this doesn't fall into view of the context.
  998.     if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  999.         if(CanBlockDisplay())    {
  1000.             bRetval = FALSE;
  1001.         }
  1002.     }
  1003.     return bRetval;
  1004. }
  1005. BOOL CDCCX::ResolveElement(LTRB& Rect, LO_TextStruct *pText, int iLocation, int32 lStartPos, int32 lEndPos, int iClear)    {
  1006.     BOOL bRetval = TRUE;
  1007.  
  1008.     //    Subtext, in order to be considered at all, must first pass the text resolution.
  1009.     if(ResolveElement(Rect, pText->x, pText->y, pText->x_offset, 
  1010.                                 pText->y_offset,pText->width, pText->height))    {
  1011.         //    Adjust the coordinates further for the specific subtext we're going to be
  1012.         //        drawing.
  1013.         //    This means we actually have to size the text....
  1014.         HDC hdc = GetContextDC();
  1015.         
  1016.         CyaFont    *pMyFont;
  1017.         SelectNetscapeFontWithCache( hdc, pText->text_attr, pMyFont );
  1018.         CSize sz;
  1019.         ResolveTextExtent(hdc, (const char *)pText->text, CASTINT(lStartPos), &sz, pMyFont);
  1020.         Rect.left += sz.cx;
  1021.         ResolveTextExtent(hdc, (const char *)pText->text + lStartPos, CASTINT(lEndPos - lStartPos + 1), &sz, pMyFont);
  1022.         Rect.right = Rect.left + sz.cx;    
  1023.         
  1024.         Rect.bottom = Rect.top + sz.cy;   
  1025.  
  1026.         ReleaseNetscapeFontWithCache( hdc, pMyFont );
  1027.  
  1028.         ReleaseContextDC(hdc);
  1029.  
  1030.         //    Return FALSE if this doesn't fall into view of the context.
  1031.         if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  1032.             if(CanBlockDisplay())    {
  1033.                 bRetval = FALSE;
  1034.             }
  1035.         }
  1036.     }
  1037.     else if(CanBlockDisplay())    {
  1038.         //    Didn't pass even the normal text filter.
  1039.         bRetval = FALSE;
  1040.     }
  1041.  
  1042.     return(bRetval);
  1043. }
  1044.  
  1045. /* 
  1046.  * Note that this was brought back, since form element positions are 
  1047.  * expressed in document coordinates, not layer coordinates, so the
  1048.  * standard ResolveElement techniques will not work.
  1049.  */
  1050. BOOL CDCCX::ResolveElement(LTRB& Rect, LO_FormElementStruct *pFormElement)    {
  1051.     BOOL bRetval = TRUE;
  1052.  
  1053.     //    First, figure the coordinates.
  1054.     Rect.left = pFormElement->x + pFormElement->x_offset - m_lOrgX;
  1055.     Rect.top = pFormElement->y + pFormElement->y_offset - m_lOrgY;
  1056.     Rect.right = Rect.left + pFormElement->width;
  1057.     Rect.bottom = Rect.top + pFormElement->height;
  1058.  
  1059.     /* Don't call ExtendCoord() for forms.  Form element positions are in
  1060.        document coordinates, not layer coordinates. */
  1061.  
  1062.     //    Return FALSE if this doesn't fall into view of the context.
  1063.     if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  1064.         if(CanBlockDisplay())    {
  1065.             bRetval = FALSE;
  1066.         }
  1067.     }
  1068.  
  1069.     return(bRetval);
  1070. }
  1071.  
  1072. BOOL CDCCX::ResolveElement(LTRB& Rect, NI_Pixmap *pImage, int32 lX, int32 lY, 
  1073.                            int32 orgx, int32 orgy,
  1074.                            uint32 ulWidth, uint32 ulHeight)
  1075. {
  1076.     BOOL bRetval = TRUE;
  1077.  
  1078.     if(ulWidth == 0)    {
  1079.         ulWidth = pImage->header.width;
  1080.     }
  1081.  
  1082.     if(ulHeight == 0)    {
  1083.         ulHeight = pImage->header.height;
  1084.     }
  1085.     Rect.left = orgx + lX - m_lOrgX;
  1086.     Rect.top = orgy + lY - m_lOrgY;
  1087.     
  1088.     ExtendCoord(Rect);
  1089.  
  1090.     if (Rect.top < 0 && lX) Rect.top = 0;
  1091.     if (Rect.left < 0 && lY) Rect.left = 0;
  1092.  
  1093.     Rect.right = Rect.left + ulWidth;
  1094.     Rect.bottom = Rect.top + ulHeight;
  1095.  
  1096.     return(bRetval);
  1097. }
  1098.  
  1099. BOOL CDCCX::ResolveElement(LTRB& Rect, LO_TableStruct *pTable, int iLocation)    {
  1100.     BOOL bRetval = TRUE;
  1101.  
  1102.     //    First, figure the coordinates.
  1103.     Rect.left = pTable->x + pTable->x_offset - m_lOrgX;
  1104.     Rect.top = pTable->y + pTable->y_offset - m_lOrgY;
  1105.     Rect.right = Rect.left + pTable->width;
  1106.     Rect.bottom = Rect.top + pTable->height;
  1107.  
  1108.     //    Return FALSE if this doesn't fall into view of the context.
  1109.     if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  1110.         if(CanBlockDisplay())    {
  1111.             bRetval = FALSE;
  1112.         }
  1113.     }
  1114.  
  1115.     return(bRetval);
  1116. }
  1117.  
  1118. BOOL CDCCX::ResolveElement(LTRB& Rect, LO_SubDocStruct *pSubDoc, int iLocation)    {
  1119.     BOOL bRetval = TRUE;
  1120.  
  1121.     //    First, figure the coordinates.
  1122.     Rect.left = pSubDoc->x + pSubDoc->x_offset - m_lOrgX;
  1123.     Rect.top = pSubDoc->y + pSubDoc->y_offset - m_lOrgY;
  1124.     Rect.right = Rect.left + pSubDoc->width;
  1125.     Rect.bottom = Rect.top + pSubDoc->height;
  1126.  
  1127.     //    Return FALSE if this doesn't fall into view of the context.
  1128.     if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  1129.         if(CanBlockDisplay())    {
  1130.             bRetval = FALSE;
  1131.         }
  1132.     }
  1133.  
  1134.     return(bRetval);
  1135. }
  1136.  
  1137. BOOL CDCCX::ResolveElement(LTRB& Rect, LO_CellStruct *pCell, int iLocation)    {
  1138.     BOOL bRetval = TRUE;
  1139.  
  1140.     //    First, figure the coordinates.
  1141.     Rect.left = pCell->x + pCell->x_offset - m_lOrgX;
  1142.     Rect.top = pCell->y + pCell->y_offset - m_lOrgY;
  1143.     Rect.right = Rect.left + pCell->width;
  1144.     Rect.bottom = Rect.top + pCell->height;
  1145.  
  1146.     //    Return FALSE if this doesn't fall into view of the context.
  1147.     if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  1148.         if(CanBlockDisplay())    {
  1149.             bRetval = FALSE;
  1150.         }
  1151.     }
  1152.  
  1153.     return(bRetval);
  1154. }
  1155.  
  1156. BOOL CDCCX::ResolveElement(LTRB& Rect, LO_EmbedStruct *pEmbed, int iLocation, Bool bWindowed)    {
  1157.     BOOL bRetval = TRUE;
  1158.  
  1159.     //    First, figure the coordinates.
  1160.     Rect.left = -m_lOrgX;
  1161.     Rect.top = -m_lOrgY;
  1162.  
  1163.     // For windowed embeds, we only need the position of the embed,
  1164.     // and we ignore the layer origin. For windowless embeds, we only
  1165.     // need the layer origin, and not the position of the embed.
  1166.     if (bWindowed) {
  1167.         Rect.left += pEmbed->x + pEmbed->x_offset + pEmbed->border_width;
  1168.         Rect.top += pEmbed->y + pEmbed->y_offset + pEmbed->border_width;
  1169.     }
  1170.     
  1171.     Rect.right = Rect.left + pEmbed->width;
  1172.     Rect.bottom = Rect.top + pEmbed->height;
  1173.  
  1174.     if (!bWindowed)
  1175.         ExtendCoord(Rect);
  1176.  
  1177.     //    Return FALSE if this doesn't fall into view of the context.
  1178.     if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  1179.         if(CanBlockDisplay())    {
  1180.             bRetval = FALSE;
  1181.         }
  1182.     }
  1183.  
  1184.     return(bRetval);
  1185. }
  1186.  
  1187. BOOL CDCCX::ResolveElement(LTRB& Rect, LO_LinefeedStruct *pLineFeed, int iLocation)    {
  1188.     BOOL bRetval = TRUE;
  1189.  
  1190.     //    First, figure the coordinates.
  1191.     Rect.left = pLineFeed->x + pLineFeed->x_offset - m_lOrgX;
  1192.     Rect.top = pLineFeed->y + pLineFeed->y_offset - m_lOrgY;
  1193.     Rect.right = Rect.left + pLineFeed->width;
  1194.     Rect.bottom = Rect.top + pLineFeed->height;
  1195.  
  1196.     //    Return FALSE if this doesn't fall into view of the context.
  1197.     if(Rect.top > m_lHeight || Rect.bottom < 0 || Rect.right < 0 || Rect.left > m_lWidth) {
  1198.         if(CanBlockDisplay())    {
  1199.             bRetval = FALSE;
  1200.         }
  1201.     }
  1202.  
  1203.     return(bRetval);
  1204. }
  1205.  
  1206. inline BOOL CDCCX::ResolveLineSolid()    {
  1207.     //    Don't default to all solid lines.
  1208.     return(FALSE);
  1209. }
  1210.  
  1211. COLORREF CDCCX::ResolveTextColor(LO_TextAttr *pAttr)    {
  1212. //    Purpose:    Determine the Forground color of the attribute.
  1213. //    Arguments:    pAttr    The attributes from which we will obtain the color.
  1214. //    Returns:    COLORREF    The color.
  1215. //    Comments:    Override this if you need finer control over the selections
  1216. //                    of color such as printing.
  1217. //    Revision History:
  1218. //        06-09-95    created GAB
  1219.  
  1220.     //    Default implementation simply returns the color requested. Make sure that
  1221.     // we get the closest match in the palette and not one of the static system
  1222.     // colors. or'ing 0x02000000L in here is easier than finding every occurence
  1223.     // of SetTextColor downstream
  1224.     if(pAttr != NULL)    {
  1225.         return(0x02000000L | RGB(pAttr->fg.red, pAttr->fg.green, pAttr->fg.blue));
  1226.     }
  1227.     else    {
  1228.         return(RGB(0,0,0));
  1229.     }
  1230. }
  1231.  
  1232. //
  1233. // if we are not in true-color mode snap the color to the palette
  1234. //  otherwise they will get dithered to the windows 16-color palette
  1235. //  in the view's EraseBackground method
  1236. //
  1237. COLORREF CDCCX::ResolveBGColor(unsigned uRed, unsigned uGreen, unsigned uBlue)    
  1238. {
  1239.  
  1240.     int index = 0;
  1241.     if ((m_iBitsPerPixel <= 8) && m_pPal) {
  1242.  
  1243.         index = ::GetNearestPaletteIndex(m_pPal, RGB(uRed, uGreen, uBlue));
  1244.  
  1245.         PALETTEENTRY palEntry;
  1246.         ::GetPaletteEntries(m_pPal, index, 1, &palEntry);
  1247.         uRed   = palEntry.peRed;
  1248.         uGreen = palEntry.peGreen;
  1249.         uBlue  = palEntry.peBlue;
  1250.  
  1251.     }
  1252.  
  1253.     return(RGB(uRed, uGreen, uBlue));
  1254.  
  1255. }
  1256.  
  1257. BOOL CDCCX::ResolveHRSolid(LO_HorizRuleStruct *pHorizRule)    
  1258. {
  1259.     //    Determine if an HR is to be solid or 3D.
  1260.     //    Override this if you need to specifically control the display of
  1261.     //        HRs.
  1262.     if((pHorizRule->ele_attrmask & LO_ELE_SHADED) == LO_ELE_SHADED && pHorizRule->thickness > 1) {
  1263.         return(FALSE);
  1264.     }
  1265.     return(TRUE);
  1266. }
  1267.  
  1268. inline COLORREF CDCCX::ResolveDarkLineColor()    {
  1269.     //    By default, return the dark color.
  1270.     //    Override if you need to control HR colors.
  1271.     return(m_rgbDarkColor);
  1272. }
  1273.  
  1274. inline COLORREF CDCCX::ResolveLightLineColor()    {
  1275.     //    By default, return the light color.
  1276.     //    Override if you need to control HR colors.
  1277.     return(m_rgbLightColor);
  1278. }
  1279.  
  1280. COLORREF CDCCX::ResolveBorderColor(LO_TextAttr *pAttr)    {
  1281.     //    Default is to simply return the color requested.
  1282.     //    Override if you need to control border display.
  1283.     if(pAttr != NULL)    {
  1284.         return(RGB(pAttr->fg.red, pAttr->fg.green, pAttr->fg.blue));
  1285.     }
  1286.     else    {
  1287.         return(RGB(0,0,0));
  1288.     }
  1289. }
  1290.  
  1291. COLORREF CDCCX::ResolveLOColor(LO_Color *color)    {
  1292.     //    Default is to simply return the color requested.
  1293.     //    Override if you need to control border display.
  1294.     if(color != NULL)    {
  1295.         return(RGB(color->red, color->green, color->blue));
  1296.     }
  1297.     else    {
  1298.         return(RGB(0,0,0));
  1299.     }
  1300. }
  1301.  
  1302. void CDCCX::ResolveTransparentColor(unsigned uRed, unsigned uGreen, unsigned uBlue)    {
  1303.     //    Sets the transparency color of images.
  1304.     //    This in most cases is the same as the background color.
  1305.     //    Override this if you take special interest in controlling the background color.
  1306.  
  1307.     int iIndex = 0;
  1308.     IL_IRGB *rgbTransparent = GetContext()->transparent_pixel;
  1309.  
  1310.     if ((m_iBitsPerPixel <= 8) && m_pPal) {
  1311.         iIndex = ::GetNearestPaletteIndex(m_pPal, m_rgbBackgroundColor);
  1312.         curColorSpace->cmap.index[MAX_IMAGE_PALETTE_ENTRIES] = iIndex;
  1313.     }
  1314.  
  1315.     //    Simply let the image lib know what's up.
  1316.     if (!rgbTransparent) {
  1317.         rgbTransparent = XP_NEW_ZAP(IL_IRGB);
  1318.         GetContext()->transparent_pixel = rgbTransparent;
  1319.     }
  1320.  
  1321.     rgbTransparent->index = MAX_IMAGE_PALETTE_ENTRIES;
  1322.     rgbTransparent->red = uRed;
  1323.     rgbTransparent->green = uGreen;
  1324.     rgbTransparent->blue = uBlue;    
  1325. }
  1326.  
  1327. // rgbLight is used to render the top/left edges, and rgbDark is used to
  1328. // render the bottom/right edges
  1329. void CDCCX::Display3DBox(LTRB& Rect, COLORREF rgbLight, COLORREF rgbDark, int32 lWidth, BOOL bAdjust)    {
  1330.     HDC hDC = GetContextDC();
  1331.  
  1332.     //    Adjust the y value by half the height.  We'll need to move it back
  1333.     //        to the original position, since we have a reference to the rect.
  1334.     int32 lAdjust = 0;
  1335.     if(bAdjust == TRUE)    {
  1336.         //    This should only happen with HRs!
  1337.         lAdjust = Rect.Height() / 2;
  1338.         if(MMIsText() == FALSE)    {
  1339.             Rect.top -= lAdjust;
  1340.             Rect.bottom -= lAdjust;
  1341.         }
  1342.     }
  1343.     else    {
  1344.         //    When bAdjust is false, this means we are dealing with a table/cell/subdoc.
  1345.         //    To properly draw these, we need to shrink the rect on the right and bottom
  1346.         //        by the width.
  1347.         lAdjust = lWidth;
  1348.         Rect.right -= lAdjust;
  1349.         Rect.bottom -= lAdjust;
  1350.     }
  1351.  
  1352.     // If there's a thick border then miter the join where the different
  1353.     // colors meet
  1354.     if(lWidth > Pix2TwipsX(1) && ResolveLineSolid() == FALSE)    {
  1355.         HPEN    hOldPen = (HPEN)::SelectObject(hDC, GetStockObject(NULL_PEN));
  1356.         POINT   aPoints[6];
  1357.         HBRUSH  hbDark, hbLight, hOldBrush;
  1358.         
  1359.         // Make sure that in 256 color mode we get a PALETTE RGB color
  1360.         hbDark = ::CreateSolidBrush(0x02000000L | rgbDark);
  1361.         hbLight = ::CreateSolidBrush(0x02000000L | rgbLight);
  1362.  
  1363.         //    Map all the points.
  1364.         //    Left and top.
  1365.         aPoints[0].x = CASTINT(Rect.left + lWidth);
  1366.         aPoints[0].y = CASTINT(Rect.top + lWidth);
  1367.         aPoints[1].x = CASTINT(Rect.left + lWidth);
  1368.         aPoints[1].y = CASTINT(Rect.bottom);
  1369.         aPoints[2].x = CASTINT(Rect.left);
  1370.         aPoints[2].y = CASTINT(Rect.bottom + lWidth);
  1371.         aPoints[3].x = CASTINT(Rect.left);
  1372.         aPoints[3].y = CASTINT(Rect.top);
  1373.         aPoints[4].x = CASTINT(Rect.right + lWidth);
  1374.         aPoints[4].y = CASTINT(Rect.top);
  1375.         aPoints[5].x = CASTINT(Rect.right);
  1376.         aPoints[5].y = CASTINT(Rect.top + lWidth);
  1377.         
  1378.         hOldBrush = (HBRUSH)::SelectObject(hDC, hbLight);
  1379.         ::Polygon(hDC, aPoints, 6);
  1380.  
  1381.         //    Right and bottom.
  1382.         aPoints[0].x = CASTINT(Rect.right);
  1383.         aPoints[0].y = CASTINT(Rect.bottom);
  1384.         aPoints[3].x = CASTINT(Rect.right + lWidth);
  1385.         aPoints[3].y = CASTINT(Rect.bottom + lWidth);
  1386.         
  1387.         ::SelectObject(hDC, hbDark);
  1388.         ::Polygon(hDC, aPoints, 6);
  1389.  
  1390.         ::SelectObject(hDC, hOldPen);
  1391.         ::SelectObject(hDC, hOldBrush);
  1392.         VERIFY(::DeleteObject(hbDark));
  1393.         VERIFY(::DeleteObject(hbLight));
  1394.     }
  1395.     else    {
  1396.         HBRUSH  hbLight, hbDark, hOldBrush;
  1397.  
  1398.         // Left/top edges
  1399.         hbLight = ::CreateSolidBrush(0x02000000L | rgbLight);
  1400.         hOldBrush = (HBRUSH)::SelectObject(hDC, hbLight);
  1401.         
  1402.         ::PatBlt(hDC, CASTINT(Rect.left), CASTINT(Rect.top),
  1403.             CASTINT(Rect.right - Rect.left), lWidth, PATCOPY);
  1404.         ::PatBlt(hDC, CASTINT(Rect.left), CASTINT(Rect.top),
  1405.             lWidth, CASTINT(Rect.bottom - Rect.top), PATCOPY);
  1406.         
  1407.         ::SelectObject(hDC, hOldBrush);
  1408.         VERIFY(::DeleteObject(hbLight));
  1409.  
  1410.         // Bottom/right edges
  1411.         hbDark = ::CreateSolidBrush(0x02000000L | rgbDark);
  1412.         hOldBrush = (HBRUSH)::SelectObject(hDC, hbDark);
  1413.  
  1414.         ::PatBlt(hDC, CASTINT(Rect.left), CASTINT(Rect.bottom),
  1415.             CASTINT(Rect.right - Rect.left), lWidth, PATCOPY);
  1416.         ::PatBlt(hDC, CASTINT(Rect.right), CASTINT(Rect.top),
  1417.             lWidth, CASTINT(Rect.bottom - Rect.top) + 1, PATCOPY);
  1418.         
  1419.         ::SelectObject(hDC, hOldBrush);
  1420.         VERIFY(::DeleteObject(hbDark));
  1421.     }
  1422.     //    Reposition.
  1423.     if(bAdjust == TRUE)    {
  1424.         //    HRs
  1425.         if(MMIsText() == FALSE)    {
  1426.             Rect.top += lAdjust;
  1427.             Rect.bottom += lAdjust;
  1428.         }
  1429.     }
  1430.     else    {
  1431.         //    Table/cell/subdoc
  1432.         Rect.right += lAdjust;
  1433.         Rect.bottom += lAdjust;
  1434.     }
  1435.  
  1436.     ReleaseContextDC(hDC);
  1437. }
  1438.  
  1439. static HPEN
  1440. CreateStyledPen(COLORREF color, int nWidth, int nPenStyle)
  1441. {
  1442. #ifdef _WIN32
  1443.     LOGBRUSH    lb;
  1444.     DWORD       dwPenStyle;
  1445. #endif
  1446.  
  1447. #ifdef _WIN32
  1448.     lb.lbStyle = 0;  // ignored
  1449.     lb.lbColor = 0x02000000L | color;
  1450.     lb.lbStyle = 0;  // ignored
  1451.  
  1452.     dwPenStyle = PS_GEOMETRIC | PS_ENDCAP_SQUARE | PS_JOIN_MITER;
  1453.  
  1454.     return ::ExtCreatePen(dwPenStyle | nPenStyle, nWidth, &lb, 0, NULL);
  1455. #else
  1456.     return ::CreatePen(nPenStyle, nWidth, 0x02000000L | color);
  1457. #endif
  1458. }
  1459.  
  1460. static void
  1461. DisplaySpecialBorder(HDC hDC, RECT &r, COLORREF color, int iWidth, BOOL bSolid)
  1462. {
  1463.     HPEN    hPen = ::CreatePen(PS_DOT, 1, 0x02000000L | color);
  1464.     HPEN    hOldPen = (HPEN)::SelectObject(hDC, hPen);
  1465.     HBRUSH    hOldBrush = (HBRUSH) ::SelectObject(hDC, ::GetStockObject(NULL_BRUSH));
  1466.  
  1467.     ::SetBkMode(hDC, TRANSPARENT);
  1468.     for( int i = 0; i < iWidth; i++ )
  1469.     {
  1470.         ::Rectangle(hDC, r.left, r.top, r.right, r.bottom);
  1471.         ::InflateRect(&r, -1, -1);
  1472.     }
  1473.     
  1474.     ::SelectObject(hDC, hOldPen);
  1475.     ::SelectObject(hDC, hOldBrush);
  1476.     VERIFY(::DeleteObject(hPen));
  1477. }
  1478.  
  1479. static void
  1480. DisplaySolidBorder(HDC hDC, RECT &r, COLORREF color, LTRB &widths)
  1481. {
  1482.     // See if all border edges are the same width
  1483.     if (widths.left == widths.top && widths.left == widths.right && widths.left == widths.bottom) {
  1484.         HPEN    hPen = ::CreatePen(PS_INSIDEFRAME, widths.left, 0x02000000L | color);
  1485.         HPEN    hOldPen = (HPEN)::SelectObject(hDC, hPen);
  1486.         HBRUSH    hOldBrush = (HBRUSH) ::SelectObject(hDC, ::GetStockObject(NULL_BRUSH));
  1487.  
  1488.         // Draw it using a single rectangle call
  1489.         ::Rectangle(hDC, r.left, r.top, r.right, r.bottom);
  1490.         ::SelectObject(hDC, hOldPen);
  1491.         ::SelectObject(hDC, hOldBrush);
  1492.         VERIFY(::DeleteObject(hPen));
  1493.  
  1494.     } else {
  1495.         HBRUSH  hBrush = ::CreateSolidBrush(0x02000000L | color);
  1496.         HBRUSH  hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush);
  1497.  
  1498.         // Draw each of the individual edges using PatBlt
  1499.         if (widths.left > 0)
  1500.             ::PatBlt(hDC, r.left, r.top, widths.left, r.bottom - r.top, PATCOPY);
  1501.  
  1502.         if (widths.top > 0)
  1503.             ::PatBlt(hDC, r.left, r.top, r.right - r.left, widths.top, PATCOPY);
  1504.  
  1505.         if (widths.right > 0)
  1506.             ::PatBlt(hDC, r.right - widths.right, r.top, widths.right, r.bottom - r.top, PATCOPY);
  1507.  
  1508.         if (widths.bottom > 0)
  1509.             ::PatBlt(hDC, r.left, r.bottom - widths.bottom, r.right - r.left, widths.bottom, PATCOPY);
  1510.         
  1511.         ::SelectObject(hDC, hOldBrush);
  1512.         VERIFY(::DeleteObject(hBrush));
  1513.     }
  1514. }
  1515.  
  1516. static void
  1517. DisplayDoubleBorder(HDC hDC, RECT &r, COLORREF color, LTRB &widths)
  1518. {
  1519.     LTRB    strokeWidths;
  1520.  
  1521.     // Compute the stroke width for each of the edges
  1522.     strokeWidths.left = (widths.left + 1) / 3;
  1523.     strokeWidths.top = (widths.top + 1) / 3;
  1524.     strokeWidths.right = (widths.right + 1) / 3;
  1525.     strokeWidths.bottom = (widths.bottom + 1) / 3;
  1526.  
  1527.     // Draw the outer lines
  1528.     DisplaySolidBorder(hDC, r, color, strokeWidths);
  1529.  
  1530.     // Adjust the rectangle to be the inner rectangle
  1531.     r.left += CASTINT(widths.left - strokeWidths.left);
  1532.     r.top += CASTINT(widths.top - strokeWidths.top);
  1533.     r.right -= CASTINT(widths.right - strokeWidths.right);
  1534.     r.bottom -= CASTINT(widths.bottom - strokeWidths.bottom);
  1535.  
  1536.     // Draw the inner lines
  1537.     DisplaySolidBorder(hDC, r, color, strokeWidths);
  1538. }
  1539.  
  1540. // rgbLight is used to render the top/left edges, and rgbDark is used to
  1541. // render the bottom/right edges
  1542. void
  1543. CDCCX::Display3DBorder(LTRB& Rect, COLORREF rgbLight, COLORREF rgbDark, LTRB &widths)
  1544. {
  1545.     if (widths.left == widths.top && widths.left == widths.right && widths.left == widths.bottom) {
  1546.         // This routine is faster especially for one-pixel thick lines    
  1547.         Display3DBox(Rect, rgbLight, rgbDark, widths.left, FALSE);
  1548.  
  1549.     } else {
  1550.         HDC    hDC = GetContextDC();
  1551.  
  1552.         HPEN    hOldPen = (HPEN)::SelectObject(hDC, GetStockObject(NULL_PEN));
  1553.         POINT   aPoints[6];
  1554.         HBRUSH  hbDark, hbLight, hOldBrush;
  1555.         
  1556.         // Make sure that in 256 color mode we get a PALETTE RGB color
  1557.         hbDark = ::CreateSolidBrush(0x02000000L | rgbDark);
  1558.         hbLight = ::CreateSolidBrush(0x02000000L | rgbLight);
  1559.  
  1560.         // Map all the points. Draw it inside of the rect. Draw the left
  1561.         // and top edges first
  1562.         aPoints[0].x = CASTINT(Rect.left + widths.left);
  1563.         aPoints[0].y = CASTINT(Rect.top + widths.top);
  1564.         aPoints[1].x = CASTINT(Rect.left + widths.left);
  1565.         aPoints[1].y = CASTINT(Rect.bottom - widths.bottom);
  1566.         aPoints[2].x = CASTINT(Rect.left);
  1567.         aPoints[2].y = CASTINT(Rect.bottom);
  1568.         aPoints[3].x = CASTINT(Rect.left);
  1569.         aPoints[3].y = CASTINT(Rect.top);
  1570.         aPoints[4].x = CASTINT(Rect.right);
  1571.         aPoints[4].y = CASTINT(Rect.top);
  1572.         aPoints[5].x = CASTINT(Rect.right - widths.right);
  1573.         aPoints[5].y = CASTINT(Rect.top + widths.top);
  1574.         
  1575.         hOldBrush = (HBRUSH)::SelectObject(hDC, hbLight);
  1576.         ::Polygon(hDC, aPoints, 6);
  1577.  
  1578.         //    Right and bottom.
  1579.         aPoints[0].x = CASTINT(Rect.right - widths.right);
  1580.         aPoints[0].y = CASTINT(Rect.bottom - widths.bottom);
  1581.         aPoints[3].x = CASTINT(Rect.right);
  1582.         aPoints[3].y = CASTINT(Rect.bottom);
  1583.         
  1584.         ::SelectObject(hDC, hbDark);
  1585.         ::Polygon(hDC, aPoints, 6);
  1586.  
  1587.         ::SelectObject(hDC, hOldPen);
  1588.         ::SelectObject(hDC, hOldBrush);
  1589.         VERIFY(::DeleteObject(hbDark));
  1590.         VERIFY(::DeleteObject(hbLight));
  1591.         
  1592.         ReleaseContextDC(hDC);
  1593.     }
  1594. }
  1595.  
  1596. // Adjust border for selection feedback of table or cell
  1597. // Returns width used in excess of table border (into space between cells)
  1598. //  because that will have to be restored to background when removing selection
  1599. int32 SetSelectionBorder(int32 *pWidth, int32 iCellSpacing)
  1600. {
  1601.     int32 iOldWidth = *pWidth;
  1602.     int32 iExcess = 0;
  1603.     // Allow wider selection if border is very large
  1604.     int32 iMaxWidth = 2*ED_SELECTION_BORDER;
  1605.     // 
  1606.     *pWidth = min(*pWidth,iMaxWidth);
  1607.     // Also use spacing between cells if less than maximum
  1608.     if( *pWidth < 6 )
  1609.     {
  1610.         iExcess = min(iCellSpacing, 6-*pWidth);
  1611.         *pWidth += iExcess;
  1612.     }
  1613.     return iExcess;
  1614. }
  1615.  
  1616. int32
  1617. CDCCX::DisplayTableBorder(LTRB& Rect, LO_TableStruct *pTable)
  1618. {
  1619.     COLORREF        rgbBorder = ResolveLOColor(&pTable->border_color);
  1620.     COLORREF        rgbLight, rgbDark;
  1621.     HDC             hDC;
  1622.     int             nStrokeWidth;
  1623.     RECT            r = {CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)};
  1624.     LTRB            insetRect;
  1625.     LTRB    borderWidths(pTable->border_left_width, pTable->border_top_width,
  1626.                                     pTable->border_right_width, pTable->border_bottom_width);
  1627.     //TRACE0("DisplayTableBorder\n");
  1628.  
  1629.     // Only the Editor sets table elements as selected, so we don't need EDT_IS_EDITOR
  1630.     if( pTable->ele_attrmask & LO_ELE_SELECTED )
  1631.     {
  1632.         // Use the selection background color to draw a solid border
  1633.         COLORREF rgbBorder;
  1634.         wfe_GetSelectionColors(m_rgbBackgroundColor, NULL, &rgbBorder);
  1635.         hDC = GetContextDC();
  1636.         // Use same border thickness for all sides - use the minimum Table border thickness
  1637.         //  and the space between cells if available
  1638.         int32 iBorderWidth = min(borderWidths.bottom,min(borderWidths.top,min(borderWidths.left, borderWidths.right)));
  1639.         SetSelectionBorder(&iBorderWidth, pTable->inter_cell_space);
  1640.         borderWidths.left = borderWidths.right = borderWidths.top = borderWidths.bottom = iBorderWidth;
  1641.  
  1642.         // Show a solid border up to twice default selection border as the selection feedback
  1643.         DisplaySolidBorder(hDC, r, rgbBorder, borderWidths);
  1644.         ReleaseContextDC(hDC);
  1645.         // Return actual border width used
  1646.         return iBorderWidth;
  1647.     }
  1648.     else
  1649.     {
  1650.  
  1651.     if (pTable->border_style == BORDER_GROOVE || pTable->border_style == BORDER_RIDGE ||
  1652.         pTable->border_style == BORDER_INSET || pTable->border_style == BORDER_OUTSET) {
  1653.  
  1654.         // Compute the 3D colors to use. If the border color is the same as the background
  1655.         // color then just use the light/dark colors we've already computed
  1656.         if (rgbBorder == m_rgbBackgroundColor) {
  1657.             rgbLight = m_rgbLightColor;
  1658.             rgbDark = m_rgbDarkColor;
  1659.         
  1660.         } else {
  1661.             Compute3DColors(rgbBorder, rgbLight, rgbDark);
  1662.         }
  1663.     }
  1664.  
  1665.     hDC = GetContextDC();
  1666.     switch (pTable->border_style) {
  1667.         case BORDER_NONE:
  1668.             break;
  1669.  
  1670.         case BORDER_DOTTED:
  1671.         case BORDER_DASHED:
  1672.         case BORDER_SOLID:
  1673. //            hDC = GetContextDC();
  1674.             DisplaySolidBorder(hDC, r, rgbBorder, borderWidths);
  1675. //            ReleaseContextDC(hDC);
  1676.             break;
  1677.  
  1678.         case BORDER_DOUBLE:
  1679. //            hDC = GetContextDC();
  1680.             DisplayDoubleBorder(hDC, r, rgbBorder, borderWidths);
  1681. //            ReleaseContextDC(hDC);
  1682.             break;
  1683.  
  1684.         case BORDER_GROOVE:
  1685.             // This is done as a sunken outer border with a raised inner
  1686.             // border. Windows group boxes have this appearance
  1687.             borderWidths.left /= 2;
  1688.             borderWidths.top /= 2;
  1689.             borderWidths.right /= 2;
  1690.             borderWidths.bottom /= 2;
  1691.             Display3DBorder(Rect, rgbDark, rgbLight, borderWidths);
  1692.             insetRect.left = Rect.left + borderWidths.left;
  1693.             insetRect.top = Rect.top + borderWidths.top;
  1694.             insetRect.right = Rect.right - borderWidths.right;
  1695.             insetRect.bottom = Rect.bottom - borderWidths.bottom;
  1696.             Display3DBorder(insetRect, rgbLight, rgbDark, borderWidths);
  1697.             break;
  1698.  
  1699.         case BORDER_RIDGE:
  1700.             // This is done as a raised outer border with a sunken inner border
  1701.             borderWidths.left /= 2;
  1702.             borderWidths.top /= 2;
  1703.             borderWidths.right /= 2;
  1704.             borderWidths.bottom /= 2;
  1705.             Display3DBorder(Rect, rgbLight, rgbDark, borderWidths);
  1706.             insetRect.left = Rect.left + borderWidths.left;
  1707.             insetRect.top = Rect.top + borderWidths.top;
  1708.             insetRect.right = Rect.right - borderWidths.right;
  1709.             insetRect.bottom = Rect.bottom - borderWidths.bottom;
  1710.             Display3DBorder(insetRect, rgbDark, rgbLight, borderWidths);
  1711.             break;
  1712.  
  1713.         case BORDER_INSET:
  1714.             // This is what Windows refers to as a sunken border
  1715.             Display3DBorder(Rect, rgbDark, rgbLight, borderWidths);
  1716.             break;
  1717.  
  1718.         case BORDER_OUTSET:
  1719.             // This is what Windows refers to as a raised border
  1720.             Display3DBorder(Rect, rgbLight, rgbDark, borderWidths);
  1721.             break;
  1722.  
  1723.         default:
  1724.             ASSERT(FALSE);
  1725.             break;
  1726.     }
  1727.     }
  1728.     return 0;
  1729. }
  1730.  
  1731. void CDCCX::EditorDisplayZeroWidthBorder(LTRB& Rect, BOOL bSelected){
  1732.     // Show a 1-pixel dotted border. Used in the editor
  1733.     // Use the same color we would use for a selection background,
  1734.     //   but use the opposite color if we will be selecting,
  1735.     //   so NOT opperation yields a contrasting color relative to background
  1736.     COLORREF rgbColor;
  1737.     wfe_GetSelectionColors(m_rgbBackgroundColor, NULL, &rgbColor);
  1738.  
  1739.     HDC hdc = GetContextDC();
  1740.     // Use dotted line if not selected, or solid if selecting
  1741.     HPEN pPen = ::CreatePen(bSelected ? PS_SOLID : PS_DOT, 1, rgbColor);
  1742.     HPEN pOldPen = (HPEN)::SelectObject(hdc, pPen);
  1743.     ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top), NULL);
  1744.     ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.top));
  1745.     ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.bottom));
  1746.     ::LineTo(hdc, CASTINT(Rect.left), CASTINT(Rect.bottom));
  1747.     ::LineTo(hdc, CASTINT(Rect.left), CASTINT(Rect.top));
  1748.     ::SelectObject(hdc, pOldPen);
  1749.     ReleaseContextDC(hdc);
  1750.     VERIFY(::DeleteObject(pPen));
  1751. }
  1752.  
  1753. void CDCCX::DrawRectBorder(LTRB& Rect, COLORREF rgbColor, int32 lWidth)    {
  1754.     //    This should only be called for display of the border for images, and embeds.
  1755.     HDC hdc = GetContextDC();
  1756.  
  1757.     // The border goes outside of the rectangle, so we need to adjust the
  1758.     // rectangle accordingly
  1759.     int32 lAdjust = lWidth / 2;
  1760.     int32 rAdjust = lAdjust;
  1761.     if(lWidth % 2)    {
  1762.         lAdjust += Pix2TwipsX(1);
  1763.     }
  1764.     rAdjust += Pix2TwipsX(1);
  1765.  
  1766.     LTRB rect(Rect.left - lAdjust, Rect.top - lAdjust,
  1767.         Rect.right + rAdjust, Rect.bottom + rAdjust);
  1768.     SafeSixteen(rect);
  1769.  
  1770.     HPEN hBorder = ::CreatePen(PS_SOLID, CASTINT(lWidth), rgbColor);
  1771.     HPEN hOldPen = (HPEN)::SelectObject(hdc, hBorder);
  1772.     HBRUSH hOldBrush = (HBRUSH) ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH));
  1773.  
  1774.     //    Draw it.
  1775.     ::Rectangle(hdc, CASTINT(rect.left), CASTINT(rect.top),
  1776.         CASTINT(rect.right), CASTINT(rect.bottom));
  1777.  
  1778.     ::SelectObject(hdc, hOldBrush);
  1779.     ::SelectObject(hdc, hOldPen);
  1780.     VERIFY(::DeleteObject(hBorder));
  1781.     ReleaseContextDC(hdc);
  1782.  
  1783. }
  1784.  
  1785. void CDCCX::DisplaySelectionFeedback(uint16 ele_attrmask, const LTRB& rect)
  1786. {
  1787.     BOOL bSelect =  ele_attrmask & LO_ELE_SELECTED;
  1788.     // Don't do anything if unselecting any other objects
  1789.     //  since these will be completely redrawn.
  1790.     if ( !bSelect || !EDT_IS_EDITOR(GetContext()) ) {
  1791.         return;
  1792.     }
  1793.     LTRB Rect(rect.left, rect.top,
  1794.         rect.right, rect.bottom);
  1795.  
  1796.     SafeSixteen(Rect);
  1797.     // Draw selection feedback. It has to fit entirely within rect, because
  1798.     // when it's turned off, all that will happen is that it won't be drawn.
  1799.     HDC hdc = GetContextDC();
  1800.  
  1801.     int32 rWidth = Rect.right - Rect.left;
  1802.     int32 rHeight = Rect.bottom - Rect.top;
  1803.     if ( rWidth <= (ED_SELECTION_BORDER*2) || rHeight <= (ED_SELECTION_BORDER*2) ) {
  1804.         // Too narrow to draw frame. Draw solid.
  1805.         RECT r;
  1806.         ::SetRect(&r, CASTINT(Rect.left), CASTINT(Rect.top),
  1807.             CASTINT(Rect.right), CASTINT(Rect.bottom));
  1808.         ::InvertRect(hdc, &r);
  1809.     }
  1810.     else {
  1811.         //    Frame.
  1812.         LTRB inner(Rect.left + ED_SELECTION_BORDER, Rect.top + ED_SELECTION_BORDER,
  1813.             Rect.right - ED_SELECTION_BORDER, Rect.bottom - ED_SELECTION_BORDER);
  1814.         SafeSixteen(inner);
  1815.  
  1816.         RECT SelRect;
  1817.         ::SetRect(&SelRect, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(inner.top));
  1818.           ::InvertRect(hdc, &SelRect);
  1819.         ::SetRect(&SelRect, CASTINT(Rect.left), CASTINT(inner.top), CASTINT(inner.left), CASTINT(inner.bottom));
  1820.           ::InvertRect(hdc, &SelRect);
  1821.         ::SetRect(&SelRect, CASTINT(inner.right), CASTINT(inner.top), CASTINT(Rect.right), CASTINT(inner.bottom));
  1822.           ::InvertRect(hdc, &SelRect);
  1823.         ::SetRect(&SelRect, CASTINT(Rect.left), CASTINT(inner.bottom), CASTINT(Rect.right), CASTINT(Rect.bottom));
  1824.           ::InvertRect(hdc, &SelRect);
  1825.     }
  1826.  
  1827.     ReleaseContextDC(hdc);
  1828. }
  1829.  
  1830. void CDCCX::EraseToBackground(const LTRB& rect, int32 borderWidth)
  1831. {
  1832.     if(!EDT_IS_EDITOR(GetContext())){
  1833.         return;
  1834.     }
  1835.     LTRB Rect(rect.left - borderWidth, rect.top - borderWidth,
  1836.                 rect.right + borderWidth, rect.bottom + borderWidth);
  1837.  
  1838.     // The editor draws selection feedback. Touch all the pixels so that
  1839.     // any pre-existing selection feedback is erased.
  1840.     HDC hdc = GetContextDC();
  1841.     
  1842.     RECT     destRect;
  1843.     ::SetRect(&destRect, CASTINT(Twips2PixX(Rect.left)), CASTINT(Twips2PixY(Rect.top)),
  1844.         CASTINT(Twips2PixX(Rect.right)), CASTINT(Twips2PixX(Rect.bottom)));
  1845.  
  1846.     // Is this really true? (Troy thinks conversion is only needed for 
  1847.     //  memory DC)
  1848.     // Coordinates to _EraseBkgnd() must be in device units
  1849.     // NOTE: _EraseBkgnd() call will use m_pImageDC, that's why we
  1850.     // aren't using it
  1851.     _EraseBkgnd(hdc,destRect,
  1852.             Twips2PixX(GetOriginX() ),
  1853.             Twips2PixY(GetOriginY() ),
  1854.             NULL);
  1855.     ReleaseContextDC(hdc);
  1856. }
  1857.  
  1858.  
  1859. #ifdef LAYERS
  1860. // Erase the background at the given rect. x, y, width and height are
  1861. // in document coordinates.
  1862. void CDCCX::EraseBackground(MWContext *pContext, int iLocation, 
  1863.                 int32 x, int32 y, uint32 width, uint32 height,
  1864.                 LO_Color *pColor)
  1865. {
  1866.     HDC hdc = GetContextDC();
  1867.     int32 orgX = GetOriginX();
  1868.     int32 orgY = GetOriginY();
  1869.     int32 lDrawingOrgX, lDrawingOrgY;
  1870.     RECT   eraseRect;
  1871.     int32 x0, y0;
  1872.  
  1873.     x0 = (x > orgX) ? x - orgX : orgX - x;
  1874.     y0 = (y > orgY) ? y - orgY : orgY - y;
  1875.     ::SetRect(&eraseRect, CASTINT(x0), CASTINT(y0), 
  1876.                         CASTINT(x0+width), CASTINT(y0+height));
  1877.     GetDrawingOrigin(&lDrawingOrgX, &lDrawingOrgY);
  1878.     _EraseBkgnd(hdc, eraseRect, orgX-lDrawingOrgX, orgY-lDrawingOrgY, 
  1879.                 pColor);
  1880.  
  1881.     ReleaseContextDC(hdc);
  1882. }
  1883. #endif /* LAYERS */
  1884.  
  1885. static BOOL
  1886. CanCreateBrush(HBITMAP hBitmap)
  1887. {
  1888.     BITMAP    bitmap;
  1889.  
  1890.     // We can create a brush if the bitmap is exacly 8x8
  1891.     ::GetObject(hBitmap, sizeof(bitmap), &bitmap);
  1892.     return bitmap.bmWidth == 8 && bitmap.bmHeight == 8;
  1893. }
  1894.  
  1895.  
  1896. // orgX, orgY, and crRect are interpreted in the logical coordinates
  1897. // of pDC
  1898. //
  1899. // Note: The caller is responsible for having selected the logical palette
  1900. // before calling this routine. If not, the call to CreateSolidBrush() will
  1901. // get mapped to the nearest system color (probably not the desired behavior)
  1902. BOOL CDCCX::_EraseBkgnd(HDC pDC, RECT& crRect, int32 orgX, int32 orgY, 
  1903.                         LO_Color* bg)
  1904. {
  1905.     // The order of priority is as follows:
  1906.     //   1. passed in image
  1907.     //   2. passed in color
  1908.     //   3. document backdrop image
  1909.     //   4. document solid color
  1910.     COLORREF    bgColor = bg ? RGB(bg->red, bg->green, bg->blue) : m_rgbBackgroundColor;
  1911.     
  1912.     HBRUSH hBrush = NULL;
  1913.     if (m_iBitsPerPixel == 16)
  1914.         // We don't want a dithered brush
  1915.         hBrush = ::CreateSolidBrush(::GetNearestColor(pDC,bgColor));
  1916.     else
  1917.         hBrush = ::CreateSolidBrush(0x02000000L | bgColor);
  1918.  
  1919.     ::FillRect(pDC, &crRect, hBrush);
  1920.  
  1921. #ifdef DDRAW
  1922.     if (GetPrimarySurface()) {
  1923.         ::FillRect(GetDispDC(), &crRect, hBrush);
  1924.     }
  1925. #if 0 //DEBUG_mhwang
  1926.     TRACE("CDCCX::_EraseBkgnd, %d,%d,%d,%d(ltrb)\n", crRect.left, crRect.top,
  1927.                                 crRect.right, crRect.bottom);
  1928. #endif
  1929. #endif
  1930.     VERIFY(::DeleteObject(hBrush));
  1931.     return TRUE;
  1932. }
  1933.  
  1934.  
  1935.  
  1936.  
  1937.  
  1938. struct iconMap{
  1939.     int iIconNum;
  1940.     int x;
  1941.     int y;
  1942.     unsigned int bitmapID;
  1943.     unsigned int maskID;
  1944. }
  1945.  
  1946. #define SMIME_ICON_CX    50
  1947. #define SMIME_ICON_CY    30
  1948. #define SECADV_ICON_CX    51
  1949. #define SECADV_ICON_CY    30
  1950.  
  1951. #define ICONMAPSIZE 31
  1952.  
  1953. static iconMap[ICONMAPSIZE] = {
  1954.     IL_IMAGE_DELAYED, IMAGE_SMICON_WIDTH, IMAGE_SMICON_HEIGHT,IDB_SMIMAGE_DELAYED, IDB_SMIMAGE_MASK,
  1955.     IL_IMAGE_NOT_FOUND, IMAGE_ICON_SIZE, IMAGE_ICON_SIZE, IDB_IMAGE_NOTFOUND,IDB_IMAGE_MASK,
  1956.     IL_IMAGE_BAD_DATA, IMAGE_ICON_SIZE, IMAGE_ICON_SIZE, IDB_IMAGE_BAD, IDB_IMAGE_BAD_MASK,
  1957.     IL_IMAGE_INSECURE, IMAGE_ICON_SIZE, IMAGE_ICON_SIZE, IDB_IMAGE_SEC_REPLACE,IDB_IMAGE_MASK,
  1958.     IL_GOPHER_FOLDER,GOPHER_ICON_SIZE, GOPHER_ICON_SIZE + 1, IDB_GOPHER_FOLDER,IDB_GOPHER_FOLDER_MASK,
  1959.     IL_GOPHER_IMAGE, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE + 1, IDB_GOPHER_IMAGE,IDB_GOPHER_AUDIO_MASK,
  1960.     IL_GOPHER_TEXT, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_TEXT, IDB_GOPHER_AUDIO_MASK,
  1961.     IL_GOPHER_BINARY, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_BINARY, IDB_GOPHER_AUDIO_MASK,
  1962.     IL_GOPHER_SOUND,  GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_AUDIO, IDB_GOPHER_AUDIO_MASK,
  1963.     IL_GOPHER_MOVIE, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_FIND, IDB_GOPHER_FIND_MASK,
  1964.     IL_GOPHER_TELNET, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_TELNET,IDB_GOPHER_TELNET_MASK,
  1965.     IL_GOPHER_UNKNOWN, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_GOPHER_GENERIC, IDB_GOPHER_AUDIO_MASK,
  1966.     IL_EDIT_NAMED_ANCHOR, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_NAMED_ANCHOR,     IDB_EDIT_NAMED_ANCHOR_MASK,
  1967.     IL_EDIT_FORM_ELEMENT, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_FORM_ELEMENT,IDB_EDIT_FORM_ELEMENT_MASK,
  1968.     IL_EDIT_UNSUPPORTED_TAG, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_UNSUPPORTED_TAG, IDB_EDIT_UNSUPPORTED_TAG_MASK,
  1969.     IL_EDIT_UNSUPPORTED_END_TAG, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_UNSUPPORTED_END_TAG, IDB_EDIT_UNSUPPORTED_END_TAG_MASK,
  1970.     IL_EDIT_JAVA, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_JAVA, IDB_EDIT_JAVA_MASK,
  1971.     IL_EDIT_PLUGIN, GOPHER_ICON_SIZE, GOPHER_ICON_SIZE+1, IDB_EDIT_PLUGIN,IDB_EDIT_PLUGIN_MASK,
  1972.  
  1973.     IL_SA_SIGNED, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SASIGNED, IDB_SASIGNED_MASK,
  1974.     IL_SA_ENCRYPTED, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SAENCRYPTED, IDB_SAENCRYPTED_MASK,
  1975.     IL_SA_NONENCRYPTED, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SAUNENCRYPTED, IDB_SAUNENCRYPTED_MASK,
  1976.     IL_SA_SIGNED_BAD, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SASIGNED, IDB_SASIGNED_MASK,
  1977.     IL_SA_ENCRYPTED_BAD, SECADV_ICON_CX, SECADV_ICON_CY, IDB_SASIGNEDBAD, IDB_SASIGNEDBAD_MASK,
  1978.     IL_SMIME_ATTACHED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGATTACHED, IDB_MSGSTAMPMASK,
  1979.     IL_SMIME_SIGNED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNED, IDB_MSGSTAMPMASK,
  1980.     IL_SMIME_ENCRYPTED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGENCRYPTED, IDB_MSGSTAMPMASK,
  1981.     IL_SMIME_ENC_SIGNED, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNEDENCRYPTED, IDB_MSGSTAMPMASK,
  1982.     IL_SMIME_SIGNED_BAD, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNEDBAD, IDB_MSGSTAMPMASK,
  1983.     IL_SMIME_ENCRYPTED_BAD, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGENCRYPTEDBAD, IDB_MSGSTAMPMASK,
  1984.     IL_SMIME_ENC_SIGNED_BAD, SMIME_ICON_CX, SMIME_ICON_CY, IDB_MSGSIGNEDENCRYPTEDBAD, IDB_MSGSTAMPMASK,
  1985.  
  1986.     IL_MSG_ATTACH, 24, 29, IDB_MSGATTACHBUTTON, IDB_MSGATTACHBUTTONMASK
  1987. };
  1988.  
  1989.  
  1990.  
  1991. void CDCCX::GetIconDimensions(int32* width, int32* height, int iconNumber)
  1992. {
  1993.     unsigned int bitmapID;    // resource ID of bitmap to load
  1994.     unsigned int maskID = 0;  // resource ID of mask (if any)
  1995.  
  1996.     if (iconNumber < 0)
  1997.         return;
  1998.  
  1999.     int x, y;
  2000.  
  2001.     for (int i = 0; i < ICONMAPSIZE ; i++) {
  2002.         if (iconMap[i].iIconNum == iconNumber) {
  2003.             x = iconMap[i].x;
  2004.             y = iconMap[i].y;
  2005.             bitmapID = iconMap[i].bitmapID;
  2006.             maskID = iconMap[i].maskID;
  2007.             break;
  2008.         }
  2009.     }
  2010.  
  2011.     if (i == ICONMAPSIZE) { // used default icon here.
  2012.         x = GOPHER_ICON_SIZE;
  2013.         y = GOPHER_ICON_SIZE + 1;
  2014.         bitmapID = IDB_FILE;
  2015.         maskID = IDB_GOPHER_AUDIO_MASK;
  2016.     }
  2017.  
  2018.  
  2019.     *width = CASTINT(x);
  2020.     *height = CASTINT(y);
  2021. }
  2022.  
  2023. #ifndef XP_WIN32
  2024. /* Quaternary raster codes */
  2025. #define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore))
  2026. #endif
  2027.  
  2028. static BOOL
  2029. AlterBackgroundColor(HDC pSrcDC, int width, int height, HBITMAP hMask, HBRUSH hBrush)
  2030. {
  2031.     HDC    memDC;
  2032.  
  2033.     // Create a memory DC for holding the mask
  2034.     if (!(memDC = ::CreateCompatibleDC(NULL))) {
  2035.         TRACE("AlterBackgroundColor() can't create compatible memory DC!\n");
  2036.         return FALSE;
  2037.     }
  2038.  
  2039.     // Select the mask into the memory DC
  2040.     HBITMAP    hOldMaskBitmap = (HBITMAP)::SelectObject(memDC, hMask);
  2041.  
  2042.     // Change the transparent bits of the source bitmap to the desired background
  2043.     // color by doing an AND raster op
  2044.     //
  2045.     // The mask is monochrome and will be converted to color to match the depth of
  2046.     // the destination. The foreground pixels in the mask are set to 1, and the
  2047.     // background pixels to 0. When converting to a color bitmap, white pixels (1)
  2048.     // are set to the background color of the DC, and black pixels (0) are set to
  2049.     // the text color of the DC
  2050.     //
  2051.     // Select the brush
  2052.     HBRUSH    hOldBrush = (HBRUSH)::SelectObject(pSrcDC, hBrush);
  2053.  
  2054.     // Draw the brush where the mask is 0
  2055.     ::BitBlt(pSrcDC,
  2056.                    0,
  2057.                    0,
  2058.                    width,
  2059.                    height,
  2060.                    memDC,
  2061.                    0,
  2062.                    0,
  2063. //                   ROP_PSDPxax);
  2064.                    MAKEROP4(SRCPAINT, R2_COPYPEN));
  2065.  
  2066.     // Restore the DCs
  2067.     ::SelectObject(memDC, hOldMaskBitmap);
  2068.     ::SelectObject(pSrcDC, hOldBrush);
  2069.  
  2070.     return TRUE;
  2071. }
  2072.  
  2073. /////////////////////////////////////////////////////////////////////////////
  2074. // equivalent to LoadBitmap(), except uses pDC for
  2075. // correct color mapping of BMP into pDC's palette.
  2076. BOOL CDCCX::cxLoadBitmap(LPCSTR pszBmName, char** bits,  BITMAPINFOHEADER** myBitmapInfo) 
  2077. {
  2078.  
  2079.     // get the resource from the file
  2080.     HBITMAP hBmp = (HBITMAP)FindResource(AfxGetInstanceHandle( ), pszBmName, RT_BITMAP);
  2081.     ASSERT(hBmp != NULL);
  2082.     if(!hBmp)
  2083.         return FALSE;
  2084.     HGLOBAL hRes = LoadResource(AfxGetInstanceHandle( ), (HRSRC)hBmp);
  2085.     ASSERT(hRes != NULL);
  2086.     if(!hRes)
  2087.         return FALSE;
  2088.     LPBITMAPINFO pPackedDib = (LPBITMAPINFO)(LockResource(hRes));
  2089.     ASSERT(pPackedDib != NULL);
  2090.     if(!pPackedDib)
  2091.         return FALSE;
  2092.         
  2093.     // build a DDB header for  pDC
  2094.     
  2095.     // create the DDB
  2096.     int iColorTableSize =
  2097.         (1 << pPackedDib->bmiHeader.biBitCount) * sizeof(RGBQUAD);
  2098.     LPBITMAPINFOHEADER bitmapInfo;
  2099.     bitmapInfo = (LPBITMAPINFOHEADER)calloc(sizeof(BITMAPINFOHEADER) + iColorTableSize, 1);;
  2100.     memcpy(bitmapInfo, pPackedDib, sizeof(BITMAPINFOHEADER) + iColorTableSize);
  2101.     bitmapInfo->biBitCount = m_iBitsPerPixel;
  2102.     bitmapInfo->biClrUsed = 0;
  2103.     bitmapInfo->biClrImportant = 0;
  2104.     *myBitmapInfo = bitmapInfo;
  2105.     void* pBits =
  2106.         ((char*)pPackedDib) + pPackedDib->bmiHeader.biSize + iColorTableSize;
  2107.     int widthBytes = (((bitmapInfo->biWidth * bitmapInfo->biBitCount) + 31) && ~31) >> 3;
  2108.     *bits =(char*) CDCCX::HugeAlloc(widthBytes * bitmapInfo->biHeight, 1);
  2109.     memcpy(bits, pBits, widthBytes * bitmapInfo->biHeight);
  2110.     // done, clean up
  2111.     UnlockResource(hRes);
  2112.     BOOL bResult = FreeResource(hRes);
  2113.     
  2114.     return TRUE;
  2115. }
  2116.  
  2117. void CDCCX::DisplayIcon(int32 x0, int32 y0, int icon_number)
  2118. {
  2119.     unsigned int bitmapID;    // resource ID of bitmap to load
  2120.     unsigned int maskID = 0;  // resource ID of mask (if any)
  2121.  
  2122.     if (icon_number < 0)
  2123.         return;
  2124.  
  2125.     int x, y;
  2126.     LTRB Rect;
  2127.  
  2128.     for (int i = 0; i < ICONMAPSIZE ; i++) {
  2129.         if (iconMap[i].iIconNum == icon_number) {
  2130.             x = iconMap[i].x;
  2131.             y = iconMap[i].y;
  2132.             bitmapID = iconMap[i].bitmapID;
  2133.             maskID = iconMap[i].maskID;
  2134.             break;
  2135.         }
  2136.     }
  2137.  
  2138.     if (i == ICONMAPSIZE) { // used default icon here.
  2139.         x = GOPHER_ICON_SIZE;
  2140.         y = GOPHER_ICON_SIZE + 1;
  2141.         bitmapID = IDB_FILE;
  2142.         maskID = IDB_GOPHER_AUDIO_MASK;
  2143.     }
  2144.  
  2145.     int width = CASTINT(Pix2TwipsX(x));
  2146.     int height = CASTINT(Pix2TwipsY(y));
  2147.  
  2148.     if (ResolveElement(Rect, x0, y0, 0, 0, width, height)) {
  2149.         SafeSixteen(Rect);
  2150.         
  2151.         HBITMAP hBitmap = NULL;
  2152.         HDC hdc = GetContextDC();    
  2153.  
  2154. #ifdef XP_WIN32
  2155.         if (icon_number == IL_IMAGE_DELAYED) {
  2156.             static HICON    hIcon=NULL;
  2157.  
  2158.             // The icon is represented as a small icon resource which is 16x16 pixels
  2159.             if(!hIcon)
  2160.                 hIcon = (HICON)::LoadImage(AfxGetResourceHandle(),
  2161.                     MAKEINTRESOURCE(IDI_IMAGE_DELAYED), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  2162.  
  2163.             VERIFY(::DrawIconEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top),
  2164.                 hIcon, Pix2TwipsX(16), Pix2TwipsY(16), 0, NULL, DI_NORMAL));
  2165.  
  2166.             /* don't destroy hIcon because it's static */
  2167.  
  2168. //            return;
  2169.         }
  2170.         else
  2171. #endif
  2172.         {
  2173.             // load the bitmap out of the resource file
  2174.             HBITMAP mask;
  2175.             if (!IsPrintContext()) {
  2176.                 hBitmap = LOADBITMAP(bitmapID);
  2177.                 if(maskID) 
  2178.                     mask = LOADBITMAP(maskID);
  2179.                 HBITMAP hOldBitmap = NULL;                                       
  2180.  
  2181.                 if(maskID) {
  2182.  
  2183.                     // load the mask out of the resource file
  2184.                         StretchMaskBlt(hdc, hBitmap, mask, 
  2185.                                     Rect.left, Rect.top, width, height,
  2186.                                     0, 0, x, y);
  2187.                      VERIFY(::DeleteObject(mask));
  2188.                 } 
  2189.                 else {
  2190.                     // load the bitmap into the cached image CDC                                                   
  2191.                     hOldBitmap = (HBITMAP) ::SelectObject(m_pImageDC, hBitmap);
  2192.  
  2193.                     ::StretchBlt(hdc,
  2194.                                 CASTINT(Rect.left), 
  2195.                                 CASTINT(Rect.top),
  2196.                                 CASTINT(width), 
  2197.                                 CASTINT(height), 
  2198.                                 m_pImageDC,
  2199.                                 CASTINT(0), 
  2200.                                 CASTINT(0), 
  2201.                                 CASTINT(x),
  2202.                                 CASTINT(y), 
  2203.                                 SRCCOPY);
  2204.                     ::SelectObject(m_pImageDC, hOldBitmap);
  2205.                 }
  2206.  
  2207.                 // restore the old bitmap
  2208.                 VERIFY(::DeleteObject(hBitmap));
  2209.             }
  2210.             else {    // printing icon
  2211.                 char** image_bits;
  2212.                 BITMAPINFOHEADER* imageInfo;
  2213.                 char** mask_bits;
  2214.                 BITMAPINFOHEADER* maskInfo;
  2215.                 if (cxLoadBitmap(MAKEINTRESOURCE(bitmapID), image_bits, &imageInfo)) {
  2216.                     if(maskID) {
  2217.                         BOOL fillBack = TRUE;
  2218. #ifdef XP_WIN32
  2219.                         CPrintCX* pPrintCx = (CPrintCX*)this;
  2220.                         fillBack = pPrintCx->IsPrintingBackground() ? FALSE : TRUE;
  2221. #endif
  2222.                         cxLoadBitmap(MAKEINTRESOURCE(maskID), mask_bits, &maskInfo);
  2223.                         WFE_StretchDIBitsWithMask(hdc,TRUE, m_pImageDC,
  2224.                                             CASTINT(Rect.left), 
  2225.                                             CASTINT(Rect.top),
  2226.                                             CASTINT(width), 
  2227.                                             CASTINT(height), 
  2228.                                             CASTINT(0), 
  2229.                                             CASTINT(0), 
  2230.                                             CASTINT(x),
  2231.                                             CASTINT(y), 
  2232.                                             image_bits,
  2233.                                             (BITMAPINFO*)imageInfo,
  2234.                                             mask_bits,
  2235.                                             m_bUseDibPalColors,
  2236.                                             fillBack);
  2237.                     }
  2238.                     else {
  2239.                         ::StretchDIBits(hdc,
  2240.                                             CASTINT(Rect.left), 
  2241.                                             CASTINT(Rect.top),
  2242.                                             CASTINT(width), 
  2243.                                             CASTINT(height), 
  2244.                                             CASTINT(0), 
  2245.                                             CASTINT(0), 
  2246.                                             CASTINT(x),
  2247.                                             CASTINT(y), 
  2248.                                             image_bits,
  2249.                                             (BITMAPINFO*)imageInfo,
  2250.                                             DIB_RGB_COLORS,
  2251.                                             SRCCOPY);
  2252.                     }
  2253.                 }
  2254.  
  2255.                 if (image_bits)
  2256.                     delete *image_bits;
  2257.                 if (imageInfo)
  2258.                     delete imageInfo;
  2259.                 if(maskID) {
  2260.                     if (mask_bits)
  2261.                         delete *mask_bits;
  2262.                     if (maskInfo)
  2263.                         delete maskInfo;
  2264.                 }
  2265.             }
  2266.         }
  2267.         ReleaseContextDC(hdc);
  2268.     }
  2269. }
  2270.     
  2271. int CDCCX::GetUrl(URL_Struct *pUrl, FO_Present_Types iFormatOut, BOOL bReallyLoading, BOOL bForceNew)    {
  2272.     //    Save the location of the current document, if not at the very top.
  2273.     //  Reset to top, then see if we need to change more....
  2274.     SHIST_SetPositionOfCurrentDoc(&(GetContext()->hist), 0);
  2275.     if(GetOriginX() || GetOriginY())    {
  2276. #ifdef LAYERS
  2277.         LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(GetDocumentContext(), GetOriginX(), GetOriginY(), NULL);
  2278. #else
  2279.         LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(GetDocumentContext(), GetOriginX(), GetOriginY());
  2280. #endif  /* LAYERS */
  2281.         if(pAny != NULL)    {
  2282.             TRACE("Remembering document position at element id %ld\n", pAny->ele_id);
  2283.             SHIST_SetPositionOfCurrentDoc(&(GetContext()->hist), pAny->ele_id);
  2284.         }
  2285.     }
  2286.  
  2287.     //    Handle forced image loading.
  2288.     m_csForceLoadImage = m_csNexttimeForceLoadImage;
  2289.     m_csNexttimeForceLoadImage.Empty();
  2290.     m_bLoadImagesNow = m_bNexttimeLoadImagesNow;
  2291.     m_bNexttimeLoadImagesNow = FALSE;
  2292.  
  2293.     //    Call the base.
  2294.     return(CStubsCX::GetUrl(pUrl, iFormatOut, bReallyLoading, bForceNew));
  2295. }
  2296.  
  2297. //    rewrite the BULLET_BASIC and BULLET_DISC part
  2298. //    the origional "o" approach cause a lot of problem in non-LATIN page
  2299. void CDCCX::DisplayBullet(MWContext *pContext, int iLocation, LO_BullettStruct *pBullet)    {
  2300.     //    Figure the coordinates.
  2301.     LTRB Rect;
  2302.     int        reduce;
  2303. //    if(ResolveElement(Rect, pBullet, iLocation) == TRUE)    {
  2304.     if (ResolveElement(Rect, pBullet->x, pBullet->y, 
  2305.                 pBullet->x_offset, pBullet->y_offset,
  2306.                 pBullet->width, pBullet->height) == TRUE) {
  2307.         SafeSixteen(Rect);
  2308.  
  2309.         COLORREF rgbBullet = ResolveTextColor(pBullet->text_attr);
  2310.         HDC hdc = GetContextDC();
  2311.  
  2312.         int w;
  2313.         if( pBullet->bullet_type == BULLET_MQUOTE 
  2314.             || pBullet->bullet_type == BULLET_SQUARE ) {
  2315.             w = 1;
  2316.         } else {
  2317.             w = CASTINT( (Rect.bottom - Rect.top) / 10);
  2318.             if(w < 1)
  2319.                 w = 1;
  2320.         }
  2321.  
  2322.         HPEN hpen = ::CreatePen(PS_SOLID,w,rgbBullet);
  2323.         HPEN oldPen = (HPEN)::SelectObject(hdc,hpen);      
  2324.  
  2325.         // draw_bullet_with_Ellipse
  2326.         HBRUSH hBrush = ::CreateSolidBrush(rgbBullet);
  2327.         HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush);
  2328.  
  2329.         switch(pBullet->bullet_type)    {
  2330.         
  2331.         case BULLET_MQUOTE:
  2332.             // BUG#61210 draw quote as one pixel bar on the left
  2333. #if defined (WIN32)
  2334.             ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top), NULL);
  2335. #else
  2336.             ::MoveTo(hdc, CASTINT(Rect.left), CASTINT(Rect.top));
  2337. #endif
  2338.             ::LineTo(hdc,CASTINT(Rect.left), CASTINT(Rect.bottom));
  2339.             break;
  2340.         case BULLET_SQUARE:    
  2341.             // Size of square is too large relative to solid and open circle,
  2342.             //  so reduce a little
  2343.             Rect.top++;
  2344.             Rect.bottom--;
  2345.             Rect.left++;
  2346.             Rect.right--;
  2347.             ::Rectangle(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  2348.             break;
  2349.  
  2350.         case BULLET_NONE:
  2351.             // Do nothing
  2352.             break;
  2353.  
  2354.         case BULLET_BASIC:        // solid bullet
  2355.         case BULLET_ROUND :        // todo ::RoundRect()?
  2356.         default :                // Circle
  2357.             if( BULLET_BASIC != pBullet->bullet_type )  {   // Circle
  2358.                 // don't touch hOldBrush, put hOldBrush back after draw.
  2359.                 ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH));
  2360.             }
  2361.             reduce = (Rect.bottom - Rect.top ) / 4;
  2362.             ::Ellipse(hdc, CASTINT(Rect.left+reduce), CASTINT(Rect.top+reduce),
  2363.                            CASTINT(Rect.right-reduce), CASTINT(Rect.bottom-reduce));
  2364.             break;
  2365.         }
  2366.         ::SelectObject(hdc, hOldBrush);
  2367.         VERIFY(::DeleteObject( hBrush ));
  2368.  
  2369.         ::SelectObject(hdc,oldPen);      
  2370.        ::DeleteObject(hpen);
  2371.         // end of draw_bullet_with_Ellipse
  2372.  
  2373.         ReleaseContextDC(hdc);
  2374.     }
  2375. }
  2376.  
  2377. #ifdef Frank_code
  2378. void CDCCX::DisplayBullet(MWContext *pContext, int iLocation, LO_BullettStruct *pBullet)    {
  2379.     //    Figure the coordinates.
  2380.     LTRB Rect;
  2381. //    if(ResolveElement(Rect, pBullet, iLocation) == TRUE)    {
  2382.     if (ResolveElement(Rect, pBullet->x, pBullet->y, 
  2383.                 pBullet->x_offset, pBullet->y_offset,
  2384.                 pBullet->width, pBullet->height) == TRUE) {
  2385.         SafeSixteen(Rect);
  2386.  
  2387.         COLORREF rgbBullet = ResolveTextColor(pBullet->text_attr);
  2388.         HDC hdc = GetContextDC();
  2389.  
  2390.  
  2391.         Rect.top++;
  2392.         Rect.bottom--;
  2393.         Rect.left++;
  2394.         Rect.right--;
  2395.  
  2396.         switch(pBullet->bullet_type)    {
  2397.         
  2398.         case BULLET_MQUOTE:
  2399.         case BULLET_SQUARE:    {
  2400.             HBRUSH hBrush = ::CreateSolidBrush(rgbBullet);
  2401.             HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush);
  2402.  
  2403.             ::Rectangle(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  2404.             ::SelectObject(hdc, hOldBrush);
  2405.             VERIFY(::DeleteObject( hBrush ));
  2406.             break;
  2407.         }
  2408.  
  2409.         case BULLET_BASIC:    {
  2410.             HBRUSH hBrush = ::CreateSolidBrush(rgbBullet);
  2411.             HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush);
  2412.  
  2413.             ::Ellipse(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  2414.             ::SelectObject(hdc, hOldBrush);
  2415.             VERIFY(::DeleteObject( hBrush ));
  2416.             break;
  2417.  
  2418.         }
  2419.  
  2420.         default:    {
  2421.             int w = CASTINT( (Rect.bottom - Rect.top) / 10);
  2422.             if(w < 1)
  2423.                 w = 1;
  2424.             HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
  2425.             HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush);
  2426.             HPEN hStrike = ::CreatePen(PS_SOLID, CASTINT( w ), rgbBullet);
  2427.             HPEN hOldStrike = (HPEN)::SelectObject(hdc, hStrike);
  2428.  
  2429.             ::Ellipse(hdc, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  2430.             ::SelectObject(hdc, hOldBrush);
  2431.             // Don't delete hBrush since it is a stock object
  2432.  
  2433.             ::SelectObject(hdc, hOldStrike);
  2434.             VERIFY(::DeleteObject( hStrike ));
  2435.             break;
  2436.  
  2437.             }
  2438.         }
  2439.  
  2440.         ReleaseContextDC(hdc);
  2441.     }
  2442. }
  2443. #endif
  2444.  
  2445. // Display a border of the specified size and color.  x, y, width and height
  2446. // refer to the outside perimeter of the border.
  2447. void CDCCX::DisplayBorder(MWContext *pContext, int iLocation, int x, int y, int width, int height, int bw, LO_Color *color, LO_LineStyle style)
  2448. {
  2449.     LTRB Rect;
  2450.     
  2451.     if (bw) {
  2452.         // Adjust the input parameters so that they describe the inside
  2453.         // perimeter of the border.  Don't do this for 3D borders since
  2454.         // Draw3DBox does this for us.
  2455.         if (style != LO_BEVEL) {
  2456.             x += bw;
  2457.             y += bw;
  2458.             width -= 2 * bw;
  2459.             height -= 2 * bw;
  2460.         }
  2461.  
  2462.         if (ResolveElement(Rect, x, y, 0, 0, width, height)) {
  2463.             SafeSixteen(Rect);
  2464.  
  2465.             // Call the method which really draws the border.
  2466.             switch(style) {
  2467.             case LO_SOLID:
  2468.                 DrawRectBorder(Rect, ResolveLOColor(color), bw);
  2469.                 break;
  2470.  
  2471.             case LO_BEVEL:
  2472.                 Display3DBox(Rect, ResolveDarkLineColor(),
  2473.                              ResolveLightLineColor(), Pix2TwipsX(bw), FALSE);
  2474.                 break;
  2475.  
  2476.             default:
  2477.                 break;
  2478.             }
  2479.         }
  2480.     }
  2481. }
  2482.  
  2483. void CDCCX::DisplayImageFeedback(MWContext *pContext, int iLocation, LO_Element *pElement, lo_MapAreaRec * theArea, uint32 drawFlag )
  2484. {
  2485.     if (pElement->lo_any.type == LO_IMAGE) {
  2486.         LO_ImageStruct *pImage = (LO_ImageStruct *)pElement;
  2487.         LTRB Rect;
  2488.         int borderWidth = CASTINT(pImage->border_width);
  2489.         int x = CASTINT(pImage->x + pImage->x_offset + borderWidth);
  2490.         int y = CASTINT(pImage->y + pImage->y_offset + borderWidth);
  2491.  
  2492.         if (ResolveElement(Rect, x, y, 0, 0, pImage->width, pImage->height)) {
  2493.             SafeSixteen(Rect);
  2494.  
  2495.             DisplaySelectionFeedback(pImage->ele_attrmask, Rect);
  2496.  
  2497. //#ifndef NO_TAB_NAVIGATION
  2498.             if((FE_DRAW_TAB_FOCUS & drawFlag) &&
  2499.                pImage->suppress_mode != LO_SUPPRESS) {
  2500.             
  2501.                 // use the Rect from code above.
  2502.                 if( theArea != NULL) {
  2503.                     //  It is a focused area in map, draw a focus border.
  2504.                     DrawMapAreaBorder( CASTINT(Rect.left), CASTINT(Rect.top), theArea );
  2505.                 } else {
  2506.                     // draw a focus border for the whole image
  2507.                     lo_MapAreaRec    area;
  2508.                     int32            coord[4];
  2509.                     area.coords        = coord;
  2510.                     area.type = AREA_SHAPE_RECT ;
  2511.                     area.coord_cnt = 4;
  2512.                     area.coords[0] = Rect.left;
  2513.                     area.coords[1] = Rect.top;
  2514.                     area.coords[2] = Rect.right;
  2515.                     area.coords[3] = Rect.bottom;
  2516.                     DrawMapAreaBorder( 0, 0, &area );
  2517.                 }        
  2518.             }
  2519. //#endif    /* NO_TAB_NAVIGATION */
  2520.         }
  2521.     }
  2522. }
  2523.  
  2524.  
  2525. BOOL CDCCX::IsPluginFullPage(LO_EmbedStruct *pLayoutData)
  2526. {
  2527.     // 1x1 size is signal that plugin is full page, not embedded
  2528.     if((pLayoutData->width == Pix2TwipsX(1))
  2529.         && (pLayoutData->height == Pix2TwipsX(1)))
  2530.         return TRUE;
  2531.     return FALSE;
  2532. }
  2533.  
  2534. // returns TRUE if there is a plugin on the page and that plugin
  2535. // is of pluginType == NPWFE_FULL_PAGE.  There can be only one
  2536. // plugin on a page that contains a NPWFE_FULL_PAGE plugin.
  2537. BOOL CDCCX::ContainsFullPagePlugin()
  2538. {
  2539.     NPEmbeddedApp* pEmbeddedApp = GetContext()->pluginList;
  2540.     if(pEmbeddedApp) {
  2541.         if(pEmbeddedApp->pagePluginType == NP_FullPage)
  2542.             return TRUE;
  2543.     }
  2544.     return FALSE;
  2545. }
  2546.  
  2547. //  Determine location of plugin rect, convert from TWIPS to PIXELS
  2548. void CDCCX::GetPluginRect(MWContext *pContext,
  2549.                           LO_EmbedStruct *pLayoutData,
  2550.                           RECT &rect, int iLocation,
  2551.                           BOOL windowed)
  2552. {
  2553.     if(IsPluginFullPage(pLayoutData))
  2554.     {
  2555.          ::GetClientRect(PANECX(pContext)->GetPane(), &rect);
  2556.     }
  2557.     else // plugin embedded in page
  2558.     {
  2559.         // get the display area and clamp it
  2560.         LTRB Rect;
  2561.         ResolveElement(Rect, pLayoutData, iLocation, windowed);
  2562.  
  2563.         SafeSixteen(Rect);
  2564.         rect.left   = (int)Rect.left;
  2565.         rect.top    = (int)Rect.top;
  2566.         rect.right  = (int)Rect.right;
  2567.         rect.bottom = (int)Rect.bottom;
  2568.     }
  2569. }
  2570.  
  2571. void CDCCX::DisplayWindowlessPlugin(MWContext *pContext, 
  2572.                                     LO_EmbedStruct *pEmbed,
  2573.                                     NPEmbeddedApp *pEmbeddedApp,
  2574.                                     int iLocation)
  2575. {
  2576.     RECT         rect;
  2577.     NPWindow*     pAppWin = pEmbeddedApp->wdata;
  2578.     HDC         hDC = GetContextDC();
  2579.     NPEvent event;
  2580.     FE_Region clip;
  2581.     
  2582.     // Get the coordinates of where it should be positioned
  2583.     GetPluginRect(pContext, pEmbed, rect, iLocation, FALSE);
  2584.     
  2585.     if ((pAppWin->window    != (void *)hDC) ||
  2586.         (pAppWin->x            != (uint32) rect.left) ||
  2587.         (pAppWin->y            != (uint32) rect.top) ||
  2588.         (pAppWin->width        != (uint32) (rect.right - rect.left)) ||
  2589.         (pAppWin->height    != (uint32) (rect.bottom - rect.top))) 
  2590.     {
  2591.         pAppWin->window = (void *)hDC;
  2592.         pAppWin->x = rect.left;
  2593.         pAppWin->y = rect.top;
  2594.         pAppWin->width = rect.right - rect.left;
  2595.         pAppWin->height = rect.bottom - rect.top;
  2596.         pAppWin->type = NPWindowTypeDrawable;
  2597.         
  2598.         NPL_EmbedSize(pEmbeddedApp);
  2599.     }
  2600.     
  2601. #ifdef LAYERS
  2602.     clip = GetDrawingClip();
  2603.     if (clip) 
  2604.     {
  2605.         XP_Rect xprect;
  2606.         
  2607.         FE_GetRegionBoundingBox(clip, &xprect);
  2608.         rect.left = CASTINT(xprect.left);
  2609.         rect.top = CASTINT(xprect.top);
  2610.         rect.right = CASTINT(xprect.right);
  2611.         rect.bottom = CASTINT(xprect.bottom);
  2612.     }
  2613. #endif /* LAYERS */        
  2614.     
  2615.     event.event = WM_PAINT;
  2616.     event.wParam = (uint32)hDC;
  2617.     event.lParam = (uint32)▭
  2618.     
  2619.     NPL_HandleEvent(pEmbeddedApp, (void *)&event, pAppWin->window);
  2620.  
  2621.     ReleaseContextDC(hDC);
  2622. }
  2623.  
  2624.  
  2625. // create a window and pass its offset/size to the plugin
  2626. void CDCCX::DisplayPlugin(MWContext *pContext, LO_EmbedStruct *pEmbed,
  2627.                           NPEmbeddedApp* pEmbeddedApp, int iLocation)
  2628. {
  2629.     RECT         rect;
  2630.     NPWindow*     pAppWin = pEmbeddedApp->wdata;
  2631.  
  2632.        if(pAppWin->window == NULL)
  2633.         return;
  2634.  
  2635.     if (::IsWindowVisible((HWND)pAppWin->window) && 
  2636.         (pEmbed->ele_attrmask & LO_ELE_INVISIBLE))
  2637.         ::ShowWindow((HWND)pAppWin->window, SW_HIDE);
  2638.  
  2639.     // If the plugin is embedded we need to make sure the window is
  2640.     // positioned properly
  2641.     if (!IsPluginFullPage(pEmbed)) {
  2642.         RECT    curRect;
  2643.             
  2644.         // Get the coordinates of where it should be positioned
  2645.         GetPluginRect(pContext, pEmbed, rect, iLocation, TRUE);
  2646.  
  2647.         // Get the current coordinates relative to the parent window's
  2648.         // client area
  2649.         ::GetWindowRect((HWND)pAppWin->window, &curRect);
  2650.         MapWindowPoints(NULL, ::GetParent((HWND)pAppWin->window),
  2651.                         (POINT FAR *)&curRect, 2);
  2652.                 
  2653.         // Only move/size the window if necessary
  2654.         if ((rect.left != curRect.left) ||
  2655.             (rect.right != curRect.right) ||
  2656.             (rect.top != curRect.top) ||
  2657.             (rect.bottom != curRect.bottom)){
  2658.             ::SetWindowPos((HWND)pAppWin->window, NULL, rect.left, rect.top,
  2659.                            rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE);
  2660.                     
  2661.         }
  2662.          
  2663.         // Update the NPWindow rect
  2664.         pAppWin->x = rect.left;
  2665.         pAppWin->y = rect.top;
  2666.         pAppWin->width = rect.right - rect.left;
  2667.         pAppWin->height = rect.bottom - rect.top;
  2668.     }
  2669.         
  2670.     if (!::IsWindowVisible((HWND)pAppWin->window) &&
  2671.         !(pEmbed->ele_attrmask & LO_ELE_INVISIBLE))
  2672.         ::ShowWindow((HWND)pAppWin->window, SW_SHOW);
  2673.        
  2674. }
  2675.  
  2676. void CDCCX::DisplayEmbed(MWContext *pContext, int iLocation, LO_EmbedStruct *pEmbed)
  2677. {
  2678.     NPEmbeddedApp* pEmbeddedApp = (NPEmbeddedApp*)pEmbed->FE_Data;
  2679.  
  2680.     if(pEmbeddedApp == NULL)
  2681.         return;
  2682.  
  2683.     if(wfe_IsTypePlugin(pEmbeddedApp)) {
  2684.         if (NPL_IsEmbedWindowed(pEmbeddedApp)) {
  2685.             DisplayPlugin(pContext, pEmbed, pEmbeddedApp, iLocation);
  2686.             (void)NPL_EmbedSize(pEmbeddedApp);
  2687.         }
  2688.         else
  2689.             DisplayWindowlessPlugin(pContext, pEmbed, pEmbeddedApp, iLocation);
  2690.  
  2691.         if(IsPluginFullPage(pEmbed))
  2692.             pEmbeddedApp->pagePluginType = NP_FullPage;
  2693.         else
  2694.             pEmbeddedApp->pagePluginType = NP_Embedded;
  2695.         return;
  2696.     }
  2697.  
  2698.     // else must be an OLE display
  2699.     LTRB Rect;
  2700.     if(ResolveElement(Rect, pEmbed, iLocation, FALSE) == TRUE)    {
  2701.         int32 lOrgX, lOrgY;
  2702.         
  2703.         GetDrawingOrigin(&lOrgX, &lOrgY);
  2704.         SafeSixteen(Rect);
  2705.  
  2706.         //    Draw a border around the embed if needed.
  2707.         if(pEmbed->border_width != 0)    {
  2708.             DrawRectBorder(Rect, ResolveBorderColor(NULL), pEmbed->border_width);
  2709.         }
  2710.  
  2711.         //    Get the embedded item
  2712.         CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  2713.         if(pItem == NULL)    {
  2714.             DisplayIcon(Rect.left, Rect.top, IL_IMAGE_BAD_DATA);
  2715.             return;
  2716.         }
  2717.  
  2718.         //    Handle delayed, broken, and currently loading items.
  2719.         else if(pItem->m_bDelayed == TRUE)    {
  2720.             DisplayIcon(Rect.left - lOrgX, Rect.top - lOrgY, IL_IMAGE_DELAYED);
  2721.             return;
  2722.         }
  2723.         else if(pItem->m_bBroken == TRUE)    {
  2724.             DisplayIcon(Rect.left - lOrgX, Rect.top - lOrgY, IL_IMAGE_BAD_DATA);
  2725.         }
  2726.         else if(pItem->m_bLoading == TRUE)    {
  2727.             //    Can't draw if still loading.
  2728.             return;            
  2729.         }
  2730.  
  2731.         //    Okay to draw.
  2732.         HDC hdc = GetContextDC();
  2733.         RECT crRect;
  2734.         ::SetRect(&crRect, (int)Rect.left,(int)Rect.top,(int)Rect.right,(int)Rect.bottom);
  2735.         CDC dc;
  2736.         dc.Attach(hdc);
  2737.         COLORREF backgroundColor = (COLORREF)GetSysColor(COLOR_WINDOW);
  2738.         HBRUSH tempBrush = ::CreateSolidBrush(backgroundColor);
  2739.         ::FillRect(dc.GetSafeHdc(), &crRect,tempBrush);
  2740.         ::DeleteObject(tempBrush);
  2741.         if (pItem->IsInPlaceActive())  {
  2742.             if (!pItem->m_bSetExtents) {
  2743.                 pItem->m_bSetExtents = TRUE;
  2744.                 SIZEL temp1;
  2745.                 temp1.cx = Twips2MetricX(crRect.right - crRect.left);
  2746.                 temp1.cy = Twips2MetricY(crRect.bottom - crRect.top);
  2747.                 HRESULT sc = pItem->m_lpObject->SetExtent(DVASPECT_CONTENT, &temp1);
  2748.                 sc = pItem->m_lpObject->Update();
  2749.             }
  2750.             crRect.left += sysInfo.m_iScrollWidth + sysInfo.m_iBorderWidth;
  2751.             crRect.top += sysInfo.m_iScrollHeight + sysInfo.m_iBorderHeight;
  2752.             crRect.right -=  sysInfo.m_iScrollWidth + sysInfo.m_iBorderWidth;
  2753.             crRect.bottom -= sysInfo.m_iScrollHeight + sysInfo.m_iBorderHeight;
  2754.             pItem->SetItemRects(&crRect);
  2755.         }
  2756.         pItem->Draw(&dc, &crRect);
  2757.         dc.Detach();
  2758.         ReleaseContextDC(hdc);
  2759.     }
  2760. }
  2761.  
  2762. void CDCCX::DisplayHR(MWContext *pContext, int iLocation, LO_HorizRuleStruct *pHorizRule)    
  2763. {
  2764.     //    Figure out the coordinates of where to draw the HR.
  2765.     LTRB Rect;
  2766. //    if(ResolveElement(Rect, pHorizRule, iLocation) == TRUE)    {
  2767.     if(ResolveElement(Rect, pHorizRule->x,pHorizRule->y,
  2768.                     pHorizRule->x_offset, pHorizRule->y_offset,
  2769.                     pHorizRule->width, pHorizRule->height) == TRUE)    {
  2770.         SafeSixteen(Rect);
  2771.  
  2772. #ifdef EDITOR
  2773.         // Don't draw the editor's end-of-document hrule unless we're
  2774.         // displaying paragraph marks.
  2775.         if ( pHorizRule->edit_offset < 0 && ! EDT_DISPLAY_PARAGRAPH_MARKS(pContext) ) {
  2776.             return;
  2777.         }
  2778.  
  2779.         // Increase height of selection rect if it is very small
  2780.         LTRB SelRect = Rect;
  2781.         if( SelRect.Height() < 6 )
  2782.         {
  2783.             SelRect.top -= (6 - SelRect.Height())/2;
  2784.             SelRect.bottom = SelRect.top + 6;
  2785.         }
  2786. //        EraseToBackground(SelRect);
  2787. #endif /* EDITOR */
  2788.  
  2789.         //    Find out if we are doing a solid or 3D HR.
  2790.         if(ResolveHRSolid(pHorizRule) == TRUE)    {
  2791.             HDC hdc = GetContextDC();
  2792.  
  2793.             //    Draw a solid HR.
  2794.             //    We'll be using the darker color to do this.
  2795.             COLORREF rgbColor = ResolveDarkLineColor();
  2796.  
  2797.             HPEN cpHR = ::CreatePen(PS_SOLID, CASTINT(Pix2TwipsY(pHorizRule->thickness)), rgbColor);
  2798.             HPEN pOldPen = (HPEN)::SelectObject(hdc, cpHR);
  2799.             if(MMIsText() == TRUE)    {
  2800.                 ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top + Rect.Height() / 2), NULL);
  2801.                 ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.top + Rect.Height() / 2));    //    use top, or diagonal.
  2802.             }
  2803.             else    {
  2804.                 ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top), NULL);
  2805.                 ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.top));    //    use top, or diagonal.
  2806.             }
  2807.             ::SelectObject(hdc, pOldPen);
  2808.             VERIFY(::DeleteObject(cpHR));
  2809.     
  2810.             ReleaseContextDC(hdc);
  2811.         }
  2812.         else    {
  2813.             Display3DBox(Rect, ResolveDarkLineColor(), ResolveLightLineColor(),
  2814.                 Pix2TwipsX(1), TRUE);
  2815.         }
  2816. #ifdef EDITOR
  2817.         DisplaySelectionFeedback(pHorizRule->ele_attrmask, SelRect);
  2818. #endif //EDITOR
  2819.     }
  2820. }
  2821.  
  2822. // Common algorithm for setting contrasting background and text colors
  2823. void wfe_GetSelectionColors( COLORREF rgbBackgroundColor, 
  2824.                              COLORREF* pTextColor, COLORREF* pBackColor)
  2825. {
  2826.     //CLM: Always use Blue text on white or white text on blue if selecting
  2827.     // Test intensity of real background so entire selection uses same colors
  2828.     // This algorithm favors using dark
  2829.     // Possible problem: If we have relatively bright text on a dark background image
  2830.     BOOL bDarkBackground = (GetRValue(rgbBackgroundColor) + 
  2831.                             GetGValue(rgbBackgroundColor) + 
  2832.                             GetBValue(rgbBackgroundColor)) < 192;
  2833.  
  2834.     if( pTextColor ){
  2835.         *pTextColor = bDarkBackground ? RGB(0,0,128) : RGB(255,255,255);
  2836.     }
  2837.     if( pBackColor ){
  2838.         *pBackColor = bDarkBackground ?  RGB(255,255,255) : RGB(0,0,128);
  2839.     }
  2840. }
  2841.  
  2842.                
  2843. void CDCCX::DisplayLineFeed(MWContext *pContext, int iLocation, LO_LinefeedStruct *pLineFeed, XP_Bool clear)
  2844. {
  2845.     LTRB Rect;
  2846.     Bool bElementResolved;
  2847.     Bool bSpecialDrawing = EDT_IS_EDITOR(pContext) && pLineFeed->break_type;
  2848.  
  2849. #ifdef EDITOR
  2850.     // Allow selection feedback and display of end-of-paragraph marks in the editor.
  2851.     // We do nothing if we're not in the editor.
  2852.     // We do nothing if this isn't an end-of-paragraph or hard break.
  2853.     // If we're displaying the marks, then we display them as little squares.
  2854.     // Otherwise we just do the selection feedback.
  2855.     // The selection feedback is a rectangle the height of the linefeed 1/2 of the rectangle's height.
  2856.     // located at the left edge of the linefeed's range.
  2857.  
  2858.     // We need to expand the linefeed's width here so that ResolveElement thinks it's at least as wide
  2859.     // as we're going to draw it.
  2860.     Bool bExpanded = FALSE;
  2861.     int32 expandedWidth;
  2862.     int32 expandedHeight;
  2863.     if ( bSpecialDrawing ) {
  2864.         const int32 kMinimumWidth = 7;
  2865.         const int32 kMinimumHeight = 12;
  2866.  
  2867.         int32 originalWidth = pLineFeed->width;
  2868.         int32 originalHeight= pLineFeed->height;
  2869.         expandedWidth = originalWidth;
  2870.         expandedHeight = originalHeight;
  2871.  
  2872.         if ( expandedWidth < kMinimumWidth ) {
  2873.             expandedWidth = kMinimumWidth;
  2874.             bExpanded = TRUE;
  2875.         }
  2876.         if ( expandedHeight < kMinimumHeight ) {
  2877.             expandedHeight = kMinimumHeight;
  2878.             bExpanded = TRUE;
  2879.         }
  2880.         pLineFeed->width = expandedWidth;
  2881.         pLineFeed->height = expandedHeight;
  2882. //        bElementResolved = ResolveElement(Rect, pLineFeed, iLocation);
  2883.         bElementResolved = ResolveElement(Rect, pLineFeed->x, pLineFeed->y,
  2884.                                     pLineFeed->x_offset,pLineFeed->y_offset,
  2885.                                     pLineFeed->width, pLineFeed->height);
  2886.         pLineFeed->width = originalWidth;
  2887.         pLineFeed->height = originalHeight;
  2888.     }
  2889.     else
  2890.     {
  2891. //        bElementResolved = ResolveElement(Rect, pLineFeed, iLocation);
  2892.         bElementResolved = ResolveElement(Rect, pLineFeed->x, pLineFeed->y,
  2893.                                 pLineFeed->x_offset, pLineFeed->y_offset,
  2894.                                 pLineFeed->width, pLineFeed->height);
  2895.     }
  2896. #else
  2897. //    bElementResolved = ResolveElement(Rect, pLineFeed, iLocation);
  2898.         bElementResolved = ResolveElement(Rect, pLineFeed->x, pLineFeed->y,
  2899.                                 pLineFeed->x_offset, pLineFeed->y_offset,
  2900.                                 pLineFeed->width, pLineFeed->height);
  2901. #endif
  2902.  
  2903.     if (bElementResolved) {
  2904.         SafeSixteen(Rect);
  2905.  
  2906.         if ( ! EDT_IS_EDITOR(pContext) || ! pLineFeed->break_type ) {
  2907.             // If the linefeed has a solid background color, then use it.
  2908.             // To Be Done: If we're selected, use the fg color instead of the bg color.
  2909. #ifndef LAYERS
  2910.       // For layers, we don't want to draw the background 
  2911.             if (pLineFeed->text_attr->no_background == FALSE && !IsPrintContext()) {
  2912.                 HBRUSH     hBrush;
  2913.                 CRect     cRect(CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  2914.                 HDC hdc = GetContextDC(iLocation);
  2915.  
  2916.                 if (m_iBitsPerPixel == 16)
  2917.                     // We don't want a dithered brush
  2918.                     hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, RGB(pLineFeed->text_attr->bg.red,
  2919.                         pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue)));
  2920.                 else
  2921.                     hBrush = ::CreateSolidBrush(0x02000000L | ResolveBGColor(pLineFeed->text_attr->bg.red,
  2922.                         pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue));
  2923.                 HBRUSH hOldBrush;
  2924.                 hOldBrush = ::SelectObject(hdc, hBrush);
  2925.                 ::FillRect(hdc, &cRect, hBrush);
  2926.                 ::SelectObject(hdc, hOldBrush);
  2927.                 VERIFY(::DeleteObject(hBrush));
  2928.  
  2929.                 ReleaseContextDC(hdc, iLocation);
  2930.             }
  2931. #endif // LAYERS
  2932.             return;
  2933.         }
  2934.  
  2935.         HDC hdc = GetContextDC();
  2936.         RECT r;
  2937.         ::SetRect(&r, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  2938.         // Need to look up the text color.
  2939.         LO_TextAttr * attr = pLineFeed->text_attr;
  2940.  
  2941.         //    Determine the color.
  2942.         COLORREF rgbColor = ResolveTextColor(attr);
  2943.         COLORREF textBackColor;
  2944.         Bool selected = pLineFeed->ele_attrmask & LO_ELE_SELECTED;
  2945.  
  2946.         if ( selected ) {
  2947.             wfe_GetSelectionColors(m_rgbBackgroundColor, &rgbColor, &textBackColor);
  2948.         }
  2949.  
  2950.         if (clear & ! selected) {
  2951. #ifdef EDITOR
  2952.             // If the linefeed has a solid background color, then use it
  2953.             if (pLineFeed->text_attr->no_background == FALSE && !IsPrintContext()) {
  2954.                 HBRUSH     hBrush;
  2955.                 RECT     cRect;
  2956.                 ::SetRect(&cRect, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  2957.  
  2958.                 if (m_iBitsPerPixel == 16)
  2959.                     // We don't want a dithered brush
  2960.                     hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, RGB(pLineFeed->text_attr->bg.red,
  2961.                         pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue)));
  2962.                 else
  2963.                     hBrush = ::CreateSolidBrush(0x02000000L | ResolveBGColor(pLineFeed->text_attr->bg.red,
  2964.                         pLineFeed->text_attr->bg.green, pLineFeed->text_attr->bg.blue));
  2965.                 ::FillRect(hdc, &cRect, hBrush);
  2966.                 VERIFY(::DeleteObject(hBrush));
  2967.             }
  2968.             else {
  2969.                 EraseToBackground(Rect);
  2970.             }
  2971.             // If this linefeed draws outside it bounds, then
  2972.             // EraseToBackground could have
  2973.             // smashed a nearby element.
  2974.             // So invalidate this portion. (The main examples of this are
  2975.             // linefeeds in tables.)
  2976.             if ( bExpanded && IsWindowContext()) {
  2977.                 ::InvalidateRect(PANECX(pContext)->GetPane(), &r, FALSE);
  2978.             }
  2979. #endif
  2980.         }
  2981.  
  2982. #ifdef EDITOR
  2983.         // Limit the size of the drawn paragraph marker.
  2984.         const int32 kMaxHeight = 30;
  2985.         if ( expandedHeight > kMaxHeight ){
  2986.             expandedHeight = kMaxHeight;
  2987.         }
  2988.         int32 desiredWidth = expandedHeight / 2;
  2989.         if ( expandedWidth > desiredWidth ) {
  2990.             expandedWidth = desiredWidth;
  2991.         }
  2992.  
  2993.         r.right = CASTINT(r.left + expandedWidth);
  2994.         r.bottom = CASTINT(r.top + expandedHeight);
  2995.  
  2996. #endif        
  2997.         if (selected) {
  2998.             HBRUSH cbBrush = ::CreateSolidBrush(textBackColor);
  2999.             ::FillRect(hdc, &r, cbBrush);
  3000.             VERIFY(::DeleteObject(cbBrush));
  3001.         }
  3002.         if ( EDT_DISPLAY_PARAGRAPH_MARKS(pContext)
  3003.             && (! pLineFeed->prev // Don't draw mark after end-of-doc mark
  3004.                 || pLineFeed->prev->lo_any.edit_offset >= 0 ) ) {
  3005.             HBRUSH cbBrush = ::CreateSolidBrush(rgbColor);
  3006.             if ( r.right - r.left > 5 ) {
  3007.                 r.left += 2;
  3008.                 r.right -= 2;
  3009.             }
  3010.             if ( r.bottom - r.top > 5 ) {
  3011.                 r.top += 2;
  3012.                 r.bottom -= 2;
  3013.             }
  3014.             // draw line breaks at 1/3 height of paragraph marks
  3015.             if ( pLineFeed->break_type == LO_LINEFEED_BREAK_HARD ){
  3016.                 r.top += (r.bottom - r.top) * 2 / 3;
  3017.             }
  3018.             ::FillRect(hdc, &r, cbBrush);
  3019.             VERIFY(::DeleteObject(cbBrush));
  3020.         }
  3021.         ReleaseContextDC(hdc);
  3022.     }
  3023. }
  3024.  
  3025. void CDCCX::DisplaySubDoc(MWContext *pContext, int iLocation, LO_SubDocStruct *pSubDoc)    {
  3026.     LTRB Rect;
  3027. //    if(ResolveElement(Rect, pSubDoc, iLocation) == TRUE)    {
  3028.     if(ResolveElement(Rect, pSubDoc->x, pSubDoc->y, pSubDoc->x_offset,
  3029.                         pSubDoc->y_offset, pSubDoc->width, pSubDoc->height) == TRUE)    {
  3030.         SafeSixteen(Rect);
  3031.  
  3032.         if(pSubDoc->border_width > 0)    {
  3033.             Display3DBox(Rect, ResolveLightLineColor(), ResolveDarkLineColor(), pSubDoc->border_width);
  3034.         }
  3035.     }
  3036. }
  3037.  
  3038. void CDCCX::DisplayCell(MWContext *pContext, int iLocation, LO_CellStruct *pCell)    {
  3039.     LTRB Rect;
  3040. //    if(ResolveElement(Rect, pCell, iLocation) == TRUE)    {
  3041.     if(ResolveElement(Rect, pCell->x, pCell->y, pCell->x_offset,
  3042.                         pCell->y_offset, pCell->width, pCell->height) == TRUE)    {
  3043.         SafeSixteen(Rect);
  3044.  
  3045. #ifndef LAYERS
  3046.         // With layers, the background color is done with a layer
  3047.  
  3048.         // If the cell has a background color, then use it
  3049.         if (pCell->bg_color && !IsPrintContext()) {
  3050.             HBRUSH     hBrush;
  3051.             RECT     cRect;
  3052.             ::SetRect(&cRect, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  3053.             HDC hdc = GetContextDC(iLocation);
  3054.  
  3055.             if (m_iBitsPerPixel == 16)
  3056.                 // We don't want a dithered brush
  3057.                 hBrush = ::CreateSolidBrush(::GetNearestColor(hdc, RGB(pCell->bg_color->red,
  3058.                     pCell->bg_color->green, pCell->bg_color->blue)));
  3059.             else
  3060.                 hBrush = ::CreateSolidBrush(0x02000000L | ResolveBGColor(pCell->bg_color->red,
  3061.                     pCell->bg_color->green, pCell->bg_color->blue));
  3062.  
  3063.             ::FillRect(hdc, &cRect, hBrush);
  3064.             VERIFY(::DeleteObject(hBrush));
  3065.  
  3066.             ReleaseContextDC(pDC, iLocation);
  3067.         }
  3068.  
  3069.         // If we decide to allow nested table cells to have the
  3070.         // background show through then we need this code
  3071. #endif /* LAYERS */
  3072. #ifdef EDITOR
  3073.         if( EDT_IS_EDITOR(pContext) )
  3074.         {
  3075.             int32 iExtraSpace = 0;
  3076.             int32 iBorder = pCell->border_width;
  3077.             // Cell highlightin is thicker
  3078.             int32 iMaxWidth = 2 * ED_SELECTION_BORDER;
  3079.             BOOL bSelected = pCell->ele_attrmask & LO_ELE_SELECTED;
  3080.             BOOL bSelectedSpecial = pCell->ele_attrmask & LO_ELE_SELECTED_SPECIAL;
  3081.             COLORREF rgbBorder;
  3082.             HDC hDC = 0;
  3083.  
  3084.             if( bSelected || bSelectedSpecial )
  3085.             {
  3086.                 // Use the selection background color to draw a solid border
  3087.                 wfe_GetSelectionColors(m_rgbBackgroundColor, NULL, &rgbBorder);
  3088.                 hDC = GetContextDC();
  3089.                 RECT r;
  3090.                 ::SetRect(&r, CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom));
  3091.  
  3092.                 // If there is inter-cell spacing and 
  3093.                 // draw selection in that region as much as possible
  3094.                 if( pCell->inter_cell_space > 0 && iBorder < iMaxWidth )
  3095.                 {
  3096.                     iExtraSpace = min(iMaxWidth - iBorder, pCell->inter_cell_space / 2);
  3097.                     iBorder += iExtraSpace;
  3098.                     ::InflateRect(&r, iExtraSpace, iExtraSpace);
  3099.                 }
  3100.  
  3101.                 LTRB borderWidths(iBorder, iBorder, iBorder, iBorder);
  3102.  
  3103.                 if( bSelectedSpecial )
  3104.                 {
  3105.                     // Show a solid DASHED border as the special selection feedback
  3106.                     DisplaySpecialBorder(hDC, r, rgbBorder, iBorder, TRUE);
  3107.                 } else {
  3108.                     // Show a solid border as the selection feedback
  3109.                     DisplaySolidBorder(hDC, r, rgbBorder, borderWidths);
  3110.                 }
  3111.             }
  3112.  
  3113.             if( pCell->border_width == 0 || LO_IsEmptyCell(pCell) )
  3114.             {
  3115.                 // Draw zero-border and empty cells with the dotted line
  3116.                 //   (Navigator will not display borders of empty cells)
  3117.                 // Don't bother testing (EDT_DISPLAY_TABLE_BORDERS)
  3118.                 //  since we don't support turning borders off now
  3119.                 EditorDisplayZeroWidthBorder(Rect, pCell->ele_attrmask & LO_ELE_SELECTED);
  3120.  
  3121.             }
  3122.             else if( !bSelected )
  3123.             {
  3124.                 Display3DBox(Rect, ResolveDarkLineColor(), ResolveLightLineColor(), pCell->border_width);
  3125.             }
  3126.  
  3127.             // If directly-drawn selection border is narrower than minimum selection width (ED_SELECTION_BORDER)
  3128.             //  add inverse highlighting whose width is ED_SELECTION_BORDER
  3129.             // Thus total selection effect will always be between 
  3130.             //      ED_SELECTION_BORDER and (2*ED_SELECTION_BORDER) in thickness
  3131.             if( hDC && (bSelected || bSelectedSpecial) &&
  3132.                 iBorder < ED_SELECTION_BORDER )
  3133.             {
  3134.                 //  TODO: IMAGES THAT FILL CELL WILL OVERWRITE THIS SELECTION - Especially bad when iBorder = 0
  3135.                 LTRB CellRect = Rect;
  3136.                 // Draw inside the border rect
  3137.                 CellRect.Inflate(-1);
  3138.                 if( bSelectedSpecial )
  3139.                 {
  3140.                     RECT r;
  3141.                     ::SetRect(&r, CASTINT(CellRect.left), CASTINT(CellRect.top), 
  3142.                               CASTINT(CellRect.right), CASTINT(CellRect.bottom));
  3143.                     // Show an inverted DASHED border as the special selection feedback
  3144.                     DisplaySpecialBorder(hDC, r, rgbBorder, iBorder, FALSE);
  3145.                 } else {
  3146.                     DisplaySelectionFeedback(LO_ELE_SELECTED, CellRect);
  3147.                 }
  3148.             }
  3149.             
  3150.             if( hDC )
  3151.                 ReleaseContextDC(hDC);
  3152.         } 
  3153.         else
  3154. #endif // EDITOR
  3155.         // Normal border drawing for Navigator
  3156.         if( pCell->border_width > 0 ) {
  3157.             Display3DBox(Rect, ResolveDarkLineColor(), ResolveLightLineColor(), pCell->border_width);
  3158.         }
  3159.     }
  3160. }
  3161.  
  3162. VOID CALLBACK EXPORT LineDDAProcTabFocus(
  3163.     int x,    // x-coordinate of point being evaluated  
  3164.     int y,    // y-coordinate of point being evaluated  
  3165.     LPARAM lpData     // address of application-defined data 
  3166.    )
  3167. {
  3168.     static BOOL flip = FALSE;
  3169.     // HDC hdc = (HDC) lpData;
  3170.     flip = ! flip;
  3171. #ifdef _WIN32
  3172.     SetPixelV((HDC)lpData, x, y, flip? COLORREF(RGB(0,0,0)) : COLORREF(RGB(255,255,255)) ); 
  3173. #else
  3174.     SetPixel((HDC)lpData, x, y, flip? COLORREF(RGB(0,0,0)) : COLORREF(RGB(255,255,255)) ); 
  3175. #endif
  3176.     return;
  3177. }    
  3178.  
  3179. void CDCCX::DrawTabFocusLine( HDC hdc, BOOL supportPixel, int x, int y, int x2, int y2)
  3180. {
  3181.     if( supportPixel ) {
  3182.         // support SetPixel()
  3183.         LineDDA( x, y, x2, y2, (LINEDDAPROC)LineDDAProcTabFocus, (LPARAM)hdc );
  3184.     } else {
  3185.         // SetPixel is not supported
  3186. #ifdef _WIN32
  3187.         ::MoveToEx(hdc, x,  y, NULL);
  3188. #else
  3189.         ::MoveTo(hdc, x,  y );
  3190. #endif
  3191.         ::LineTo(hdc, x2, y2);
  3192.     }
  3193.  
  3194. }
  3195.  
  3196. // Monochrome brush with every other pixel set
  3197. struct CAlternateBrush {
  3198.     HBRUSH    hBrush;
  3199.  
  3200.     CAlternateBrush();
  3201.    ~CAlternateBrush();
  3202. } alternateBrush;
  3203.  
  3204. CAlternateBrush::CAlternateBrush()
  3205. {
  3206.     // Monochrome pattern brush we use for drawing horizontal and vertical alternate
  3207.     // lines (lines with every other pixel set)
  3208.     static const WORD gray50 [] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
  3209.     HBITMAP    hBitmap = ::CreateBitmap(8, 8, 1, 1, gray50);
  3210.  
  3211.     hBrush = ::CreatePatternBrush(hBitmap);
  3212.     ::DeleteObject(hBitmap);
  3213. }
  3214.  
  3215. CAlternateBrush::~CAlternateBrush()
  3216. {
  3217.     ::DeleteObject(hBrush);
  3218. }
  3219.  
  3220. void CDCCX::DrawTabFocusRect( HDC hdc, BOOL supportPixel, int left, int top, int right, int bottom)
  3221. {
  3222.     RECT    rect = {left, top, right, bottom};
  3223.     DWORD    dwOldTextColor, dwOldBkColor;
  3224.  
  3225.     ASSERT(alternateBrush.hBrush);
  3226.  
  3227.     dwOldTextColor = ::SetTextColor(hdc, RGB(0,0,0));
  3228.     dwOldBkColor = ::SetBkColor(hdc, RGB(255,255,255));
  3229.  
  3230.     ::FrameRect(hdc, &rect, alternateBrush.hBrush);
  3231.  
  3232.     ::SetTextColor(hdc, dwOldTextColor);
  3233.     ::SetBkColor(hdc, dwOldBkColor);
  3234. }
  3235.  
  3236. //#ifndef NO_TAB_NAVIGATION 
  3237. // see function lo_is_location_in_area() in file ns\lib\layout\laymap.c for area types.
  3238. void CDCCX::DrawMapAreaBorder( int baseX, int baseY, lo_MapAreaRec * theArea )
  3239. {
  3240.     int     centerX, centerY, radius;
  3241.     int        left, top, right, bottom;
  3242.     int        oldDrawingMode;
  3243.     int        ii;
  3244.     HDC        hdc = GetContextDC();
  3245.     HPEN    pTabFocusPen;
  3246.     HPEN    pOldPen;
  3247.     HBRUSH    hOldBrush;
  3248.     BOOL    supportPixel = ::GetDeviceCaps(  hdc, RASTERCAPS ) & RC_BITBLT ;
  3249.  
  3250.     if( ! supportPixel || theArea->type == AREA_SHAPE_CIRCLE ) {
  3251.         // todo get color for hi-light
  3252.         oldDrawingMode    = SetROP2( hdc, R2_NOT);        // R2_NOT reverse the screen color
  3253.         pTabFocusPen    = ::CreatePen(PS_DOT, 1, COLORREF( RGB(0,0,0)) );
  3254.         pOldPen            = (HPEN)::SelectObject(hdc, pTabFocusPen);
  3255.         hOldBrush        = (HBRUSH) ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH));
  3256.     }
  3257.     
  3258.     switch( theArea->type )
  3259.     {
  3260.         case AREA_SHAPE_RECT:
  3261.             if (theArea->coord_cnt >= 4)
  3262.             {
  3263.                 left    = (int)(baseX + theArea->coords[0]);        // Pix2TwipsY()?
  3264.                 top        = (int)(baseY + theArea->coords[1]);
  3265.                 right    = (int)(baseX + theArea->coords[2]);
  3266.                 bottom    = (int)(baseY + theArea->coords[3]);
  3267.                 DrawTabFocusRect(hdc, supportPixel, left, top, right, bottom);
  3268.                 if( supportPixel )
  3269.                     DrawTabFocusRect(hdc, supportPixel, left+1, top+1, right-1, bottom-1);  // double line
  3270.             }
  3271.             break;
  3272.  
  3273.         case AREA_SHAPE_CIRCLE:
  3274.             if ( theArea->coord_cnt >= 3)
  3275.             {
  3276.                 centerX = (int)theArea->coords[0] + baseX;
  3277.                 centerY = (int)theArea->coords[1] + baseY;
  3278.                 radius    = (int)theArea->coords[2];
  3279.                 
  3280.                 left    = centerX - radius ;
  3281.                 top        = centerY - radius ;
  3282.                 right    = centerX + radius ;
  3283.                 bottom    = centerY + radius ;
  3284.                 //todo the NULL_BRUSH may cause problems on some platforms(win3.1, win95).
  3285.                 ::Ellipse(hdc, left, top, right, bottom);
  3286.                 ::Ellipse(hdc, left+1, top+1, right-1, bottom-1);  // double line
  3287.             }
  3288.             break;
  3289.  
  3290.         case AREA_SHAPE_POLY:
  3291.             if (theArea->coord_cnt >= 6)
  3292.             {
  3293.                 for( ii=0; ii<= theArea->coord_cnt-4; ii+=2) {
  3294.                     DrawTabFocusLine( hdc, supportPixel, 
  3295.                         (int)theArea->coords[ii]   + baseX, (int)theArea->coords[ii+1] + baseY,
  3296.                         (int)theArea->coords[ii+2] + baseX, (int)theArea->coords[ii+3] + baseY);
  3297.                 }
  3298.                 // make it close
  3299.                 // work around: for 6 edges, theArea->coord_cnt is 13 !! 
  3300.                 // Cannot use theArea->coord_cnt-2 for last x.
  3301.                 // use ii, which stoped at the last point.
  3302.                 DrawTabFocusLine( hdc, supportPixel, 
  3303.                     (int)theArea->coords[ii]   + baseX, (int)theArea->coords[ii+1] + baseY,
  3304.                         (int)theArea->coords[0] + baseX, (int)theArea->coords[1] + baseY);
  3305.  
  3306.             }
  3307.             break;
  3308.  
  3309.         case AREA_SHAPE_DEFAULT:
  3310.             // TODO ??????
  3311.             break;
  3312.  
  3313.         case AREA_SHAPE_UNKNOWN:
  3314.         default:
  3315.             break;
  3316.     }
  3317.  
  3318.     if( ! supportPixel || theArea->type == AREA_SHAPE_CIRCLE ) {
  3319.         ::SelectObject(hdc, hOldBrush);
  3320.         ::SelectObject(hdc, pOldPen);
  3321.         VERIFY(::DeleteObject(pTabFocusPen));
  3322.         ::SetROP2( hdc, oldDrawingMode );
  3323.     }
  3324.  
  3325.     ReleaseContextDC(hdc);
  3326.  
  3327. }
  3328. //#endif    /* NO_TAB_NAVIGATION */
  3329.  
  3330.  
  3331.  
  3332. void CDCCX::DisplaySubtext(MWContext *pContext, int iLocation, LO_TextStruct *pText, int32 lStartPos, int32 lEndPos, XP_Bool iClear)    
  3333. {
  3334.     //    Figure the coordinates of where to draw the text.
  3335.     LTRB Rect;
  3336.     if(ResolveElement(Rect, pText, iLocation, lStartPos, lEndPos, iClear) == TRUE)    {
  3337.         SafeSixteen(Rect);
  3338.  
  3339.         HDC hdc = GetContextDC();
  3340.  
  3341.         // cache the attribute pointer
  3342.         LO_TextAttr * attr = pText->text_attr;
  3343.  
  3344.         BOOL display_background_color = !attr->no_background;
  3345.  
  3346.         //    Determine the color.
  3347.         COLORREF rgbColor = ResolveTextColor(attr);
  3348.         
  3349.         //    If the color is the same as the background color, then we are selecting.
  3350.         //    Go into opaque mode.
  3351.         COLORREF rgbOldBackgroundColor;
  3352.  
  3353.         // what color does layout think our background color is?
  3354.         COLORREF textBackColor = RGB(attr->bg.red, attr->bg.green, attr->bg.blue);
  3355.  
  3356.         //IMPORTANT! Note that we will get called to draw a sub-part of a text line
  3357.         //   with LO_ELE_SELECTED flag set and the selected start-end is 
  3358.         //   outside of range to be drawn, thus we are really drawing the UNSELECTED
  3359.         //   portion of the text. So be sure to test that drawing and selectd start positions match
  3360.  
  3361.         // [ = lStartPos
  3362.         // ] = lEndPos
  3363.         // ( = sel_start
  3364.         // ) = sel_end
  3365.         // selection calls one of these two:
  3366.         //     subtext           [ (    ) ]
  3367.         //     subtext [        ]  (    )
  3368.         // drawtext calls subtext three times: [       ] [(     )] [      ]
  3369.  
  3370.         BOOL bSelected = (pText->ele_attrmask & LO_ELE_SELECTED) && 
  3371.                          (lStartPos >= (int32)pText->sel_start) &&
  3372.                          ((int32)pText->sel_end >= lEndPos) ;
  3373.  
  3374. #if 0
  3375.         XP_TRACE(("DisplaySubtext args: lStartPos(%d) lEndPos(%d)"
  3376.             " iClear(%d) element: selected(%d) sel_start(%d) sel_end(%d) bSelected(%d)\n",
  3377.             lStartPos, lEndPos,
  3378.             iClear,
  3379.             (pText->ele_attrmask & LO_ELE_SELECTED),
  3380.             (int32)pText->sel_start,  (int32)pText->sel_end, bSelected
  3381.             ));
  3382. #endif
  3383.         if (bSelected) {
  3384.             // Note that we do NOT have the "real" text color if selected,
  3385.             //  making it impossible to preview new colors in Character Properties dialog
  3386.             wfe_GetSelectionColors(m_rgbBackgroundColor, &rgbColor, &textBackColor);
  3387.             display_background_color = TRUE;
  3388.         }
  3389.  
  3390.         if(display_background_color)
  3391.         {
  3392.             rgbOldBackgroundColor = ::SetBkColor(hdc, textBackColor);
  3393.             ::SetBkMode(hdc, OPAQUE);
  3394.         }
  3395.  
  3396.         //    Select the font.
  3397.         CyaFont    *pMyFont;
  3398.         SelectNetscapeFontWithCache( hdc, attr, pMyFont);
  3399.  
  3400.         //    Set the text color.
  3401.         COLORREF rgbOldColor = ::SetTextColor(hdc, rgbColor);
  3402.  
  3403.         // Originally, we drew just the substring of characters
  3404.         // that we were asked to. But this did not handle kerning
  3405.         // correctly, since kerned characters could intrude into the
  3406.         // area of the substring. Worse, when selecting, the reverse-
  3407.         // video characters were drawn outside their boundaries, which
  3408.         // caused thin vertical strips of selection to remain when the
  3409.         // selection was erased.
  3410.         //
  3411.         // Now we draw the whole string, clipped to the bounds of the
  3412.         // substring. -- jhp
  3413.  
  3414.         LTRB fullRect;
  3415.         ResolveElement(fullRect, pText->x, pText->y, pText->x_offset,
  3416.                         pText->y_offset, pText->width, pText->height);
  3417.         SafeSixteen(fullRect);
  3418.         //    Output
  3419.  
  3420.         int iOldDC = ::SaveDC(hdc);
  3421.         ::IntersectClipRect(hdc, (int)Rect.left, (int)Rect.top, (int)Rect.right, (int)Rect.bottom);
  3422.         CIntlWin::TextOutWithCyaFont(
  3423.             pMyFont,
  3424.             INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext)),
  3425.             hdc, 
  3426.             CASTINT(fullRect.left),
  3427.             CASTINT(fullRect.top),
  3428.             (const char *)pText->text,
  3429.             CASTINT(pText->text_len));
  3430.  
  3431.         ::RestoreDC(hdc, iOldDC);
  3432.  
  3433.         ::SetTextColor(hdc, rgbOldColor);
  3434.  
  3435.  
  3436.         //    Handle strike, under_line, Spell and INLINEINPUT manually
  3437.         DrawTextPostDecoration(hdc, attr, &Rect, rgbColor );
  3438.  
  3439.         //    Normalize our selection if present.
  3440.         if (display_background_color) {
  3441.             ::SetBkColor(hdc, rgbOldBackgroundColor);
  3442.             ::SetBkMode(hdc, TRANSPARENT);
  3443.         }
  3444.  
  3445.         ReleaseNetscapeFontWithCache( hdc, pMyFont );
  3446.     
  3447.         ReleaseContextDC(hdc);
  3448.     }
  3449. }    // void CDCCX::DisplaySubtext()
  3450.  
  3451. #define TABLE_HAS_BORDER(pTable) \
  3452.     ((pTable)->border_top_width > 0 || (pTable)->border_right_width > 0 || \
  3453.      (pTable)->border_bottom_width > 0 || (pTable)->border_left_width > 0)
  3454.  
  3455. void CDCCX::DisplayTable(MWContext *pContext, int iLocation, LO_TableStruct *pTable)    {
  3456.     LTRB Rect;
  3457.     int32 iSelectionBorder = 0;
  3458.     BOOL bHaveBorder = TABLE_HAS_BORDER(pTable);
  3459.  
  3460.     if(ResolveElement(Rect, pTable->x, pTable->y, pTable->x_offset,
  3461.                         pTable->y_offset, pTable->width, pTable->height) == TRUE)    {
  3462.         SafeSixteen(Rect);
  3463.         LTRB TableRect = Rect;
  3464.  
  3465.         //TRACE0("DisplayTable\n");
  3466.  
  3467.         if( bHaveBorder ) {
  3468.             iSelectionBorder = DisplayTableBorder(Rect, pTable);
  3469.         } 
  3470. #ifdef EDITOR
  3471.         else if ( EDT_DISPLAY_TABLE_BORDERS(pContext) )
  3472.         {
  3473.             if( 0 == pTable->inter_cell_space )
  3474.             {
  3475.                 // When no cell spacing, Table border is on top of cell borders,
  3476.                 //   so increase by 1 pixel so we always have a distinquishable table border
  3477.                 TableRect.Inflate(1);
  3478.                 iSelectionBorder = 1;
  3479.             }
  3480.             EditorDisplayZeroWidthBorder(TableRect, pTable->ele_attrmask & LO_ELE_SELECTED);
  3481.         }
  3482.  
  3483.         // Show extra selection if border was not wide enough for clear selection feedback
  3484.         if( EDT_IS_EDITOR(pContext) && (pTable->ele_attrmask & LO_ELE_SELECTED) &&
  3485.             iSelectionBorder < ED_SELECTION_BORDER )
  3486.         {
  3487.             // If directly-drawn selection border is too narrow (or none),
  3488.             //  add Inverse-Video highlighting to the maximum thickness allowed
  3489.             // Decrease size by amount of solid border used,
  3490.             if( iSelectionBorder )
  3491.                 TableRect.Inflate(-(iSelectionBorder));
  3492.  
  3493.             DisplaySelectionFeedback(LO_ELE_SELECTED, TableRect);
  3494.         }
  3495. #endif //EDITOR
  3496.     }
  3497. }
  3498.  
  3499. // handle strike , under_line, Spell and INLINEINPUT after text is drawn.
  3500. void CDCCX::DrawTextPostDecoration( HDC hdc, LO_TextAttr * attr, LTRB *pRect, COLORREF rgbColor )
  3501. {
  3502. #ifdef font_do_it  // font handles underline, strikeOut 
  3503.         //    Handle strike manually
  3504.         if(attr->attrmask & LO_ATTR_STRIKEOUT)    {
  3505.             HPEN cpStrike = ::CreatePen(PS_SOLID, CASTINT(pRect->Height() / 10), rgbColor);
  3506.             HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike);
  3507.             ::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top + pRect->Height() / 2), NULL);
  3508.             ::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->top + pRect->Height() / 2));
  3509.             ::SelectObject(hdc, pOldPen);
  3510.             VERIFY(::DeleteObject(cpStrike));
  3511.         }
  3512.  
  3513.         // because netscape font module doesn't support under_list, it is handled manually
  3514.         BOOL bUnderline = FALSE;
  3515.         if(attr->attrmask & LO_ATTR_ANCHOR) { 
  3516.             /*
  3517.              * if (prefInfo.m_bUnderlineAnchors)
  3518.              *   bUnderline = TRUE;
  3519.              */
  3520.         }
  3521.         if(attr->attrmask & LO_ATTR_UNDERLINE)    {
  3522.             bUnderline = TRUE;
  3523.         }
  3524.         if( bUnderline ) {
  3525.             HPEN cpStrike = ::CreatePen(PS_SOLID, CASTINT(pRect->Height() / 10), rgbColor);
  3526.             HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike);
  3527.             ::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top + pRect->Height()-1 ), NULL);
  3528.             ::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->top + pRect->Height()-1 ));
  3529.             ::SelectObject(hdc, pOldPen);
  3530.             VERIFY(::DeleteObject(cpStrike));
  3531.         }
  3532. #endif  // font handles underline, strikeOut 
  3533.         //    Handle Spell and INLINEINPUT  manually
  3534.         if(attr->attrmask & (LO_ATTR_SPELL | LO_ATTR_INLINEINPUT)  )    {
  3535.             HPEN cpStrike = ::CreatePen(PS_DOT, CASTINT(pRect->Height() / 10), 
  3536.                         RGB(attr->attrmask & LO_ATTR_SPELL ? 255 : 0, 
  3537.                             0,
  3538.                             attr->attrmask & LO_ATTR_SPELL ? 255 : 0 ) );
  3539.             HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike);
  3540.             ::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top + pRect->Height()-1 ), NULL);
  3541.             ::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->top + pRect->Height()-1 ));
  3542.             ::SelectObject(hdc, pOldPen);
  3543.             VERIFY(::DeleteObject(cpStrike));
  3544.         }
  3545.  
  3546. } // DrawTextPostDecoration()
  3547.  
  3548. //TODO add uint32 drawFalg to the interface, check all caller to pass in the drawFlag, 
  3549. // C++ default mechanism doesn't work for calling from C.
  3550. void CDCCX::DisplayText(MWContext *pContext, int iLocation, LO_TextStruct *pText, XP_Bool iClear)    
  3551. {
  3552.         DisplayText(pContext, iLocation, pText, iClear, 0);            // use default if calling grom C.
  3553. }
  3554.  
  3555. /* cannot use default drawFlag = 0, if this function is called from C */
  3556. // an old interface  gateway for caller in C.
  3557. void CDCCX::DisplayText(MWContext *pContext, int iLocation, LO_TextStruct *pText, XP_Bool iClear, uint32 drawFlag )    
  3558. {
  3559.     //    Figure out the coordinates of where to draw the text.
  3560.     LTRB Rect;
  3561.     if(ResolveElement(Rect, pText->x, pText->y, pText->x_offset,
  3562.                         pText->y_offset, pText->width, pText->height) == TRUE)    {
  3563.         SafeSixteen(Rect);
  3564.  
  3565.         // cache the attribute pointer
  3566.         LO_TextAttr * attr = pText->text_attr;
  3567.     
  3568.         if (attr)    // dmb 11/21/96 - w/o this line, we crash on blinking things like the phonebook.
  3569.         {
  3570.             BOOL display_background_color = !attr->no_background;
  3571.             HDC hdc;
  3572.             hdc = GetContextDC();
  3573.  
  3574.             //    Determine the color.
  3575.             COLORREF rgbColor = ResolveTextColor(attr);
  3576.  
  3577.             // what does layout think the background color is?
  3578.             COLORREF textBackColor = RGB(attr->bg.red, attr->bg.green, attr->bg.blue);
  3579.  
  3580.             // If the text is the same color as the background we are selecting text
  3581.             //   and need to go into OPAQUE mode so the text will show up on the screen
  3582.             COLORREF rgbOldBackgroundColor;
  3583.             if (pText->ele_attrmask & LO_ELE_SELECTED) {
  3584.                 display_background_color = TRUE;
  3585.                 wfe_GetSelectionColors(m_rgbBackgroundColor, &rgbColor, &textBackColor);
  3586.             }
  3587.  
  3588.             if(display_background_color)
  3589.             {
  3590.                 rgbOldBackgroundColor = ::SetBkColor(hdc, textBackColor);
  3591.                 ::SetBkMode(hdc, OPAQUE);
  3592.             }
  3593.             else {
  3594.                 ::SetBkMode(hdc, TRANSPARENT);
  3595.             }
  3596.  
  3597.             //    Select the font.
  3598.             // CNetscapeFont *pFont;
  3599.             // HFONT pOldFont = SelectFont(hdc, attr, pFont);
  3600.  
  3601.             //    Set the text color.
  3602.             COLORREF rgbOldColor = ::SetTextColor(hdc, rgbColor);
  3603.  
  3604. //    #ifndef NO_TAB_NAVIGATION
  3605.             // draw a focus box if pText is current  TabFocus
  3606.             if( drawFlag & FE_DRAW_TAB_FOCUS ) {
  3607.                 HPEN pTabFocusPen;
  3608.                 HPEN pOldPen;
  3609.                 BOOL    supportPixel = ::GetDeviceCaps(  hdc, RASTERCAPS ) & RC_BITBLT ;
  3610.                 if( ! supportPixel ) {
  3611.                     pTabFocusPen = ::CreatePen(PS_DOT, 1, rgbColor);
  3612.                     pOldPen = (HPEN)::SelectObject(hdc, pTabFocusPen);
  3613.                 }
  3614.                 
  3615.                 DrawTabFocusRect(hdc, supportPixel, CASTINT(Rect.left), CASTINT(Rect.top),
  3616.                                                 CASTINT(Rect.right), CASTINT(Rect.bottom));
  3617.                 
  3618.                 if( ! supportPixel ) {
  3619.                     ::SelectObject(hdc, pOldPen);
  3620.                     VERIFY(::DeleteObject(pTabFocusPen));
  3621.                 }
  3622.             }
  3623. //    #endif    /* NO_TAB_NAVIGATION */
  3624.  
  3625.             CyaFont            *pMyFont;
  3626.             SelectNetscapeFontWithCache( hdc, attr, pMyFont);
  3627.         
  3628. #ifdef DEBUG_aliu
  3629.             ASSERT( pMyFont );
  3630. #endif
  3631.  
  3632.             if( pMyFont ) {
  3633.                 CIntlWin::TextOutWithCyaFont(
  3634.                     pMyFont,
  3635.                     INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext)),
  3636.                     hdc, 
  3637.                     CASTINT(Rect.left),    
  3638.                     CASTINT(Rect.top),
  3639.                     (char *)pText->text,
  3640.                     CASTINT(pText->text_len) 
  3641.                 );
  3642.  
  3643.             }
  3644.             ::SetTextColor(hdc, rgbOldColor);
  3645.             
  3646.         //    Handle strike, under_line, Spell and INLINEINPUT manually
  3647.             DrawTextPostDecoration(hdc, attr, &Rect, rgbColor );
  3648.  
  3649. #if 0
  3650. moved into DrawTextPostDecoration()
  3651.             //    Handle Spell and INLINEINPUT  manually
  3652.             if(attr->attrmask & (LO_ATTR_SPELL | LO_ATTR_INLINEINPUT)  )    {
  3653.                 HPEN cpStrike = ::CreatePen(PS_DOT, CASTINT(Rect.Height() / 10), 
  3654.                             RGB(attr->attrmask & LO_ATTR_SPELL ? 255 : 0, 
  3655.                                 0,
  3656.                                 attr->attrmask & LO_ATTR_INLINEINPUT ? 255 : 0 ) );
  3657.                 HPEN pOldPen = (HPEN)::SelectObject(hdc, cpStrike);
  3658.                 ::MoveToEx(hdc, CASTINT(Rect.left), CASTINT(Rect.top + Rect.Height()-1 ), NULL);
  3659.                 ::LineTo(hdc, CASTINT(Rect.right), CASTINT(Rect.top + Rect.Height()-1 ));
  3660.                 ::SelectObject(hdc, pOldPen);
  3661.                 VERIFY(::DeleteObject(cpStrike));
  3662.             }
  3663. #endif
  3664.  
  3665.             //    Normalize our selection if present.
  3666.             if (display_background_color) {
  3667.                 ::SetBkColor(hdc, rgbOldBackgroundColor);
  3668.                 ::SetBkMode(hdc, TRANSPARENT);
  3669.             }
  3670.  
  3671.             // ReleaseFont(hdc, pOldFont);
  3672.             ReleaseNetscapeFontWithCache(hdc, pMyFont);
  3673.  
  3674.             ReleaseContextDC(hdc);
  3675.         }
  3676.     }
  3677. }    // void CDCCX::DisplayText()
  3678.  
  3679. void CDCCX::FreeEmbedElement(MWContext *pContext, LO_EmbedStruct *pEmbed)    {
  3680.     //    We have our OLE document handle this.
  3681.     GetDocument()->FreeEmbedElement(pContext, pEmbed);
  3682. }
  3683.  
  3684. void CDCCX::GetEmbedSize(MWContext *pContext, LO_EmbedStruct *pEmbed, NET_ReloadMethod bReload)    
  3685. {
  3686.     //    We have our OLE document handle this.
  3687.     GetDocument()->GetEmbedSize(pContext, pEmbed, bReload);
  3688. }
  3689.  
  3690. #ifdef LAYERS
  3691. void CDCCX::GetTextFrame(MWContext *pContext, LO_TextStruct *pText,
  3692.              int32 lStartPos, int32 lEndPos, XP_Rect *frame)
  3693. {
  3694.     frame->left = pText->x + pText->x_offset;
  3695.     frame->top = pText->y + pText->y_offset;
  3696.  
  3697.     HDC pDC = GetContextDC();
  3698.         
  3699.     CyaFont    *pMyFont;
  3700.     SelectNetscapeFontWithCache( pDC, pText->text_attr, pMyFont );
  3701.     CSize sz;
  3702.     ResolveTextExtent(pDC, (const char *)pText->text, CASTINT(lStartPos), &sz, pMyFont);
  3703.     frame->left += sz.cx;
  3704.     ResolveTextExtent(pDC, (const char *)pText->text + lStartPos, CASTINT(lEndPos - lStartPos + 1), &sz, pMyFont);
  3705.     frame->right = frame->left + sz.cx;    
  3706.         
  3707.     frame->bottom = frame->top + sz.cy;   
  3708.  
  3709.     ReleaseNetscapeFontWithCache( pDC, pMyFont );
  3710.  
  3711.     ReleaseContextDC(pDC);
  3712. }
  3713. #endif  /* LAYERS */
  3714.  
  3715. int CDCCX::GetTextInfo(MWContext *pContext, LO_TextStruct *pText, LO_TextInfo *pTextInfo)    {
  3716.     HDC hdc = GetAttribDC();
  3717.  
  3718.     //    Determine and select the font.
  3719.     CyaFont    *pMyFont;
  3720.     SelectNetscapeFontWithCache( hdc, pText->text_attr, pMyFont );
  3721.  
  3722.     //    Get the information regarding the size of the font for layout.
  3723.     SIZE sExtent;
  3724.     ResolveTextExtent(
  3725.         INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(pContext))
  3726.         , hdc, (const char *)pText->text, pText->text_len, &sExtent, pMyFont);
  3727.  
  3728.     pTextInfo->max_width = sExtent.cx;
  3729.  
  3730.     pTextInfo->ascent = pMyFont->GetAscent();
  3731.     pTextInfo->descent = pMyFont->GetDescent();
  3732.     pTextInfo->lbearing = pTextInfo->rbearing = 0;
  3733.  
  3734.     ReleaseNetscapeFontWithCache( hdc, pMyFont );
  3735.     ReleaseContextDC(hdc);
  3736.     return(TRUE);
  3737. }
  3738.  
  3739. BOOL CDCCX::ResolveTextExtent(int16 wincsid, HDC pDC, LPCTSTR pString, int iLength, LPSIZE pSize, CyaFont *pMyFont)    
  3740. {
  3741.     // Always measure it because the bytes * mean width algorithm 
  3742.     // won't work for many code point. Expecially UTF8 which 3 byte 
  3743.     // could be one character which takes 1 or 2 columns.
  3744.     return CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, wincsid, pDC, pString, iLength, pSize);
  3745. #if 0
  3746.     BOOL bRetval;
  3747.  
  3748.     // if(pMyFont->GetMeanWidth() == 0 )    {
  3749.     if( ! pMyFont->IsFixedFont() ) {
  3750.         bRetval = CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, wincsid, pDC, pString, iLength, pSize);
  3751.         return(bRetval);
  3752.     }
  3753.     else    {
  3754.         //    fixed size.
  3755.         pSize->cx = (int) ((long)pMyFont->GetMeanWidth() * (long)iLength);
  3756.         pSize->cy = pMyFont->GetHeight();
  3757.         bRetval = TRUE;
  3758.     }
  3759.     return(bRetval);
  3760. #endif
  3761. }
  3762.  
  3763.  
  3764. // 
  3765. // This function is called only when applet are windowless and force a
  3766. // paint on the java side
  3767. //
  3768. void CDCCX::DrawJavaApp(MWContext *pContext, int iLocation, LO_JavaAppStruct *pJava)
  3769. {
  3770. #ifdef JAVA
  3771.  
  3772.     RECT        rect;
  3773.     HDC         hDC = GetContextDC();
  3774.     NPEvent     event;
  3775.     FE_Region   clip;
  3776.     
  3777. #ifdef LAYERS
  3778.     clip = GetDrawingClip();
  3779.     if (clip) 
  3780.     {
  3781.         XP_Rect xprect;
  3782.         
  3783.         FE_GetRegionBoundingBox(clip, &xprect);
  3784.         rect.left = CASTINT(xprect.left);
  3785.         rect.top = CASTINT(xprect.top);
  3786.         rect.right = CASTINT(xprect.right);
  3787.         rect.bottom = CASTINT(xprect.bottom);
  3788.     }
  3789. #endif /* LAYERS */        
  3790.     
  3791.     event.event = WM_PAINT;
  3792.     event.wParam = (uint32)hDC;
  3793.     event.lParam = (uint32)▭
  3794.     
  3795.     LJ_HandleEvent(pContext, pJava, (void *)&event);
  3796.  
  3797.     ReleaseContextDC(hDC);
  3798. #endif
  3799. }
  3800.  
  3801.