home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / cxwin.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  234.8 KB  |  7,192 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.  
  21. #include "cxwin.h"
  22.  
  23. #include "cntritem.h"
  24. #include "medit.h"
  25. #include "button.h"
  26. #include "fmbutton.h"
  27. #include "gridedge.h"
  28. #include "cxsave.h"
  29. #include "netsvw.h"
  30. #include "shcut.h"
  31. #include "mainfrm.h"
  32. #include "dialog.h"
  33. #include "cxprint.h"
  34. #include "findrepl.h"
  35. #include "feembed.h"
  36. #include "libevent.h"
  37. #include "np.h"
  38. #include "nppg.h"
  39. #include "nppriv.h"
  40. #include "winclose.h"
  41. #include "tooltip.h"
  42. #include "slavewnd.h"
  43.  
  44. #include "intl_csi.h"
  45. #include "abdefn.h"
  46. #include "feimage.h"
  47. #include "edt.h"
  48. extern char * EDT_NEW_DOC_URL;
  49. extern char * EDT_NEW_DOC_NAME;
  50. #define ED_SIZE_FEEDBACK_BORDER   3
  51.  
  52. #define EDT_IS_SIZING   ( EDT_IS_EDITOR(GetContext()) && EDT_IsSizing(GetContext()) )
  53.  
  54. #ifdef JAVA
  55. #include "np.h"
  56. #include "java.h"
  57. #include "prlog.h"
  58. #ifdef DDRAW
  59. static DDSURFACEDESC ddsd;
  60. #endif
  61. extern "C" {
  62. #ifndef NSPR20
  63. PR_LOG_DEFINE(APPLET);
  64. #else
  65. extern PRLogModuleInfo *APPLET;
  66. #endif
  67.  
  68. /*
  69. ** API for querying the Navigator's Color Palette from the "outside"...
  70. ** 
  71. ** This is used by AWT, when it is first started, to clone the navigator's
  72. ** color palette. 
  73. */
  74. PR_PUBLIC_API(HPALETTE) GET_APPLICATION_PALETTE(void)
  75. {
  76.     HPALETTE hPal = (HPALETTE)NULL;
  77.     CWinCX *pActiveContext;
  78.     CGenericFrame *pFrame;
  79.  
  80.     // XXX This is busted/need to move palette in frame -- Hokay?
  81.     pFrame = ((CNetscapeApp *)AfxGetApp())->m_pFrameList;
  82.     if( pFrame ) {
  83.         pActiveContext = pFrame->GetActiveWinContext();
  84.         if( pActiveContext ) {
  85.             hPal = pActiveContext->GetPalette();
  86.         }
  87.     }
  88.     return hPal;
  89. }
  90. };
  91. #endif  /* JAVA */
  92.  
  93. // older versions of MFC don't have this #define
  94. #ifndef DEFAULT_GUI_FONT
  95. #define DEFAULT_GUI_FONT ANSI_FIXED_FONT
  96. #endif
  97.  
  98. #define NOT_A_DIALOG(wincx) \
  99.     ((wincx) ? \
  100.      (wincx)->GetFrame() ? \
  101.      (wincx)->GetFrame()->GetMainContext() ? \
  102.      (wincx)->GetFrame()->GetMainContext()->GetContext() ? \
  103.      (wincx)->GetFrame()->GetMainContext()->GetContext()->type != MWContextDialog \
  104.      : TRUE : TRUE : TRUE : TRUE)
  105.  
  106.  
  107. //    An empty frame API so that this code will work without the presence of a frame window.
  108. CNullFrame *CWinCX::m_pNullFrame = NULL;
  109. void *CWinCX::m_pExitCookie = NULL;
  110.  
  111. void wincx_exit(UINT uMsg, WPARAM wParam, LPARAM lParam)
  112. {
  113.     //  ExitInstance, clean up if possible.
  114.     if(CWinCX::m_pNullFrame) {
  115.         delete CWinCX::m_pNullFrame;
  116.         CWinCX::m_pNullFrame = NULL;
  117.     }
  118.     if(CWinCX::m_pExitCookie) {
  119.         slavewnd.UnRegister(CWinCX::m_pExitCookie);
  120.         CWinCX::m_pExitCookie = NULL;
  121.     }
  122. }
  123.  
  124.  
  125. CWinCX::CWinCX(CGenericDoc *pDocument, CFrameGlue *pFrame, CGenericView *pView, MWContextType mwType, ContextType cxType) : CPaneCX(pView ? pView->m_hWnd : NULL, FALSE) {
  126. //  Purpose:    Construct a window context
  127. //  Arguments:  pDocument   The document, if NULL, one is created in CDCCX.
  128. //                          It should be noted that this has to be a CNetscapeDoc
  129. //                              currently, since it handles certain Ole aspects in
  130. //                              the Netscape way.
  131. //              pFrame  The frame which owns this view.  Can be NULL (turns off
  132. //                          any frame access).
  133. //              hView   The view which this context interacts with.  Can not be NULL.
  134. //  Returns:    none
  135. //  Comments:   Basically set the context type.
  136. //  Revision History:
  137. //      06-25-95    created GAB
  138. //
  139.  
  140.     //  Set the context type.
  141.     m_cxType = cxType;
  142.     GetContext()->type = mwType;    //    by default only.
  143.  
  144.     m_pGenView = pView;
  145.     
  146.     //  No previous mouse event in this context.
  147.     m_LastMouseEvent = m_None;
  148.     m_bScrollingTimerSet = FALSE;
  149.     m_bMouseMoveTimerSet = FALSE;
  150.     //  We start off thinking we have a border when a frame cell.
  151.     m_bHasBorder = TRUE;
  152.  
  153.     m_MM = MM_TEXT;
  154.  
  155.     //  And the frame.
  156.     m_pFrame = pFrame;
  157.     pLastToolTipImg = 0;
  158.     m_pLastToolTipAnchor = NULL;
  159.  
  160.     //  Set up a callback in exit instance.
  161.     if(NULL == m_pExitCookie) {
  162.         m_pExitCookie = slavewnd.Register(SLAVE_EXITINSTANCE, wincx_exit);
  163.     }
  164.     //  If there's no NULL frame yet, create one.
  165.     if(NULL == m_pNullFrame)    {
  166.         m_pNullFrame = new CNullFrame;
  167.     }
  168.  
  169.     //    If there's no frame, use the Null Frame.
  170.     if(m_pFrame == NULL)    {
  171.         TRACE("Using the NULL frame\n");
  172.         m_pFrame = m_pNullFrame;
  173.     }
  174.  
  175.     //  And the document.
  176.     m_pDocument = pDocument;
  177. #ifdef DDRAW
  178.     m_ScrollWindow = FALSE;
  179.     m_physicWinRect.Empty();
  180. #endif
  181.     //    We're not active.
  182.     m_bActiveState = FALSE;
  183.  
  184.     //  We're not laying out.
  185.     m_bIsLayingOut = FALSE;
  186.  
  187.     //    We've not highlighted an anchor.
  188.     m_pLastArmedAnchor = NULL;
  189.  
  190.     //    No old progress;
  191.     m_lOldPercent = 0;
  192.  
  193.     // not doing a drag/drop operation
  194.     m_bDragging = FALSE;
  195.  
  196.     //      No selected embedded item.
  197.     m_pSelected = NULL;
  198.     
  199.     m_bSelectingCells = FALSE;
  200.     m_bInPopupMenu = FALSE;
  201.  
  202.     //    Inform the view of its new context.
  203.     if(m_pGenView)   {
  204.         m_pGenView->SetContext(this);
  205.     }
  206.  
  207.     /*__EDITOR__*/
  208.     m_bMouseInSelection = FALSE;
  209.  
  210.     //    We've not over an image.
  211.     m_pLastImageObject = NULL;
  212.  
  213.     m_crWindowRect = CRect(0, 0, 0, 0);
  214.  
  215.     //    Mouse is up not down.
  216.     m_bLBDown = FALSE;
  217.     m_bLBUp = TRUE;
  218.     m_uMouseFlags = 0;
  219.     m_cpMMove.x = m_cpMMove.y = 0;
  220.     m_ToolTip = 0;
  221.  
  222.  
  223.     //  size is not chrome specified yet.
  224.     m_bSizeIsChrome = FALSE;
  225.  
  226.     //  Clear those old elements that we will track in the
  227.     //      loaded page (see FireMouseOverEvent....)
  228.     m_pLastOverAnchorData = NULL;
  229.     m_pLastOverElement = NULL;
  230.     m_pStartSelectionCell = NULL;
  231.     m_bLastOverTextSet = FALSE;
  232.  
  233. //#ifndef NO_TAB_NAVIGATION 
  234.     m_lastTabFocus.pElement        = NULL;
  235.     m_lastTabFocus.mapAreaIndex    = 0;        // 0 means no focus, start with index 1.
  236.     m_lastTabFocus.pAnchor            = NULL;
  237.     m_isReEntry_setLastTabFocusElement  = 0;     // to provent re-entry
  238. //#endif    /* NO_TAB_NAVIGATION */
  239.  
  240.     imageToolTip = NULL;
  241. }
  242.  
  243. CWinCX::~CWinCX()   {
  244. //  Purpose:    Destroy a window context.
  245. //  Arguments:  none
  246. //  Returns:    none
  247. //  Comments:   Does context instance specific cleanup.
  248. //  Revision History:
  249. //      06-25-95    created GABby
  250. //
  251.     
  252.     MWContext *pContext = GetContext();
  253.  
  254.     if(GetFrame() != NULL)    {
  255.         GetFrame()->ClearContext(this);
  256.     }
  257.  
  258.     if (m_ToolTip)
  259.         delete m_ToolTip;
  260.  
  261.     XP_ListDestroy (imageToolTip);
  262.  
  263.     // Netcaster going away
  264.     if (GetContext() == theApp.m_pNetcasterWindow)
  265.         theApp.m_pNetcasterWindow = NULL ;
  266. }
  267.  
  268. #ifdef DDRAW
  269. void CWinCX::CalcWinPos()
  270. {
  271.     RECT tempRect1, tempRect2;
  272.  
  273.     ::GetWindowRect(GetPane(), &tempRect1);
  274.     ::GetClientRect(GetPane(), &tempRect2);
  275.  
  276.     int wWidth, cWidth;
  277.     int wHeight, cHeight;
  278.     int width, height;
  279.  
  280.     wWidth = tempRect1.right - tempRect1.left;
  281.     cWidth = tempRect2.right - tempRect2.left;
  282.     width =    wWidth - cWidth;
  283.     if (IsVScrollBarOn())
  284.         width -= sysInfo.m_iScrollWidth; 
  285.     m_physicWinRect.left = tempRect1.left + (width / 2);
  286.     m_physicWinRect.right = tempRect1.right - (width / 2);
  287.  
  288.     wHeight = tempRect1.bottom - tempRect1.top;
  289.     cHeight = tempRect2.bottom - tempRect2.top;
  290.     height = wHeight - cHeight;
  291.     if (IsHScrollBarOn())
  292.         height -= sysInfo.m_iScrollHeight; 
  293.     m_physicWinRect.top = tempRect1.top + (height / 2);
  294.     m_physicWinRect.bottom = tempRect1.bottom - (width / 2);
  295.  
  296. }
  297. #endif
  298.  
  299. void CWinCX::Initialize(BOOL bOwnDC, RECT *pRect, BOOL bInitialPalette, BOOL bNewMemDC)   {
  300. //  Purpose:    Initialize properties of this context.
  301. //  Arguments:  void
  302. //  Returns:    void
  303. //  Comments:   Basically set up the iWidth and iHeight of the context.
  304. //              To be called after initial construction.
  305. //  Revision History:
  306. //      06-25-95    created GABby
  307. //
  308.  
  309.     CPaneCX::Initialize(bOwnDC, pRect, bInitialPalette, bNewMemDC);
  310. #ifdef DDRAW
  311.     m_lpDDSPrimary = NULL;
  312.     m_lpDDSBack = NULL;
  313.     mg_pPal = NULL;
  314.     m_pClipper = NULL;
  315.     m_pOffScreenClipper = NULL;
  316.     m_offScreenDC = 0;
  317.     m_lpDD = NULL;
  318.     /*
  319.      * create the main DirectDraw object
  320.      */
  321.     if (DirectDrawCreate( NULL, &m_lpDD, NULL ) != DD_OK) {
  322.         m_lpDD->Release();
  323.         m_lpDD = NULL;
  324.     }
  325.     // initialize DirectDraw stuff.
  326.     if (m_lpDD && m_lpDD->SetCooperativeLevel( GetPane(), DDSCL_NORMAL  )!= DD_OK) {
  327.         ReleaseDrawSurface();
  328.     }
  329.     if (m_lpDD) {
  330.         SetUseDibPalColors(FALSE);
  331. //        DDSURFACEDESC       ddsd;
  332.         DDCAPS             ddscaps, ddshel;
  333.         ZeroMemory((void*)&ddscaps, sizeof(DDCAPS));
  334.         // Create the primary surface with 1 back buffer
  335.         ddscaps.dwSize = sizeof( DDCAPS );
  336.         ZeroMemory((void*)&ddshel, sizeof(DDCAPS));
  337.         // Create the primary surface with 1 back buffer
  338.         ddshel.dwSize = sizeof( DDCAPS );
  339.         m_lpDD->GetCaps(&ddscaps, &ddshel);
  340.  
  341.         ZeroMemory((void*)&ddsd, sizeof(DDSURFACEDESC));
  342.         // Create the primary surface with 1 back buffer
  343.         ddsd.dwSize = sizeof( ddsd );
  344.         ddsd.dwFlags = DDSD_CAPS;
  345.         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  346.         if (m_lpDD->CreateSurface( &ddsd, &m_lpDDSPrimary, NULL ) != DD_OK) {
  347.             ReleaseDrawSurface();
  348.         }
  349.         else {  // create Offscreen draw surface. 
  350.             CreateAndLockOffscreenSurface(*pRect);
  351.             // now create the palette for direct draw surface.
  352.             if (m_lpDDSPrimary) {
  353.                 ZeroMemory(&m_surfDesc, sizeof(ddsd));
  354.                 m_surfDesc.dwSize = sizeof(ddsd);
  355.  
  356.                 m_surfDesc.dwFlags = DDSD_PIXELFORMAT;
  357.                 m_lpDDSBack->GetSurfaceDesc(&m_surfDesc);
  358.                 DDPIXELFORMAT pFormat;
  359.                 m_lpDDSPrimary->GetPixelFormat(&pFormat);
  360.                 // If this surface supports a palette, then do it
  361.  
  362.                 if (m_surfDesc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
  363.  
  364.                     PALETTEENTRY palEntry[256];
  365.                     ::GetPaletteEntries(GetPalette(), 0, 255, palEntry);
  366.                     if (m_lpDD->CreatePalette(DDPCAPS_8BIT, palEntry, &mg_pPal, NULL) != DD_OK) {
  367.                         ReleaseDrawSurface();
  368.                     }
  369.                     else {
  370.                         if (m_lpDDSPrimary->SetPalette(mg_pPal )!= DD_OK) {
  371.                             ReleaseDrawSurface();
  372.                         }
  373.                         else {
  374.                             m_lpDDSBack->SetPalette(mg_pPal ); 
  375.                         }
  376.                     }
  377.                 }
  378.  
  379.                 // Use a clipper object for clipping when in windowed mode
  380.  
  381.                 if (m_lpDD->CreateClipper(0, &m_pClipper, NULL) != DD_OK) {
  382.                     ReleaseDrawSurface();
  383.                 }
  384.                 if (m_pClipper) {
  385.                     if (m_pClipper->SetHWnd(0, GetPane()) != DD_OK) {
  386.                         ReleaseDrawSurface();
  387.                     }
  388.                     else {
  389.                         if (m_lpDDSPrimary->SetClipper(m_pClipper) != DD_OK) {
  390.                             ReleaseDrawSurface();
  391.                         }
  392.                     }
  393.                 }
  394.                 if (m_lpDD->CreateClipper(0, &m_pOffScreenClipper, NULL) != DD_OK) {
  395.                     ReleaseDrawSurface();
  396.                 }
  397.                 else {
  398.                     if (m_lpDDSBack->SetClipper(m_pOffScreenClipper) != DD_OK) {
  399.                         ReleaseDrawSurface();
  400.                     }
  401.                 }
  402.  
  403.             }
  404.         }
  405.     }
  406. #endif
  407. }
  408.  
  409. #ifdef DDRAW
  410. void CWinCX::SetClipOnDrawSurface(LPDIRECTDRAWSURFACE surface, HRGN hClipRgn)
  411. {
  412.     if (m_offScreenDC) {
  413.         if (hClipRgn == FE_NULL_REGION)    {
  414.             ::SelectClipRgn(m_offScreenDC, NULL);
  415.         }
  416.         else {
  417.             ::SelectClipRgn(m_offScreenDC, hClipRgn);
  418.         }
  419.     }
  420. }
  421.  
  422. void CWinCX::RestoreAllDrawSurface()
  423. {
  424. #ifdef XP_WIN32
  425.     if( m_lpDDSPrimary->Restore() == DD_OK ) {
  426.         if (m_lpDDSBack->Restore() == DD_OK) {
  427.             return;
  428.         }
  429.     }
  430.  
  431.     // if the surface can not be restore.
  432.     TRACE("There is something wrong with DirectDraw surface.\n");
  433.     ReleaseDrawSurface();
  434. #endif
  435. }
  436.  
  437. void CWinCX::ReleaseDrawSurface()
  438.     {
  439. #ifdef XP_WIN32
  440.         if (m_offScreenDC) {
  441.             ReleaseOffscreenSurfDC();
  442.             m_offScreenDC = 0;
  443.         }
  444.         if (m_pOffScreenClipper) {
  445.             m_pOffScreenClipper->Release();
  446.             m_pOffScreenClipper = NULL;
  447.         }
  448.         if (m_pClipper) {
  449.             m_pClipper->Release();
  450.             m_pClipper = NULL;
  451.         }
  452.         if (m_lpDDSPrimary) {
  453.             m_lpDDSPrimary->Release();
  454.             m_lpDDSPrimary = NULL;
  455.         }
  456.         if (m_lpDDSBack) {
  457.             m_lpDDSBack->Release();
  458.             m_lpDDSBack = NULL;
  459.         }
  460.         if (mg_pPal) {
  461.             mg_pPal->Release();
  462.             mg_pPal = NULL;
  463.         }
  464.         if (m_lpDD) {
  465.             m_lpDD->Release();
  466.             m_lpDD = NULL;
  467.         }
  468.         HDC hdc = GetContextDC();
  469.         CDCCX::SetUseDibPalColors(!IsPrintContext() && (::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE));
  470.         ReleaseContextDC(hdc);
  471. #endif  // WIN32
  472.     }
  473. #endif // DDRAW
  474.  
  475.  
  476.  
  477.  
  478. void CWinCX::ClearFrame()    {
  479.     m_pFrame = NULL;
  480.  
  481.     //    Go through all our immediate children, clearing
  482.     //        their frame.
  483.     //    They will in turn call thier children, if present.
  484.     MWContext *pChild;
  485.     XP_List *pTraverse = GetContext()->grid_children;
  486.     while (pChild = (MWContext*)XP_ListNextObject(pTraverse)) {
  487.         WINCX(pChild)->ClearFrame();
  488.     }
  489. }
  490. //    If we're a grid cell, we need to return the parent's palette.
  491. HPALETTE CWinCX::GetPalette() const    {
  492.     if(IsGridCell() == TRUE && GetParentContext() != NULL)    {
  493.         ASSERT(ABSTRACTCX(GetParentContext())->IsWindowContext());
  494.         return(WINCX(GetParentContext())->GetPalette());
  495.     }
  496.     //    Return the normal stuff.
  497.     return(CDCCX::GetPalette());
  498. }
  499.  
  500.  
  501. void CWinCX::DestroyContext()   {
  502.     if(IsDestroyed() == FALSE)  {
  503.         ResetToolTipImg();
  504.  
  505.         //  Deactivate any embedded items.
  506.         OnDeactivateEmbedCX();
  507.  
  508.         //    Release our modality if any is in effect.
  509.         POSITION rTraverse = m_cplModalOver.GetHeadPosition();
  510.         while(rTraverse)    {
  511.             HWND    hwndOwner;
  512.  
  513.             //    We stored the HWND of the window we're being modal over
  514.             //    Retrieve it.
  515.             hwndOwner = (HWND)m_cplModalOver.GetNext(rTraverse);
  516.             if (::IsWindow(hwndOwner)) {
  517.                 //  Must make sure no one else thinks they are modal over the
  518.                 //      window before we go off and enable it.
  519.                 int iTraverse = 1;
  520.                 BOOL bEnable = TRUE;
  521.                 MWContext *pMW = NULL;
  522.                 XP_List *pTraverse = XP_GetGlobalContextList();
  523.                 while (pMW = (MWContext *)XP_ListNextObject(pTraverse)) {
  524.                     if(ABSTRACTCX(pMW) && ABSTRACTCX(pMW)->IsWindowContext()) {
  525.                         CWinCX *pCX = WINCX(pMW);
  526.                         if(this == pCX) {
  527.                             //  Exclude ourselves from the check.
  528.                             continue;
  529.                         }
  530.                         POSITION rInsane = pCX->m_cplModalOver.GetHeadPosition();
  531.                         HWND hCheck = NULL;
  532.                         while(rInsane) {
  533.                             hCheck = (HWND)pCX->m_cplModalOver.GetNext(rInsane);
  534.                             if(hCheck == hwndOwner) {
  535.                                 //  Someone else will enable it later.
  536.                                 bEnable = FALSE;
  537.                                 break;
  538.                             }
  539.                         }
  540.                     }
  541.                     if(FALSE == bEnable) {
  542.                         //  No need to continue if decided already.
  543.                         break;
  544.                     }
  545.                 }
  546.                 if(bEnable) {
  547.                     ::EnableWindow(hwndOwner, TRUE);
  548.                 }
  549.             }
  550.         }
  551.         m_cplModalOver.RemoveAll();
  552.  
  553.         //    Perform our close callbacks.
  554.         if(!m_cplCloseCallbacks.IsEmpty())    {
  555.             POSITION rFuncs = m_cplCloseCallbacks.GetHeadPosition();
  556.             POSITION rArgs = m_cplCloseCallbackArgs.GetHeadPosition();
  557.             void (*pCloseCallback)(void *) = NULL;
  558.             void *pCloseCallbackArg = NULL;
  559.  
  560.             while(rFuncs)   {
  561.                 pCloseCallback = (void (*)(void *))m_cplCloseCallbacks.GetNext(rFuncs);
  562.                 pCloseCallbackArg = m_cplCloseCallbackArgs.GetNext(rArgs);
  563.  
  564.                 if(pCloseCallback != NULL)  {
  565.                     pCloseCallback(pCloseCallbackArg);
  566.                 }
  567.             }
  568.  
  569.             m_cplCloseCallbacks.RemoveAll();
  570.             m_cplCloseCallbackArgs.RemoveAll();
  571.         }
  572.  
  573.         MWContext *pContext = GetContext();
  574.  
  575.         //JavaScript has lifetime-linked windows which must close now too
  576.         if (pContext->js_dependent_list) {
  577.         MWContext *pDepContext;
  578.         XP_List *pTraverse = pContext->js_dependent_list;
  579.         while (pDepContext = (MWContext *)XP_ListNextObject(pTraverse)) {
  580.             pDepContext->js_parent = 0;
  581.             FE_DestroyWindow(pDepContext);
  582.         }
  583.         XP_ListDestroy(pContext->js_dependent_list);
  584.         pContext->js_dependent_list = NULL;
  585.         }
  586.         if (pContext->js_parent) {
  587.         if (XP_ListCount(pContext->js_parent->js_dependent_list) == 1) {
  588.             XP_ListDestroy(pContext->js_parent->js_dependent_list);
  589.             pContext->js_parent->js_dependent_list=NULL;
  590.         }
  591.         else {
  592.             XP_ListRemoveObject(pContext->js_parent->js_dependent_list, pContext);
  593.         }
  594.  
  595.         }
  596.  
  597.         //  Call the base.  This will delete the object !!
  598.         //  To make sure that m_pPal is not being selected to a dc
  599.         HDC hdc = GetContextDC();
  600.         ::SelectPalette(hdc,  (HPALETTE)::GetStockObject(DEFAULT_PALETTE), FALSE);
  601.         //  Get rid of the home grown DC that we created.
  602.         if(GetPane() != NULL)    {
  603.         #ifdef DDRAW
  604.             ReleaseDrawSurface();
  605.         #endif
  606.             ReleaseContextDC(hdc);
  607.         }
  608. #ifdef JAVA
  609.         //
  610.         // Discard the events pending for the context...
  611.         //
  612.         LJ_DiscardEventsForContext(pContext);
  613. #endif /* JAVA */
  614.     }
  615.     
  616.  
  617.     CPaneCX::DestroyContext();
  618.  
  619. }
  620.  
  621.  
  622. void CWinCX::OnDeactivateEmbedCX()  {
  623.     CGenericView *pView = GetView();
  624.     if(pView != NULL && m_pSelected != NULL) {
  625.         //    Obtain the plugin structure.
  626.         NPEmbeddedApp *pPluginShim = (NPEmbeddedApp *)m_pSelected->FE_Data;
  627.         //    Make sure it is not a plugin, but an OLE container item.
  628.         if(pPluginShim != NULL && wfe_IsTypePlugin(pPluginShim) == FALSE)    {
  629.             //    Get the container item, and deactivate it.
  630.             CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pPluginShim->fe_data;
  631.             if(pItem != NULL && pItem->IsInPlaceActive() == TRUE)   {
  632.                 TRY    {
  633.                     pItem->Deactivate();
  634.  
  635.                 }
  636.                 CATCH(CException, e)    {
  637.                     //    Something went wrong in OLE (other app down).
  638.                     //    No complicated handling here, just keep running.
  639.                 }
  640.                 END_CATCH
  641.             }
  642.         }
  643.         //    Clear that nothing is currently selected.
  644.         m_pSelected = NULL;
  645.     }
  646. }
  647.  
  648. #ifdef EDITOR
  649. void CWinCX::Scroll(int iBars, UINT uSBCode, UINT uPos, HWND hCtrl, UINT uTimes)
  650. {
  651.     int32 lOldOrgY = GetOriginY();
  652.     int32 lOldOrgX = GetOriginX();
  653.     
  654.     CPaneCX::Scroll(iBars, uSBCode, uPos, hCtrl, uTimes);
  655.     
  656.     if(lOldOrgY != GetOriginY() || lOldOrgX != GetOriginX()) {
  657.         if( EDT_IS_EDITOR(GetContext()) ){
  658.             EDT_WindowScrolled( GetContext() );
  659.         }
  660.     }
  661. }
  662. #endif
  663.  
  664.  
  665. #ifdef DDRAW
  666. void CWinCX::ScrollWindow(int x, int y) 
  667. {
  668.     RECT source, dest;
  669.     dest.top = m_physicWinRect.top;
  670.     dest.bottom = m_physicWinRect.bottom;
  671.     dest.left = m_physicWinRect.left;
  672.     dest.right = m_physicWinRect.right;
  673.     source.top = m_physicWinRect.top;
  674.     source.bottom = m_physicWinRect.bottom;
  675.     source.left = m_physicWinRect.left;
  676.     source.right = m_physicWinRect.right;
  677.     RECT updateRect;
  678.     updateRect.top = m_physicWinRect.top;
  679.     updateRect.bottom = m_physicWinRect.bottom;
  680.     updateRect.left = m_physicWinRect.left;
  681.     updateRect.right = m_physicWinRect.right;
  682.  
  683.     if (y == 0) { // scrolling horz
  684.         if (x > 0) {// scroll right.
  685.             dest.left += x;
  686.             source.right -= x;
  687.         }
  688.         else {
  689.             dest.right += x;
  690.             source.left -= x;
  691.         }
  692.         if (m_physicWinRect.left == dest.left) {
  693.             updateRect.left = dest.right;
  694.         }
  695.         else
  696.             updateRect.left = m_physicWinRect.left;
  697.         updateRect.right = updateRect.left + abs(x);
  698.     }
  699.     else if (x == 0) { // scroll vert.
  700.         if (y > 0) {// scroll down.
  701.             dest.top += y;
  702.             source.bottom -= y;
  703.         }
  704.         else {
  705.             dest.bottom += y;
  706.             source.top -= y;
  707.         }
  708.         if (m_physicWinRect.top == dest.top) {
  709.             updateRect.top = dest.bottom;
  710.         }
  711.         else
  712.             updateRect.top = m_physicWinRect.top;
  713.         updateRect.bottom = updateRect.top + abs(y);
  714.     }
  715.     if (y < 0 || x < 0) {
  716.         if(IsVScrollBarOn() ) { 
  717.             updateRect.left -= sysInfo.m_iScrollWidth;
  718.             updateRect.right -= sysInfo.m_iScrollWidth;
  719.         }
  720.          if(IsHScrollBarOn()) {
  721.             updateRect.top -= sysInfo.m_iScrollWidth;
  722.             updateRect.bottom -= sysInfo.m_iScrollWidth;
  723.         }
  724.     }
  725.     ::OffsetRect(&updateRect, -GetWindowsXPos(), -GetWindowsYPos());
  726.       HRESULT err = m_lpDDSBack->ReleaseDC(m_offScreenDC);
  727.     ::OffsetRect(&dest, -GetWindowsXPos(), -GetWindowsYPos());
  728.     err = m_lpDDSBack->Blt(&dest, m_lpDDSPrimary, &source, DDBLT_WAIT, NULL);
  729.     if (err == DDERR_SURFACELOST) {
  730.         RestoreAllDrawSurface();
  731.         err = m_lpDDSBack->Blt(&dest, m_lpDDSPrimary, &source, DDBLT_WAIT, NULL);
  732.     }
  733.     m_lpDDSBack->GetDC(&m_offScreenDC);
  734.  
  735.     m_ScrollWindow = TRUE;
  736. #ifdef DEBUG_mhwang
  737.     TRACE("Scroll Window\n");
  738. #endif
  739.     m_pAlternateDC = m_offScreenDC;
  740.     RefreshArea(m_offScreenDC, updateRect.left + m_lOrgX, updateRect.top + m_lOrgY, 
  741.                     updateRect.right - updateRect.left,
  742.                     updateRect.bottom - updateRect.top);
  743.     RECT prcUpdate;
  744. //    ::ScrollWindowEx(GetPane(), x, (int) y, NULL, NULL, NULL, &prcUpdate, SW_SCROLLCHILDREN);
  745.     if (m_lpDDSPrimary ) {
  746.         LTRB rect(m_physicWinRect);
  747.         rect.left -= GetWindowsXPos();
  748.         rect.right -= GetWindowsXPos();
  749.         rect.top -= GetWindowsYPos();
  750.         rect.bottom -= GetWindowsYPos();
  751.         FE_Region hCurClip = GetDrawingClip();
  752.         HDC hdc;
  753.         m_lpDDSPrimary->GetDC(&hdc);
  754.         ::SelectClipRgn(hdc, NULL);
  755.         m_lpDDSPrimary->ReleaseDC(hdc);
  756.         BltToScreen(rect, NULL);
  757.     }
  758.     m_pAlternateDC = 0;
  759.     m_ScrollWindow = FALSE;
  760. }
  761. #endif
  762. //    This function get's called when the window moves around.
  763. void CWinCX::OnMoveCX()    {
  764.     //  WARNING:m_crWindowRect will be invalid until next AftWMSize!
  765.  
  766.     //    Go through all our immediate children, telling them their screen location
  767.     //        has changed.
  768.     //    They will in turn call thier children, if present.
  769.     MWContext *pChild;
  770.     XP_List *pTraverse = GetContext()->grid_children;
  771.     while (pChild = (MWContext*)XP_ListNextObject(pTraverse)) {
  772.         WINCX(pChild)->OnMoveCX();
  773.     }
  774.     JSEvent *event;
  775.     event = XP_NEW_ZAP(JSEvent);
  776.     event->type = EVENT_MOVE;
  777.  
  778.     CFrameWnd *pFWnd = GetFrame()->GetFrameWnd();
  779.     if(pFWnd) {
  780.         CRect crFrame;
  781.         pFWnd->GetWindowRect(crFrame);
  782.         event->x = (int32)crFrame.left;
  783.         event->y = (int32)crFrame.top;
  784.         event->screenx = (int32)crFrame.left;
  785.         event->screeny = (int32)crFrame.top;
  786.         ET_SendEvent(GetContext(), 0, event,
  787.                      0, 0);
  788.     }
  789. #ifdef DDRAW
  790.     CalcWinPos();
  791. #endif
  792. }
  793.  
  794. static void
  795. wfe_ResizeFullPagePlugin(MWContext* pContext, int32 lWidth, int32 lHeight)
  796. {
  797.     ASSERT(pContext);
  798.     NPWindow* npWindow = pContext->pluginList->wdata;
  799.  
  800.     ASSERT(npWindow);
  801.     if (npWindow) {
  802.         npWindow->width = lWidth;
  803.         npWindow->height = lHeight;
  804.         ::SetWindowPos((HWND)npWindow->window,
  805.             NULL,
  806.             0,
  807.             0,
  808.             (int)npWindow->width,
  809.             (int)npWindow->height,
  810.             SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
  811.         NPL_EmbedSize(pContext->pluginList);
  812.     }
  813. }
  814.  
  815. #ifdef DDRAW
  816. void CWinCX::CreateAndLockOffscreenSurface(RECT& rect)
  817. {
  818.     // create new offscreen surface.
  819.     if (m_lpDDSPrimary) {
  820.         if (m_lpDDSBack) {
  821.             m_lpDDSBack->ReleaseDC(m_offScreenDC);
  822.             m_offScreenDC = 0;
  823.             m_lpDDSBack->Release();
  824.         }
  825.         m_lpDDSBack = CreateOffscreenSurface(rect);
  826.         RestoreAllDrawSurface();
  827.         if (m_lpDDSBack)
  828.             m_lpDDSBack->GetDC(&m_offScreenDC);
  829.     }
  830. }
  831.  
  832. LPDIRECTDRAWSURFACE CWinCX::CreateOffscreenSurface(RECT& rect)
  833. {
  834.     LPDIRECTDRAWSURFACE retval;
  835.     // create new offscreen surface.
  836.     ZeroMemory((void*)&ddsd, sizeof(DDSURFACEDESC));
  837.     ddsd.dwSize = sizeof( ddsd );
  838.     // Create a offscreen bitmap.
  839.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  840.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  841.     ddsd.dwHeight = rect.bottom - rect.top;
  842.     ddsd.dwWidth = rect.right - rect.left;
  843.     if (m_lpDD->CreateSurface( &ddsd, &retval, NULL )!=DD_OK) { 
  844.         ReleaseDrawSurface();
  845.         return NULL;
  846.     }
  847.     else 
  848.         return retval;
  849. }
  850. #endif
  851.  
  852. void CWinCX::AftWMSize(PaneMessage *pMessage)
  853. {
  854. //  Purpose:    Informs the context that the size of the displayable area has changed.
  855. //  Arguments:  As OnSize in MFC
  856. //  Returns:    void
  857. //  Comments:   Pretty much handles every want of a resizeable window.
  858. //  Revision History:
  859. //      07-13-95    created GABby
  860. //
  861.  
  862.     //  Call the base.
  863.     //  Preserve old size for logic in this function.
  864.     int32 lOldWidth = GetWidth();
  865.     int32 lOldHeight = GetHeight();
  866.     CPaneCX::AftWMSize(pMessage);
  867.  
  868.     UINT uType = (UINT)pMessage->wParam;
  869.     int iX = LOWORD(pMessage->lParam);
  870.     int iY = HIWORD(pMessage->lParam);
  871.  
  872.     //  Wether or not we should call NiceReload before we return from this function.
  873.     //  We stall the call, as we need to update all of our state size variables
  874.     //      before we start a load which may depend upon these state variables
  875.     //      to be correct for display purposes and for turning on and off scroll
  876.     //      bars etc.
  877.     BOOL bNiceReload = FALSE;
  878.  
  879.     //  Block flailing random message we receive when a new browser
  880.     //      window is opened and we're minimized.
  881.     if(GetFrame() && GetFrame()->GetFrameWnd() &&
  882.         GetFrame()->GetFrameWnd()->IsIconic() &&
  883.         uType == 0 && iX == 0 && iY == 0)    {
  884.         //  Stop the stupid windows behavior.
  885.         return;
  886.     }
  887.  
  888.     // There is no window.
  889.     if(!GetPane() )
  890.         return;
  891.  
  892.     //    Update our idea of where we exist.
  893.     CRect crNewRect(0, 0, 0, 0);
  894.     ::GetWindowRect(GetPane(), crNewRect);
  895.  
  896. #ifdef DDRAW
  897.     // create new offscreen surface.
  898.     if (m_lpDDSPrimary) {
  899.         CreateAndLockOffscreenSurface(crNewRect);
  900.     }
  901.  
  902.     // mwh - reset our windows's screen position.  so it will be calcuate
  903.     // in DisplayPixmap again.
  904.     m_physicWinRect.Empty();
  905. #endif
  906.     if(IsGridCell() && !m_crWindowRect.EqualRect(crNewRect))    {
  907.         //  NCAPI sizing support.
  908.         CWindowChangeItem::Sizing(GetContextID(), crNewRect.left, crNewRect.top, crNewRect.Width(), crNewRect.Height());
  909.     }
  910.  
  911.     //    Don't do this on anything but restoration and maximization.
  912.     //    We don't care if we're minimized.
  913.     if(uType != SIZE_MAXIMIZED && uType != SIZE_RESTORED)    {
  914.         TRACE("Don't handle size messages of type %u\n", uType);
  915.         return;
  916.     }
  917.  
  918.     //  Update what our document thinks if In Place.
  919.     if(GetDocument() && GetDocument()->IsInPlaceActive() && GetPane())   {
  920.         int32 lIPWidth = Twips2MetricX(iX);
  921.         int32 lIPHeight = Twips2MetricY(iY);
  922.  
  923.         //  quasi-hack alert.
  924.         //  When the scroll bars are on, our twips to metrics conversions
  925.         //      are off by 1 pixel in the direction of the scroller.
  926.         //  Adjust.
  927.         //  This seems reverse logic, but is correct (horiz scroll bar
  928.         //      shortens height of window when present).
  929.         if(IsHScrollBarOn()) {            
  930.             lIPHeight -= Twips2MetricX(1);
  931.         }
  932.         if(IsVScrollBarOn())    {
  933.             lIPWidth -= Twips2MetricY(1);
  934.         }
  935.  
  936.         GetDocument()->m_csViewExtent = CSize(CASTINT(lIPWidth), CASTINT(lIPHeight));
  937.         TRACE("InPlace Document extents now %ld,%ld\n", lIPWidth, lIPHeight);
  938.     }
  939.  
  940.     CGenericView *pView = GetView();
  941.     ASSERT(pView);
  942.     
  943.     //  We can never allow resize when there are frame cells and we are in
  944.     //      print preview.  The print preview state holds a pointer to
  945.     //      one of the views in the frameset.  Once print preview is
  946.     //      completed, the code will attempt to set that view to be the
  947.     //      active view.  If deleted (as from a reload/resize), then we crash.
  948.     //  Also, if only the Y value changed, then just adjust the iHeight.
  949.     //      This doesn't apply to grid parents OR Composer, as they need to reload in
  950.     //      all resize cases.
  951.     if( !EDT_IS_EDITOR(GetContext()) &&
  952.          ((IsGridParent() && pView->IsInPrintPreview()) ||
  953.          (GetWidth() == lOldWidth && IsGridParent() == FALSE))
  954.     ) {
  955.         if(ContainsFullPagePlugin()) {
  956.             wfe_ResizeFullPagePlugin(GetContext(), GetWidth(), GetHeight());
  957.         }
  958.  
  959.         {
  960.             MWContext *context = GetContext();
  961.  
  962.             /* Mark the entire window dirty and force the compositor to composite now for
  963.                the case when the user resizes the top or bottom edge of the window. 
  964.                This can be a potential performance problem!.  Be careful.
  965.             */
  966.             if (context->compositor && GetHeight() != lOldHeight)
  967.             {
  968.                 CL_Compositor *compositor = context->compositor;
  969.                 XP_Rect rect;
  970.                 CL_OffscreenMode save_offscreen_mode;
  971.         
  972.                 rect.left = 0;
  973.                 rect.top = 0;
  974.                 rect.right = GetWidth();
  975.                 rect.bottom = GetHeight();
  976.                 CL_UpdateDocumentRect(compositor,
  977.                                       &rect, (PRBool)FALSE);
  978.  
  979.                 /*    Temporarily force drawing to use the offscreen buffering area to reduce
  980.                     flicker when resizing. (If no offscreen store is allocated, this code will
  981.                     have no effect, but it will do no harm.) */
  982.                 save_offscreen_mode = CL_GetCompositorOffscreenDrawing(compositor);
  983.                 CL_SetCompositorOffscreenDrawing(compositor, CL_OFFSCREEN_ENABLED);
  984.                 CL_CompositeNow(compositor);
  985.                 CL_SetCompositorOffscreenDrawing(compositor, save_offscreen_mode);
  986.  
  987.                 /*    Call Win32 API call to validate entire windows so that the WM_PAINT message
  988.                     that follows a resize does not force a repaint of the window.  The repaint
  989.                     happens via the compositor in the CL_UpdateDocumentRect call above */
  990.                 ::ValidateRect( GetPane(), NULL );
  991.             }                        
  992.         }
  993.  
  994.         return;
  995.     }
  996.  
  997.     //  Check the history to see if what we have is a binary image,
  998.     //      or if this is a view-source URL.
  999.     //  Don't reload if this is the case.
  1000.     History_entry *pEntry = SHIST_GetCurrent(&(GetContext()->hist));
  1001.     if(pEntry != NULL &&
  1002.         (pEntry->is_binary ||
  1003.         (pEntry->address && 0 == strncmp(pEntry->address, "view-source:", 12)))) {
  1004.         if(ContainsFullPagePlugin()) {
  1005.             // There can be only one plugin if it is full page
  1006.             wfe_ResizeFullPagePlugin(GetContext(), GetWidth(), GetHeight());
  1007.         }
  1008.         return;
  1009.     }
  1010.     //  Have any embedded items update.
  1011.     CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)GetDocument()->GetInPlaceActiveItem(pView);
  1012.     if(pItem != NULL)   {
  1013.         pItem->SetItemRects();
  1014.     }
  1015.  
  1016. #ifdef EDITOR
  1017.     if( EDT_IS_EDITOR(GetContext()) ){
  1018.         EDT_RefreshLayout( GetContext() );
  1019.     }
  1020.     else 
  1021. #endif // EDITOR
  1022.     {
  1023.         // If this is edit_view_source, then we can't reload because the 
  1024.         //  data didn't come from an acutal URL
  1025.         if( !GetContext()->edit_view_source_hack ){
  1026.             //  Reload, we need to relayout everything to the new dimenstions.
  1027.             if(m_crWindowRect.Width() != crNewRect.Width() ||
  1028.                 m_crWindowRect.Height() != crNewRect.Height()) {
  1029.                 bNiceReload = TRUE;
  1030.             }
  1031.         }
  1032.     }
  1033.     m_crWindowRect = crNewRect;
  1034.     
  1035.     //  Now that all variables are updated and in sync, we can call
  1036.     //      NiceReload if needed.
  1037.     if(bNiceReload && XP_DOCID(GetDocumentContext())) {
  1038.         /* MWContext *context = GetContext(); */
  1039.  
  1040.     //    Instead of re-loading from scratch, we want to pass new width, height of window 
  1041.     //    to the re-layout routine.
  1042.         LO_RelayoutOnResize(GetDocumentContext(), GetWidth(), GetHeight(), m_lLeftMargin, m_lTopMargin);
  1043.  
  1044.         /* Call Win32 API call to validate entire window so that the WM_PAINT message
  1045.            that follows a resize does not force a repaint of the window.  The repaint
  1046.            happens in the LO_RelayoutOnResize call above */
  1047.         ::ValidateRect( GetPane(), NULL );
  1048.  
  1049.         /*
  1050.         NiceResizeReload();
  1051.         */
  1052.     }
  1053. }
  1054.  
  1055. #ifdef EDITOR
  1056. void CWinCX::PreWMErasebkgnd(PaneMessage *pMessage)
  1057. {
  1058.     MWContext *pMWContext = GetContext();
  1059.     if( pMWContext && EDT_IS_EDITOR(pMWContext) ){
  1060.         WFE_HideEditCaret(pMWContext);
  1061.     }
  1062.  
  1063.     CPaneCX::PreWMErasebkgnd(pMessage);
  1064.  
  1065.     if( pMWContext && EDT_IS_EDITOR(pMWContext) ){
  1066.         WFE_ShowEditCaret(pMWContext);
  1067.     }
  1068. }
  1069. #endif
  1070.  
  1071. BOOL CWinCX::EraseTextBkgnd(HDC pDC, RECT& cRect, LO_TextStruct* pText)
  1072. {
  1073.     // If there's a background color specified then use it
  1074.     return CDCCX::_EraseBkgnd(pDC, cRect, GetOriginX(), GetOriginY(), 
  1075.                        pText->text_attr->no_background ? NULL : &pText->text_attr->bg);
  1076. }
  1077.  
  1078. #ifdef LAYERS
  1079. BOOL CWinCX::HandleLayerEvent(CL_Layer * pLayer, CL_Event * pEvent)
  1080. {
  1081.     XY point(pEvent->x, pEvent->y); // Event location, in layer coordinates
  1082.     BOOL bReturn = TRUE;
  1083.     fe_EventStruct *pFEEvent = (fe_EventStruct *)pEvent->fe_event;
  1084.     UINT uFlags, nFlags, nRepCnt, nChar;
  1085.     CPoint cpPoint;             // Event location, in screen coordinates
  1086.     LO_Element *pElement;
  1087.     CFormElement * pFormElement;    
  1088.  
  1089.     if (CL_IS_MOUSE_EVENT(pEvent)) {
  1090.         if (pFEEvent) {
  1091.             uFlags = pFEEvent->uFlags;
  1092.             cpPoint.x = pFEEvent->x;
  1093.         cpPoint.y = pFEEvent->y;
  1094.         }
  1095.         else {
  1096.             // This is a synthesized event and we need to fill in
  1097.             // the FE part. We can just used the uFlags from the
  1098.             // previous mouse event. Should we know all the information
  1099.             // to create the cpPoint?
  1100.             uFlags = m_uMouseFlags;
  1101.             int32 layer_x_offset = CL_GetLayerXOrigin(pLayer);
  1102.             int32 layer_y_offset = CL_GetLayerYOrigin(pLayer);
  1103.             cpPoint.x = CASTINT(pEvent->x + layer_x_offset - m_lOrgX);
  1104.             cpPoint.y = CASTINT(pEvent->y + layer_y_offset - m_lOrgY);
  1105.         }
  1106.     }
  1107.  
  1108.     if (CL_IS_KEY_EVENT(pEvent)) {
  1109.         if (pFEEvent) {
  1110.         nFlags = HIWORD(pFEEvent->fe_modifiers);
  1111.         nRepCnt = LOWORD(pFEEvent->fe_modifiers);
  1112.         nChar = pFEEvent->nChar;
  1113.         }
  1114.     }
  1115.    
  1116.     switch(pEvent->type) {
  1117.         case CL_EVENT_MOUSE_BUTTON_DOWN:
  1118.             if (pEvent->which == 1)
  1119.                 OnLButtonDownForLayerCX(uFlags, cpPoint, point, pLayer);
  1120.             // The right button is passed to the view for popup stuff
  1121.             else if (pEvent->which == 3) {
  1122.                 if(!OnRButtonDownForLayerCX(uFlags, cpPoint, 
  1123.                                 point, pLayer)) {   
  1124.                     CGenericView *pView = GetView();
  1125.                     if(pView)   {
  1126.                     bReturn = pView->OnRButtonDownForLayer(uFlags, cpPoint, 
  1127.                                         point.x, point.y,
  1128.                                         pLayer);
  1129.                     }
  1130.                 }
  1131.             }
  1132.             break;
  1133.         case CL_EVENT_MOUSE_BUTTON_UP:
  1134.             if (pEvent->which == 1)
  1135.                 OnLButtonUpForLayerCX(uFlags, cpPoint, point, pLayer, pFEEvent->pbReturnImmediately);
  1136.             else if (pEvent->which == 3) 
  1137.                 OnRButtonUpForLayerCX(uFlags, cpPoint, point, pLayer);
  1138.             break;
  1139.         case CL_EVENT_MOUSE_MOVE:
  1140.                     OnMouseMoveForLayerCX(uFlags, cpPoint, point, pLayer, pFEEvent->pbReturnImmediately);
  1141.             break;
  1142.         case CL_EVENT_MOUSE_BUTTON_MULTI_CLICK:
  1143.             if (pEvent->which == 1)
  1144.                 OnLButtonDblClkForLayerCX(uFlags, cpPoint, point, pLayer);
  1145.             else if (pEvent->which == 3) 
  1146.                 OnRButtonDblClkForLayerCX(uFlags, cpPoint, point, pLayer);
  1147.             break;
  1148.         case CL_EVENT_KEY_FOCUS_GAINED:
  1149.             bReturn = TRUE;
  1150.             break;
  1151.         case CL_EVENT_KEY_UP:
  1152.         pElement = GetLayoutElement(point, pLayer);
  1153.         // Check for form element and send event back to form element's class.
  1154.         if (pElement != NULL && pElement->type == LO_FORM_ELE && pFEEvent->x == 1) {
  1155.         switch (pElement->lo_form.element_data->type) {
  1156.             case FORM_TYPE_TEXT:
  1157.             case FORM_TYPE_PASSWORD:
  1158.             case FORM_TYPE_TEXTAREA:
  1159.             case FORM_TYPE_FILE:
  1160.             pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  1161.             ((CNetscapeEdit *)CEdit::FromHandlePermanent(pFormElement->GetRaw()))->OnEditKeyEvent(pEvent->type, pEvent->which, nRepCnt, nFlags);
  1162.             break;
  1163.             default:
  1164.             break;
  1165.         }
  1166.         } 
  1167.         break;
  1168.         case CL_EVENT_KEY_DOWN:
  1169.         pElement = GetLayoutElement(point, pLayer);
  1170.         // Check for form element and send event back to form element's class.
  1171.         if (pElement != NULL && pElement->type == LO_FORM_ELE && pFEEvent->x == 1) {
  1172.         switch (pElement->lo_form.element_data->type) {
  1173.             case FORM_TYPE_TEXT:
  1174.             case FORM_TYPE_PASSWORD:
  1175.             case FORM_TYPE_TEXTAREA:
  1176.             case FORM_TYPE_FILE:
  1177.             pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  1178.             ((CNetscapeEdit *)CEdit::FromHandlePermanent(pFormElement->GetRaw()))->OnEditKeyEvent(pEvent->type, pEvent->which, nRepCnt, nFlags);
  1179.             break;
  1180.             default:
  1181.             break;
  1182.         }
  1183.         }
  1184.         else {
  1185.         switch(nChar) {
  1186.             case ' ':
  1187.             case VK_NEXT:
  1188.             // page down
  1189.             Scroll(SB_VERT, SB_PAGEDOWN, 0, NULL);
  1190.             break;
  1191.             case VK_BACK:
  1192.             case VK_PRIOR:
  1193.             // page up
  1194.             Scroll(SB_VERT, SB_PAGEUP, 0, NULL);
  1195.             break;
  1196.             case VK_UP:
  1197.             // line up
  1198.             Scroll(SB_VERT, SB_LINEUP, 0, NULL);
  1199.             break;
  1200.             case VK_DOWN:
  1201.             // line down
  1202.             Scroll(SB_VERT, SB_LINEDOWN, 0, NULL);
  1203.             break;
  1204.             case VK_RIGHT:
  1205.             // line right
  1206.             Scroll(SB_HORZ, SB_LINERIGHT, 0, NULL);
  1207.             break;
  1208.             case VK_LEFT:
  1209.             // line left
  1210.             Scroll(SB_HORZ, SB_LINELEFT, 0, NULL);
  1211.             break;
  1212.             case VK_HOME:
  1213.                 if (::GetKeyState(VK_CONTROL) < 0)
  1214.                     Scroll(SB_VERT, SB_TOP, 0, NULL);
  1215.                 else
  1216.                     Scroll(SB_HORZ, SB_TOP, 0, NULL);
  1217.                 break;
  1218.             case VK_END:
  1219.                 if (::GetKeyState(VK_CONTROL) < 0)
  1220.                     Scroll(SB_VERT, SB_BOTTOM, 0, NULL);
  1221.                 else
  1222.                     Scroll(SB_HORZ, SB_BOTTOM, 0, NULL);
  1223.                 break;
  1224.  
  1225.             case VK_ESCAPE:
  1226.                 //  escape, kill off any selected items.
  1227.                 if(m_pSelected != NULL) {
  1228.                 OnDeactivateEmbedCX();
  1229.                 }
  1230.             break;
  1231.             default:
  1232.             break;
  1233.         }
  1234.         }
  1235.         break;
  1236.         case CL_EVENT_KEY_FOCUS_LOST:
  1237.         default:
  1238.             bReturn = FALSE;
  1239.             break;
  1240.     }
  1241.  
  1242.     return bReturn;
  1243. }
  1244.  
  1245. BOOL CWinCX::HandleEmbedEvent(LO_EmbedStruct *embed, CL_Event *pEvent)
  1246. {
  1247.     NPEvent npEvent;
  1248.     fe_EventStruct *pFEEvent = (fe_EventStruct *)pEvent->fe_event;
  1249.     NPEmbeddedApp *pEmbeddedApp = (NPEmbeddedApp *)embed->FE_Data;
  1250.  
  1251.     if (CL_IS_MOUSE_EVENT(pEvent)) {
  1252.         if (pFEEvent)
  1253.             npEvent.wParam = pFEEvent->uFlags;
  1254.         else 
  1255.             npEvent.wParam = m_uMouseFlags;
  1256.         
  1257.         npEvent.lParam = MAKELONG(pEvent->x, pEvent->y);
  1258.     }
  1259.     else if (CL_IS_KEY_EVENT(pEvent)) {
  1260.         npEvent.wParam = (uint32)pEvent->which;
  1261.         npEvent.lParam = (uint32)pEvent->modifiers;
  1262.     }
  1263.     else if (pEvent->type == CL_EVENT_MOUSE_ENTER) {
  1264.         npEvent.wParam = 0;
  1265.         npEvent.lParam = MAKELONG(HTCLIENT, 0);
  1266.     }
  1267.     else {
  1268.         npEvent.wParam = 0;
  1269.         npEvent.lParam = 0;
  1270.     }
  1271.    
  1272.     switch(pEvent->type) {
  1273.         case CL_EVENT_MOUSE_BUTTON_DOWN:
  1274.             if (pEvent->which == 1) {
  1275.                 npEvent.event = WM_LBUTTONDOWN;
  1276.             }
  1277.             else if (pEvent->which == 2)
  1278.                 npEvent.event = WM_MBUTTONDOWN;
  1279.             else
  1280.                 npEvent.event = WM_RBUTTONDOWN;
  1281.             break;
  1282.         case CL_EVENT_MOUSE_BUTTON_UP:
  1283.             if (pEvent->which == 1)
  1284.                 npEvent.event = WM_LBUTTONUP;
  1285.             else if (pEvent->which == 2)
  1286.                 npEvent.event = WM_MBUTTONUP;
  1287.             else
  1288.                 npEvent.event = WM_RBUTTONUP;
  1289.             break;
  1290.         case CL_EVENT_MOUSE_MOVE:
  1291.             npEvent.event = WM_MOUSEMOVE;
  1292.             break;
  1293.         case CL_EVENT_MOUSE_BUTTON_MULTI_CLICK:
  1294.             if (pEvent->which == 1)
  1295.                 npEvent.event = WM_LBUTTONDBLCLK;
  1296.             else if (pEvent->which == 2)
  1297.                 npEvent.event = WM_MBUTTONDBLCLK;
  1298.             else
  1299.                 npEvent.event = WM_RBUTTONDBLCLK;
  1300.             break;
  1301.         case CL_EVENT_KEY_UP:
  1302.             npEvent.event = WM_KEYUP;
  1303.             break;
  1304.         case CL_EVENT_KEY_DOWN:
  1305.             npEvent.event = WM_KEYDOWN;
  1306.             break;
  1307.         case CL_EVENT_MOUSE_ENTER:
  1308.             npEvent.event = WM_SETCURSOR;
  1309.             break;
  1310.         case CL_EVENT_KEY_FOCUS_GAINED:
  1311.             npEvent.event = WM_SETFOCUS;
  1312.             break;
  1313.         case CL_EVENT_KEY_FOCUS_LOST:
  1314.             npEvent.event = WM_KILLFOCUS;
  1315.             break;
  1316.         default:
  1317.             return FALSE;
  1318.     }
  1319.     
  1320.     return (BOOL)NPL_HandleEvent(pEmbeddedApp, &npEvent, (void*)npEvent.wParam);
  1321. }
  1322. #endif /* LAYERS */
  1323.  
  1324. BOOL CWinCX::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  1325. {
  1326.     BOOL bReturn = FALSE;
  1327.     
  1328.     //    Don't continue if this context is destroyed.
  1329.     if(IsDestroyed())    {
  1330.         return bReturn;
  1331.     }
  1332.  
  1333. #ifdef LAYERS
  1334.     /* 
  1335.      * If there's a compositor and someone has keyboard focus.
  1336.      * Note that if noone has event focus, we set the event focus
  1337.      * to the main document.
  1338.      */
  1339.     if (GetContext()->compositor) {
  1340.     if (CL_IsKeyEventGrabber(GetContext()->compositor, NULL) && 
  1341.         CL_GetCompositorRoot(GetContext()->compositor)) {
  1342.  
  1343.         CL_GrabKeyEvents(GetContext()->compositor, CL_GetLayerChildByName(
  1344.         CL_GetCompositorRoot(GetContext()->compositor), LO_BODY_LAYER_NAME));
  1345.     }
  1346.  
  1347.     if (!CL_IsKeyEventGrabber(GetContext()->compositor, NULL)) {
  1348.  
  1349.         CL_Event event;
  1350.         fe_EventStruct fe_event;
  1351.  
  1352.         //    Convert the point to something we understand.
  1353.         XY Point;
  1354.         WORD asciiChar = 0;
  1355.          
  1356.         ResolvePoint(Point, m_cpMMove);
  1357.  
  1358.         if (!EDT_IS_EDITOR(GetContext())) {
  1359.             BYTE kbstate[256];
  1360.             GetKeyboardState(kbstate);
  1361. #ifdef WIN32    
  1362.             ToAscii(nChar, nFlags & 0xff, kbstate, &asciiChar, 0);
  1363. #else
  1364.             ToAscii(nChar, nFlags & 0xff, kbstate, (DWORD*)&asciiChar, 0);
  1365. #endif
  1366.         }
  1367.  
  1368.         fe_event.fe_modifiers = MAKELONG(nRepCnt, nFlags);        
  1369.         fe_event.nChar = nChar;
  1370.         fe_event.x = 0;
  1371.  
  1372.         event.type = CL_EVENT_KEY_UP;
  1373.         event.fe_event = (void *)&fe_event;
  1374.         event.fe_event_size = sizeof(fe_EventStruct);
  1375.         event.which = asciiChar;
  1376.         event.modifiers = (GetKeyState(VK_SHIFT) < 0 ? EVENT_SHIFT_MASK : 0) 
  1377.                 | (GetKeyState(VK_CONTROL) < 0 ? EVENT_CONTROL_MASK : 0) 
  1378.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  1379.         event.x = Point.x;
  1380.         event.y = Point.y;
  1381.     
  1382.         bReturn = (BOOL)CL_DispatchEvent(GetContext()->compositor, &event);
  1383.     }
  1384.     }
  1385. #endif /* LAYERS */
  1386.  
  1387.     return bReturn;
  1388. }
  1389.  
  1390. BOOL CWinCX::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  1391. {
  1392.     BOOL bReturn = FALSE;
  1393.     
  1394.     //    Don't continue if this context is destroyed.
  1395.     if(IsDestroyed())    {
  1396.         return bReturn;
  1397.     }
  1398.  
  1399. #ifdef LAYERS
  1400.     /* 
  1401.      * If there's a compositor and someone has keyboard focus.
  1402.      * Note that if noone has event focus, we set the event focus
  1403.      * to the main document.
  1404.      */
  1405.     if (GetContext()->compositor) {
  1406.     if (CL_IsKeyEventGrabber(GetContext()->compositor, NULL) && 
  1407.         CL_GetCompositorRoot(GetContext()->compositor)) {
  1408.  
  1409.         CL_GrabKeyEvents(GetContext()->compositor, CL_GetLayerChildByName(
  1410.         CL_GetCompositorRoot(GetContext()->compositor), LO_BODY_LAYER_NAME));
  1411.  
  1412.     }
  1413.     
  1414.     if (!CL_IsKeyEventGrabber(GetContext()->compositor, NULL)) {
  1415.  
  1416.         CL_Event event;
  1417.         fe_EventStruct fe_event;
  1418.  
  1419.         //    Convert the point to something we understand.
  1420.         XY Point;
  1421.         WORD asciiChar = 0;
  1422.          
  1423.         ResolvePoint(Point, m_cpMMove);
  1424.  
  1425.         if (!EDT_IS_EDITOR(GetContext())) {
  1426.             BYTE kbstate[256];
  1427.             GetKeyboardState(kbstate);
  1428. #ifdef WIN32    
  1429.             ToAscii(nChar, nFlags & 0xff, kbstate, &asciiChar, 0);
  1430. #else
  1431.             ToAscii(nChar, nFlags & 0xff, kbstate, (DWORD*)&asciiChar, 0);
  1432. #endif
  1433.         }
  1434.  
  1435.         
  1436.         fe_event.fe_modifiers = MAKELONG(nRepCnt, nFlags);        
  1437.         fe_event.nChar = nChar;
  1438.         fe_event.x = 0;
  1439.  
  1440.         event.type = CL_EVENT_KEY_DOWN;
  1441.         event.fe_event = (void *)&fe_event;
  1442.         event.fe_event_size = sizeof(fe_EventStruct);
  1443.         event.which = asciiChar;
  1444.         event.modifiers = (GetKeyState(VK_SHIFT) < 0 ? EVENT_SHIFT_MASK : 0) 
  1445.                 | (GetKeyState(VK_CONTROL) < 0 ? EVENT_CONTROL_MASK : 0) 
  1446.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  1447.         event.x = Point.x;
  1448.         event.y = Point.y;
  1449.         event.data = nFlags>>14 & 1;//Bit represeting key repetition
  1450.  
  1451.         bReturn = (BOOL)CL_DispatchEvent(GetContext()->compositor, &event);
  1452.     }
  1453.     }
  1454. #endif /* LAYERS */
  1455.  
  1456.     return bReturn;
  1457. }
  1458.  
  1459. void CWinCX::OnLButtonDblClkCX(UINT uFlags, CPoint cpPoint)    {
  1460.     //    Only do this if clicking is enabled.
  1461.     if(IsClickingEnabled() == FALSE)    {
  1462.         return;
  1463.     }
  1464.  
  1465.     //    Don't continue if this context is destroyed.
  1466.     if(IsDestroyed())    {
  1467.         return;
  1468.     }
  1469.  
  1470.     //    Remember....
  1471.     m_LastMouseEvent = m_LBDClick;
  1472.     m_cpLBDClick = cpPoint;
  1473.     m_uMouseFlags = uFlags;
  1474.  
  1475.     //    Convert the point to something we understand.
  1476.     XY Point;
  1477.     ResolvePoint(Point, cpPoint);
  1478.  
  1479. #ifdef LAYERS
  1480.     if (GetContext()->compositor) {
  1481.         CL_Event event;
  1482.         fe_EventStruct fe_event;
  1483.         
  1484.         fe_event.uFlags = uFlags;
  1485.         fe_event.x = cpPoint.x;
  1486.         fe_event.y = cpPoint.y;
  1487.         
  1488.         event.type = CL_EVENT_MOUSE_BUTTON_MULTI_CLICK;
  1489.         event.fe_event = (void *)&fe_event;
  1490.         event.fe_event_size = sizeof(fe_EventStruct);
  1491.         event.x = Point.x;
  1492.         event.y = Point.y;
  1493.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  1494.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  1495.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  1496.         event.which = 1;
  1497.         event.data = 2;
  1498.     
  1499.         CL_DispatchEvent(GetContext()->compositor,
  1500.                  &event);
  1501.     }
  1502.     else 
  1503.         OnLButtonDblClkForLayerCX(uFlags, cpPoint, Point, NULL);
  1504.  
  1505.     //  Have the mouse timer handler do some dirty work.
  1506.     MouseTimerData mt(GetContext());
  1507.     FEU_MouseTimer(&mt);
  1508.     return;
  1509. }
  1510.  
  1511. void 
  1512. CWinCX::OnLButtonDblClkForLayerCX(UINT uFlags, CPoint& cpPoint,
  1513.                   XY& Point, CL_Layer *layer)
  1514. {
  1515. // With LAYERS turned on, the orginal method 
  1516. // OnLButtonDblClkCX is separated into two methods,
  1517. // one of which is a per-layer method.
  1518. #endif /* LAYERS */
  1519.  
  1520.     //    Process any embed activation.
  1521. #ifdef LAYERS
  1522.     LO_Element *pElement = GetLayoutElement(Point, layer);
  1523. #else
  1524.     LO_Element *pElement = GetLayoutElement(Point);
  1525. #endif
  1526.  
  1527.     if (pElement != NULL && pElement->type == LO_FORM_ELE &&
  1528.         (Point.x - pElement->lo_form.x - pElement->lo_form.x_offset < pElement->lo_form.width) &&
  1529.         (Point.x - pElement->lo_form.x - pElement->lo_form.x_offset > 0) &&
  1530.         (Point.y - pElement->lo_form.y - pElement->lo_form.y_offset < pElement->lo_form.height) &&
  1531.         (Point.y - pElement->lo_form.y - pElement->lo_form.y_offset > 0)) {
  1532.        
  1533.        CFormElement * pFormElement;
  1534.        CNetscapeButton *pButton;
  1535.        switch (pElement->lo_form.element_data->type) {
  1536.            case FORM_TYPE_BUTTON:
  1537.            case FORM_TYPE_RESET:
  1538.            case FORM_TYPE_SUBMIT:
  1539.            case FORM_TYPE_CHECKBOX:
  1540.            case FORM_TYPE_RADIO:
  1541.            pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  1542.            ((CNetscapeButton *)CButton::FromHandlePermanent(pFormElement->GetRaw()))
  1543.                 ->OnButtonEvent(CL_EVENT_MOUSE_BUTTON_MULTI_CLICK, uFlags, cpPoint);
  1544.            break;
  1545.            case FORM_TYPE_FILE:
  1546.            pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  1547.            pButton = (CNetscapeButton *)pFormElement->GetSecondaryWidget();
  1548.            if (pButton)
  1549.                pButton->OnButtonEvent(CL_EVENT_MOUSE_BUTTON_MULTI_CLICK, uFlags, cpPoint);
  1550.            break;
  1551.            default:
  1552.            break;
  1553.        }
  1554.     return;
  1555.     }
  1556.  
  1557.     if(pElement != NULL && pElement->type == LO_EMBED)    {
  1558.         //    Any previous activated embed was deactivated in the button down event.
  1559.         //    However, we should not reactivate an already active item.
  1560.         NPEmbeddedApp* pEmbeddedApp = (NPEmbeddedApp*)pElement->lo_embed.FE_Data;
  1561.         ASSERT(pEmbeddedApp);
  1562.         CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  1563.         if(pItem != NULL)    {
  1564.             if(pItem->m_bBroken == FALSE && pItem->m_bDelayed == FALSE &&
  1565.                 pItem->m_bLoading == FALSE)    {
  1566.                 if(pItem->IsInPlaceActive() == FALSE)    {
  1567.                     //    Set the active item.
  1568.                     //    This value is held in the view for now....
  1569.                     CGenericView *pView = GetView();
  1570.                     if(pView)   {
  1571.                         m_pSelected = &(pElement->lo_embed);
  1572.  
  1573.                         long lVerb = OLEIVERB_PRIMARY;
  1574.                         if(uFlags & MK_CONTROL)    {
  1575.                             lVerb = OLEIVERB_OPEN;
  1576.                         }
  1577.  
  1578.                         pView->BeginWaitCursor();
  1579.                         TRY    {
  1580.                             pItem->Activate(lVerb, pView);
  1581.  
  1582.                         }
  1583.                         CATCH(CException, e)    {
  1584.                             //    Object wouldn't activate or something went wrong,
  1585.                             //        and almost caused us to go down with it.
  1586.                             m_pSelected = NULL;
  1587.                         }
  1588.                         END_CATCH
  1589.                         pView->EndWaitCursor();
  1590.                         //    If it's not in place active at this point, there's no need
  1591.                         //        to keep track of it.
  1592.                         if(m_pSelected != NULL && pItem->IsInPlaceActive() == FALSE)    {
  1593.                             m_pSelected = NULL;
  1594.                         }
  1595.                     }
  1596.                 }
  1597.             }
  1598.             }
  1599.  
  1600.         // Dbl-click is not the same as holding mouse down
  1601.         m_bLBDown = FALSE;
  1602.         m_bLBUp = TRUE;
  1603.     }
  1604.     else {
  1605.          if(GetPane())    {
  1606.             ::SetCapture(GetPane());
  1607.         }
  1608.  
  1609. #ifdef EDITOR
  1610.         if ( EDT_IS_EDITOR(GetContext()) )
  1611.         {
  1612.             // Let the editor handle the double-click
  1613.             EDT_DoubleClick(GetContext(), Point.x, Point.y);
  1614.             // Dbl-click is NOT the same as holding mouse down
  1615.             m_bLBDown = FALSE;
  1616.             m_bLBUp = TRUE;
  1617.         }
  1618.         else
  1619.         {
  1620. #ifdef LAYERS
  1621.             LO_DoubleClick(GetDocumentContext(), Point.x, Point.y, layer);
  1622. #else
  1623.             LO_DoubleClick(GetDocumentContext(), Point.x, Point.y);
  1624. #endif /* LAYERS */
  1625.             // Double-click is the same as holding mouse down when
  1626.             // we're selecting. 
  1627.             //cmanske: WHY??? DOES THE BROWSER NEED THIS? BAD FOR EDITOR!
  1628. #endif // EDITOR
  1629.             m_bLBDown = TRUE;
  1630.             m_bLBUp = FALSE;
  1631. #ifdef EDITOR
  1632.         }
  1633. #endif
  1634.     }
  1635.  
  1636.     //  Have the mouse timer handler do some dirty work.
  1637.     //  Please don't return in the above code, I'd like this to get called
  1638.     //      in all cases with the state of the buttons set correctly.
  1639.     MouseTimerData mt(GetContext());
  1640.     FEU_MouseTimer(&mt);
  1641. }
  1642.  
  1643. BOOL CWinCX::PtInSelectedCell(CPoint &DocPoint, LO_CellStruct *cell, 
  1644.                               BOOL &bContinue, LO_Element *start_element,
  1645.                               LO_Element *end_element)
  1646. {
  1647.     BOOL bPtInRegion = FALSE;
  1648.  
  1649.     for ( LO_Any_struct * element = (LO_Any_struct *)cell->cell_list; ;
  1650.               element = (LO_Any_struct *)(element->next) ) {
  1651.         if( element == 0 ){
  1652.             bContinue = TRUE;
  1653.             return FALSE;
  1654.         }
  1655.  
  1656.         // Linefeed rect is from end of text to right ledge,
  1657.         //  so lets ignore it
  1658.         if ( element->type != LO_LINEFEED ) {
  1659.             if ( element->type == LO_TEXT && 
  1660.                  (element == (LO_Any_struct*)start_element || 
  1661.                   element == (LO_Any_struct*)end_element) ) {
  1662.                 // With 1st and last text elements, we need to
  1663.                 // account for character offsets from start or end of selection
  1664.                 LO_TextStruct *text = (LO_TextStruct*)element;
  1665.                 LTRB rect;
  1666.                 // We may have a null text element in Tables,
  1667.                 //  so use closest non-null text element
  1668.                 if( text->text == NULL){
  1669.                     if( text->prev != NULL && text->prev->type == LO_TEXT ){
  1670.                         text = (LO_TextStruct*)text->prev;
  1671.                     } else if( text->next != NULL && text->next->type == LO_TEXT ){
  1672.                         text = (LO_TextStruct*)text->next;
  1673.                     }
  1674.                 }
  1675.                 if( text->text ){
  1676.                     ResolveElement( rect, text,
  1677.                                     (int)(text->x + text->x_offset),     // Start location
  1678.                                     (int32)(text->sel_start), 
  1679.                                     (int32)(text->sel_end), FALSE ); 
  1680.                     int x = CASTINT(DocPoint.x - GetOriginX());
  1681.                     int y = CASTINT(DocPoint.y - GetOriginY());
  1682.                     bPtInRegion = x > rect.left &&
  1683.                         x < rect.right &&
  1684.                         y > rect.top &&
  1685.                         y < rect.bottom;
  1686.                 } else {
  1687.                     bPtInRegion = FALSE;
  1688.                 }
  1689.             } 
  1690.             else if (element->type == LO_CELL) {
  1691.                 bPtInRegion = PtInSelectedCell(DocPoint, 
  1692.                                                (LO_CellStruct *)element,
  1693.                                                bContinue, start_element,
  1694.                                                end_element);
  1695.             }
  1696.             else if (element->type != LO_TABLE) {
  1697.                 // Get the rect surrounding selected element,
  1698.                 CRect cRect;
  1699.                 cRect.left = CASTINT(element->x + element->x_offset);
  1700.                 cRect.top = CASTINT(element->y + element->y_offset);
  1701.                 cRect.right = CASTINT(cRect.left + element->width);
  1702.                 cRect.bottom = CASTINT(cRect.top + element->height);
  1703.                 bPtInRegion = cRect.PtInRect( DocPoint );
  1704.             }
  1705.         }
  1706.         // We're done if we are in a rect or finished with last element
  1707.         if ( bPtInRegion || !bContinue || 
  1708.              element == (LO_Any_struct*)end_element ) {
  1709.             break;
  1710.         }
  1711.     }
  1712.     
  1713.     bContinue = FALSE;
  1714.     return bPtInRegion;
  1715. }
  1716.  
  1717. //  Test if point, such mouse cursor, is within the selected region
  1718. BOOL CWinCX::PtInSelectedRegion(CPoint cPoint, BOOL bConvertToDocCoordinates,
  1719.                                 CL_Layer *layer)
  1720. {
  1721.     BOOL bPtInRegion = FALSE;
  1722.     BOOL bContinue = TRUE;
  1723.  
  1724.     CPoint DocPoint;
  1725.     if( bConvertToDocCoordinates ){
  1726.         XY Point;
  1727.         ResolvePoint(Point, cPoint);
  1728.         DocPoint.x = CASTINT(Point.x);
  1729.         DocPoint.y = CASTINT(Point.y);
  1730.     } else {
  1731.         DocPoint = cPoint;
  1732.     }
  1733.  
  1734.     int32 start_selection, end_selection;
  1735.     LO_Element * start_element = NULL;
  1736.     LO_Element * end_element = NULL;
  1737.     CL_Layer *sel_layer = NULL;
  1738.     int32 x_origin, y_origin, old_x_origin, old_y_origin;
  1739.  
  1740.     // Start the search from the current selection location    
  1741.     LO_GetSelectionEndpoints(GetDocumentContext(), 
  1742.                          &start_element, 
  1743.                          &end_element, 
  1744.                          &start_selection, 
  1745.                          &end_selection,
  1746.                          &sel_layer);
  1747.     
  1748.     if ( start_element == NULL ) {
  1749.         return FALSE;
  1750.     } 
  1751.     
  1752.     /* 
  1753.      * If the selection layer is different from the one in which
  1754.      * the event occured, there isn't a match.
  1755.      */
  1756.     if ( layer && (layer != sel_layer) ) {
  1757.         return FALSE;
  1758.     }
  1759.        
  1760.     /* 
  1761.      * Temporarily change the drawing origin to that of the selection
  1762.      * layer so that resolving the positions of the elements will 
  1763.      * result in correct coordinate space translation.
  1764.      */
  1765.     if ( sel_layer ) {
  1766.         x_origin = CL_GetLayerXOrigin(sel_layer);
  1767.         y_origin = CL_GetLayerYOrigin(sel_layer);
  1768.     }
  1769.     else {
  1770.         x_origin = 0;
  1771.         y_origin = 0;
  1772.     }
  1773.     
  1774.     CDrawable *pDrawable = GetDrawable();
  1775.     if (pDrawable) {
  1776.         pDrawable->GetOrigin(&old_x_origin, &old_y_origin);
  1777.         pDrawable->SetOrigin(x_origin, y_origin);
  1778.     }
  1779.     
  1780.     for ( LO_Any_struct * element = (LO_Any_struct *)start_element; ;
  1781.           element = (LO_Any_struct *)(element->next) ) {
  1782.         // KLUDGE: This prevents crashing when multiple selection
  1783.         //         within cells of a table
  1784.         if( element == 0 ){
  1785.             if ( pDrawable ) {
  1786.                 pDrawable->SetOrigin(old_x_origin, old_y_origin);
  1787.             }
  1788.             return FALSE;
  1789.         }
  1790.             // Linefeed rect is from end of text to right ledge,
  1791.             //  so lets ignore it
  1792.         if ( element->type != LO_LINEFEED ) {
  1793.             if ( element->type == LO_TEXT && 
  1794.                  (element == (LO_Any_struct*)start_element || 
  1795.                   element == (LO_Any_struct*)end_element) ) {
  1796.                 // With 1st and last text elements, we need to
  1797.                 // account for character offsets from start or end of selection
  1798.                 LO_TextStruct *text = (LO_TextStruct*)element;
  1799.                 LTRB rect;
  1800.                 // We may have a null text element in Tables,
  1801.                 //  so use closest non-null text element
  1802.                 if( text->text == NULL){
  1803.                     if( text->prev != NULL && text->prev->type == LO_TEXT ){
  1804.                         text = (LO_TextStruct*)text->prev;
  1805.                     } else if( text->next != NULL && text->next->type == LO_TEXT ){
  1806.                         text = (LO_TextStruct*)text->next;
  1807.                     }
  1808.                 }
  1809.                 if( text->text ){
  1810.                     ResolveElement( rect, text,
  1811.                                     (int)(text->x + text->x_offset),     // Start location
  1812.                                     (int32)(text->sel_start), 
  1813.                                     (int32)(text->sel_end), FALSE ); 
  1814.                     int x = CASTINT(DocPoint.x - GetOriginX());
  1815.                     int y = CASTINT(DocPoint.y - GetOriginY());
  1816.                     bPtInRegion = x > rect.left &&
  1817.                                   x < rect.right &&
  1818.                                   y > rect.top &&
  1819.                                   y < rect.bottom;
  1820.                 } else {
  1821.                     bPtInRegion = FALSE;
  1822.                 }
  1823.             } 
  1824.             else if (element->type == LO_CELL) {
  1825.                 bPtInRegion = PtInSelectedCell(DocPoint, 
  1826.                                                (LO_CellStruct *)element,
  1827.                                                bContinue, start_element,
  1828.                                                end_element);
  1829.             }
  1830.             else if (element->type != LO_TABLE) {
  1831.                 // Get the rect surrounding selected element,
  1832.                 CRect cRect;
  1833.                 cRect.left = CASTINT(element->x + element->x_offset);
  1834.                 cRect.top = CASTINT(element->y + element->y_offset);
  1835.                 cRect.right = CASTINT(cRect.left + element->width);
  1836.                 cRect.bottom = CASTINT(cRect.top + element->height);
  1837.                 bPtInRegion = cRect.PtInRect( DocPoint );
  1838.             }
  1839.         }
  1840.         // We're done if we are in a rect or finished with last element
  1841.         if ( bPtInRegion || !bContinue || 
  1842.              element == (LO_Any_struct*)end_element ) {
  1843.             break;
  1844.         }
  1845.     }
  1846.  
  1847.     if ( pDrawable ) {
  1848.         pDrawable->SetOrigin(old_x_origin, old_y_origin);
  1849.     }
  1850.         
  1851.     return bPtInRegion;
  1852. }
  1853.  
  1854. void CWinCX::OnLButtonDownCX(UINT uFlags, CPoint cpPoint)
  1855. {
  1856.     RelayToolTipEvent(cpPoint, WM_LBUTTONDOWN);
  1857.  
  1858.     //    Only do this if clicking is enabled.
  1859.     if(IsClickingEnabled() == FALSE)    {
  1860.         return;
  1861.     }
  1862.  
  1863.     //    Don't continue if this context is destroyed.
  1864.     if(IsDestroyed())    {
  1865.         return;
  1866.     }
  1867.  
  1868.     //    Start capturing all mouse events.
  1869.     if(GetPane())   {
  1870.         ::SetCapture(GetPane());
  1871.     }
  1872.  
  1873.     XY Point;
  1874.     ResolvePoint(Point, cpPoint);
  1875.  
  1876. #ifdef LAYERS
  1877.     
  1878.     if (GetContext()->compositor) {
  1879.         CL_Event event;
  1880.         fe_EventStruct fe_event;
  1881.         
  1882.         fe_event.uFlags = uFlags;
  1883.         fe_event.x = cpPoint.x;
  1884.         fe_event.y = cpPoint.y;
  1885.         
  1886.         event.type = CL_EVENT_MOUSE_BUTTON_DOWN;
  1887.         event.fe_event = (void *)&fe_event;
  1888.         event.fe_event_size = sizeof(fe_EventStruct);
  1889.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  1890.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  1891.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  1892.         event.x = Point.x;
  1893.         event.y = Point.y;
  1894.         event.which = 1;
  1895.     
  1896.         CL_DispatchEvent(GetContext()->compositor,
  1897.                  &event);
  1898.     }
  1899.     else 
  1900.         OnLButtonDownForLayerCX(uFlags, cpPoint, Point, NULL);
  1901.  
  1902.     //  Have the mouse timer handler do some dirty work.
  1903.     MouseTimerData mt(GetContext());
  1904.     FEU_MouseTimer(&mt);
  1905.     return;
  1906. }
  1907.  
  1908. void CWinCX::ResetToolTipImg() {
  1909.     pLastToolTipImg = 0;
  1910.     m_pLastToolTipAnchor = NULL;
  1911.     if (m_ToolTip) {
  1912.         m_ToolTip->Activate(FALSE);
  1913.         delete m_ToolTip;
  1914.         m_ToolTip = 0;
  1915.     }
  1916. }
  1917.  
  1918.  
  1919. void CWinCX::RelayToolTipEvent(POINT pt, UINT message)
  1920. {
  1921.     if (m_ToolTip) {
  1922.         MSG msg;
  1923.         msg.message = message;
  1924.         msg.hwnd = GetPane();
  1925.         msg.pt = pt;
  1926.         ::ClientToScreen(msg.hwnd, &msg.pt);
  1927.         m_ToolTip->RelayEvent(&msg);
  1928.     }
  1929. }
  1930.  
  1931. void
  1932. CWinCX::OnLButtonDownForLayerCX(UINT uFlags, CPoint &cpPoint, XY& Point, 
  1933.                 CL_Layer *layer)
  1934. {
  1935.     MWContext *pMWContext = GetContext();
  1936.     XP_ASSERT(pMWContext);
  1937.  
  1938. // With LAYERS turned on, the orginal method 
  1939. // OnLButtonDownCX is separated into two methods,
  1940. // one of which is a per-layer method.
  1941.     if (pMWContext->compositor)
  1942.       CL_GrabMouseEvents(pMWContext->compositor, layer);
  1943. #endif /* LAYERS */
  1944.  
  1945. #ifdef LAYERS
  1946.     LO_Element *pElement = GetLayoutElement(Point, layer);
  1947. #else
  1948.     LO_Element *pElement = GetLayoutElement(Point);
  1949. #endif /* LAYERS */
  1950.  
  1951.     // Check for form element and send event back to form element's class.
  1952.    if (pElement != NULL && pElement->type == LO_FORM_ELE &&
  1953.         (Point.x - pElement->lo_form.x - pElement->lo_form.x_offset < pElement->lo_form.width) &&
  1954.         (Point.x - pElement->lo_form.x - pElement->lo_form.x_offset > 0) &&
  1955.         (Point.y - pElement->lo_form.y - pElement->lo_form.y_offset < pElement->lo_form.height) &&
  1956.         (Point.y - pElement->lo_form.y - pElement->lo_form.y_offset > 0)) {
  1957.        
  1958.        CFormElement * pFormElement;
  1959.        CNetscapeButton * pButton;
  1960.        switch (pElement->lo_form.element_data->type) {
  1961.            case FORM_TYPE_BUTTON:
  1962.            case FORM_TYPE_RESET:
  1963.            case FORM_TYPE_SUBMIT:
  1964.            case FORM_TYPE_CHECKBOX:
  1965.            case FORM_TYPE_RADIO:
  1966.                pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  1967.                ((CNetscapeButton *)CButton::FromHandlePermanent(pFormElement->GetRaw()))
  1968.                 ->OnButtonEvent(CL_EVENT_MOUSE_BUTTON_DOWN, uFlags, cpPoint);
  1969.                break;
  1970.        case FORM_TYPE_FILE:
  1971.                pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  1972.            pButton = (CNetscapeButton *)pFormElement->GetSecondaryWidget();
  1973.            if (pButton)
  1974.             pButton->OnButtonEvent(CL_EVENT_MOUSE_BUTTON_DOWN, uFlags, cpPoint);
  1975.                break;
  1976.            default:
  1977.                break;
  1978.     }
  1979.     return;
  1980.    }
  1981.  
  1982.     //    Wait to set these until we know the event hasn't be cancelled
  1983.     //  by JS or really meant for a form element.  Remember....
  1984.     m_LastMouseEvent = m_LBDown;
  1985.     m_cpLBDown = cpPoint;
  1986.     m_uMouseFlags = uFlags;
  1987.     m_bLBDown = TRUE;
  1988.     m_bLBUp = FALSE;
  1989.  
  1990.  
  1991.     //    Deactivate OLE embedded items if active.
  1992.     CGenericView *pView = GetView();
  1993.     if(pView != NULL && pElement != (LO_Element *)m_pSelected && m_pSelected != NULL)    {
  1994.         OnDeactivateEmbedCX();
  1995.     }
  1996.     
  1997. #ifdef EDITOR
  1998.     ED_HitType iTableHit = ED_HIT_NONE;
  1999.     LO_Element * pTableOrCellElement = NULL;
  2000.  
  2001.     if( EDT_IS_EDITOR(pMWContext) )
  2002.     {
  2003.         m_pStartSelectionCell = NULL;
  2004.  
  2005.         // Check if user pressed down near a sizeable object border
  2006.         //   and start sizing mode if we are
  2007.         // Note: X, Y values are in Document coordinates
  2008.         if( !m_bDragging && !EDT_IsSizing(pMWContext) )
  2009.         {
  2010.             BOOL bSizeTable = FALSE;
  2011.  
  2012.             // Left button down test for selection/sizing/dragging
  2013.             iTableHit = EDT_GetTableHitRegion( pMWContext, Point.x, Point.y, &pTableOrCellElement, (uFlags & MK_CONTROL) );
  2014.  
  2015.             // Check if we can select or size a Table or Cell,
  2016.             //   but not if Alt key is pressed, ignore the table
  2017.             //   to allow sizing objects tightly surrounded by Cell border
  2018.             if( GetAsyncKeyState(VK_MENU) >= 0 &&
  2019.                 pTableOrCellElement )
  2020.             {
  2021.                 // Save cell we are in
  2022.                 if( pTableOrCellElement->type == LO_CELL )
  2023.                     m_pStartSelectionCell = pTableOrCellElement;
  2024.  
  2025.                 if( iTableHit == ED_HIT_SIZE_TABLE_WIDTH || iTableHit == ED_HIT_SIZE_TABLE_HEIGHT ||
  2026.                     iTableHit == ED_HIT_SIZE_COL || iTableHit == ED_HIT_SIZE_ROW ||
  2027.                     iTableHit == ED_HIT_ADD_ROWS || iTableHit == ED_HIT_ADD_COLS )
  2028.                 {
  2029.                     // We are sizing a table, row, or column
  2030.                     pElement = pTableOrCellElement;
  2031.                     bSizeTable = TRUE;
  2032.                 } else if( iTableHit != ED_HIT_NONE && iTableHit != ED_HIT_DRAG_TABLE )
  2033.                 {
  2034.                     m_bSelectingCells = TRUE;
  2035.                     // Mouse is in a selectable region for table, row, column, or cell.
  2036.                     // If Ctrl key is down and cell is selected, it is appended to other table cells selected
  2037.                     // Otherwise, any other cell or table selected is cleared before new element is selected.
  2038.                     // If Shift key is down, then extend selection to new cell
  2039.                     EDT_SelectTableElement(pMWContext, Point.x, Point.y, pTableOrCellElement, iTableHit, 
  2040.                                            (uFlags & MK_CONTROL), (uFlags & MK_SHIFT));
  2041.                     goto MOUSE_TIMER;
  2042.                 }
  2043.             }            
  2044.  
  2045.             if( bSizeTable ||
  2046.                 (pElement && EDT_CanSizeObject(pMWContext, pElement, Point.x, Point.y)) )
  2047.             {
  2048.                 // Flag to override the normal lock when sizing corners
  2049.                 BOOL bLock = !(BOOL)(uFlags & MK_CONTROL);
  2050.                 XP_Rect rect;
  2051.                 if( EDT_StartSizing(pMWContext, pElement, Point.x, Point.y, bLock, &rect) )
  2052.                 {
  2053.                     // Force redraw of table or cells that might have been selected
  2054.                     //   else we have NOT conflicts and garbage at overlaps
  2055.                     UpdateWindow(GetPane());
  2056.                     // Save the new rect.
  2057.                     m_rectSizing.left = rect.left;
  2058.                     m_rectSizing.right = rect.right;
  2059.                     m_rectSizing.top = rect.top;
  2060.                     m_rectSizing.bottom = rect.bottom;
  2061.                     // Draw the initial feedback -- similar to when selected
  2062.                     DisplaySelectionFeedback(LO_ELE_SELECTED, m_rectSizing);
  2063.                     goto MOUSE_TIMER;
  2064.                 }
  2065.             }
  2066.         }
  2067.     }
  2068.     // Drag Copy/Move - do only if we will not be sizing
  2069.     if( GetView()->IsKindOf(RUNTIME_CLASS(CNetscapeView)) &&
  2070.         (iTableHit == ED_HIT_DRAG_TABLE || PtInSelectedRegion(cpPoint, TRUE, layer)) ) 
  2071.     {
  2072.         // Setup to possibly do Drag Copy/Move
  2073.         // Check these flags during mouse move 
  2074.         //   and start drag only if mouse moved enough
  2075.         if( iTableHit == ED_HIT_DRAG_TABLE )
  2076.         {
  2077.             // Setup XP data for possible dragging of table or cells
  2078.             EDT_StartDragTable(pMWContext, Point.x, Point.y);
  2079.         }
  2080.         m_bMouseInSelection = TRUE;
  2081.  
  2082.     } else
  2083. #endif // EDITOR
  2084.     if ( ! m_bDragging ) {
  2085.         // If the shift key is down, we need to extend the selection.
  2086.         if( (uFlags & MK_SHIFT) ) {
  2087. #ifdef EDITOR
  2088.             if( EDT_IS_EDITOR(pMWContext) ){
  2089.                 EDT_ExtendSelection(pMWContext, Point.x, Point.y);
  2090.             } 
  2091.             else
  2092. #endif // EDITOR
  2093.             {
  2094.                 LO_ExtendSelection(GetDocumentContext(), Point.x, Point.y);
  2095.             }
  2096.         } else {
  2097.             // Start a normal selection
  2098. #ifdef EDITOR
  2099.             if( EDT_IS_EDITOR(pMWContext) ) {
  2100.                 EDT_StartSelection(pMWContext, Point.x, Point.y);
  2101.             } 
  2102.             else
  2103. #endif // EDITOR
  2104.             {
  2105. #ifdef LAYERS 
  2106.                 LO_StartSelection(GetDocumentContext(), Point.x, Point.y, layer);
  2107. #else
  2108.                 LO_StartSelection(GetDocumentContext(), Point.x, Point.y);
  2109. #endif /* LAYERS */
  2110.             }
  2111.         }
  2112.     }
  2113.     //    Highlight an anchor if we are over it.
  2114.  
  2115.     // Save an image element so we can drag into editor
  2116.     if ( pElement != NULL && pElement->type == LO_IMAGE ) {
  2117.         m_pLastImageObject = (LO_ImageStruct*)pElement;
  2118.     }
  2119.  
  2120.     // DON'T drag links when in editor - just highlight the text in the link
  2121.     if(!EDT_IS_EDITOR(pMWContext) &&
  2122.        pElement != NULL && pElement->type == LO_TEXT && pElement->lo_text.anchor_href != NULL) {
  2123.         m_pLastArmedAnchor = pElement;
  2124.         LO_HighlightAnchor(GetDocumentContext(), pElement, TRUE);
  2125.     }
  2126.  
  2127. MOUSE_TIMER:
  2128.     //  Have the mouse timer handler do some dirty work.
  2129.     //  Please don't return in the above code, I'd like this to get called
  2130.     //      in all cases with the state of the buttons set correctly.
  2131.     MouseTimerData mt(pMWContext);
  2132.     FEU_MouseTimer(&mt);
  2133. }
  2134.  
  2135. typedef struct click_closure {
  2136.     char   * szRefer;
  2137.     int         x, y;
  2138.     CWinCX * pWin;
  2139.     BOOL     bCloseOnFail;
  2140.     LO_Element * pElement;
  2141. } click_closure;
  2142.  
  2143. static void
  2144. MapToAnchorAndTarget(MWContext * context, LO_Element * pElement, int x, int y, 
  2145.              CString& csAnchor, CString& csTarget)
  2146. {
  2147.  
  2148.     switch(pElement->type) {
  2149.  
  2150.     case LO_TEXT:
  2151.     if(pElement->lo_text.anchor_href && pElement->lo_text.anchor_href->anchor) {
  2152.         csAnchor = (char *) pElement->lo_text.anchor_href->anchor;
  2153.         csTarget = (char *) pElement->lo_text.anchor_href->target;
  2154.     }
  2155.     break;
  2156.  
  2157.     case LO_IMAGE:
  2158.         //    Check for usemaps (client side ismaps).
  2159.     if(pElement->lo_image.image_attr && pElement->lo_image.image_attr->usemap_name != NULL)    {
  2160.         LO_AnchorData *pAnchorData = LO_MapXYToAreaAnchor(context, 
  2161.                             &pElement->lo_image, x, y);
  2162.         if(pAnchorData != NULL)    {
  2163.         csAnchor = (char *) pAnchorData->anchor;
  2164.         csTarget = (char *) pAnchorData->target;
  2165.         }
  2166.         break;
  2167.     }
  2168.  
  2169.     //    Check for ismaps, normal image anchors
  2170.     if(pElement->lo_image.anchor_href != NULL && 
  2171.         pElement->lo_image.anchor_href->anchor != NULL) {
  2172.         
  2173.         if(pElement->lo_image.image_attr && pElement->lo_image.image_attr->attrmask & LO_ATTR_ISMAP) {
  2174.  
  2175.         char * pAnchor = PR_smprintf("%s?%d,%d", 
  2176.                 pElement->lo_image.anchor_href->anchor, x, y);
  2177.         csAnchor = pAnchor;
  2178.         XP_FREE(pAnchor);
  2179.         csTarget =(char *)pElement->lo_image.anchor_href->target;
  2180.         }
  2181.         else {
  2182.         csAnchor = (char *)pElement->lo_image.anchor_href->anchor;
  2183.         csTarget = (char *)pElement->lo_image.anchor_href->target;
  2184.         }
  2185.     }
  2186.     break;
  2187.     break;
  2188.  
  2189.     default:
  2190.     break;
  2191.     }
  2192.  
  2193. }
  2194.  
  2195.  
  2196. //
  2197. // Mocha has processed a click on an element.  If everything is OK
  2198. //   we now will do the actual load.  If libmocha said to not
  2199. //   load and we created a new window explicitly for the load
  2200. //   delete the window
  2201. //
  2202. static void
  2203. win_click_callback(MWContext * pContext, LO_Element * pEle, int32 event,
  2204.                      void * pObj, ETEventStatus status)
  2205. {
  2206.  
  2207.     CString csAnchor, csTarget;
  2208.  
  2209.     // make sure document hasn't gone away
  2210.     if(status == EVENT_PANIC) {
  2211.     if (((click_closure *)pObj)->pElement && pEle) {
  2212.         XP_FREE(pEle);
  2213.     }
  2214.     XP_FREE(pObj);
  2215.         return;
  2216.     }
  2217.  
  2218.     // find out who we are
  2219.     click_closure * pClose = (click_closure *) pObj;
  2220.     CWinCX * pWin = pClose->pWin;
  2221.  
  2222.     // Imagemaps send click pretending to be links.  Free the link now and 
  2223.     // set the element back to the image it is.
  2224.     if (pClose->pElement) {
  2225.     if(pEle)
  2226.         XP_FREE(pEle);
  2227.     pEle = pClose->pElement;
  2228.     }
  2229.  
  2230.     MapToAnchorAndTarget(pWin->GetContext(), pEle, pClose->x, pClose->y, csAnchor, csTarget);
  2231.  
  2232. #ifdef EDITOR
  2233.     if( EDT_IS_EDITOR(pWin->GetContext()) ){
  2234.         // Ctrl Click = edit the URL
  2235.         FE_LoadUrl((char*)LPCSTR(csAnchor), LOAD_URL_COMPOSER);
  2236.         goto done;
  2237.     }
  2238. #endif // EDITOR
  2239.  
  2240.     if(status == EVENT_OK)  {
  2241.         CWinCX *pLoader = pWin->DetermineTarget(csTarget);
  2242.         pLoader->NormalGetUrl(csAnchor, pClose->szRefer, (csTarget.IsEmpty() ? NULL : (LPCSTR)csTarget));
  2243.     } else {
  2244.         if(pClose->bCloseOnFail)
  2245.             //  Make it go away if mocha said no.
  2246.             FE_DestroyWindow(pContext);
  2247.     }
  2248.  
  2249. done:
  2250.     if(pClose->szRefer)
  2251.         XP_FREE(pClose->szRefer);
  2252.     XP_FREE(pClose);
  2253.  
  2254. }
  2255.  
  2256. //
  2257. // The user clicked on a form image.  We told mocha about it and now mocha
  2258. //   is either going to tell us to submit the form or ignore it
  2259. //             
  2260. static void
  2261. image_form_click_callback(MWContext * pContext, LO_Element * pElement, int32 event,
  2262.               void * pObj, ETEventStatus status)
  2263. {
  2264.  
  2265.     // only continue if OK
  2266.     if(status != EVENT_OK) {
  2267.     XP_FREE(pObj);
  2268.     return;
  2269.     }
  2270.  
  2271.     click_closure * pClose = (click_closure *) pObj;
  2272.     CWinCX * pWin = pClose->pWin;
  2273.  
  2274.     LO_FormSubmitData *pSubmit = LO_SubmitImageForm(pContext, 
  2275.                                 &pElement->lo_image, 
  2276.                             pClose->x, 
  2277.                             pClose->y);
  2278.  
  2279.     if(pSubmit == NULL)    {
  2280.     //    Nothing to do.
  2281.     return;
  2282.     }
  2283.  
  2284.     //    Have to do a manual load here.
  2285.     URL_Struct *pUrl = NET_CreateURLStruct((const char *)pSubmit->action, NET_DONT_RELOAD);
  2286.     NET_AddLOSubmitDataToURLStruct(pSubmit, pUrl);
  2287.  
  2288.     //    Set the referrer here manually too.
  2289.     if(pClose->szRefer)
  2290.         pUrl->referer = XP_STRDUP(pClose->szRefer);
  2291.     else
  2292.         pUrl->referer = NULL;
  2293.  
  2294.     //    Request.
  2295.     pWin->GetUrl(pUrl, FO_CACHE_AND_PRESENT);
  2296.  
  2297.     //    Release.
  2298.     LO_FreeSubmitData(pSubmit);
  2299.  
  2300. }
  2301.  
  2302.  
  2303. void CWinCX::OnLButtonUpCX(UINT uFlags, CPoint cpPoint, BOOL &bReturnImmediately)    
  2304. {
  2305.     RelayToolTipEvent(cpPoint, WM_LBUTTONUP);
  2306.  
  2307.     //    Only do this if clicking is enabled.
  2308.     if(IsClickingEnabled() == FALSE)    {
  2309.         return;
  2310.     }
  2311.  
  2312.     //    Release mouse capture.
  2313.     if(GetPane())    {
  2314.         ::ReleaseCapture();
  2315.     }
  2316.  
  2317.     //    Don't continue if this context is destroyed.
  2318.     if(IsDestroyed())    {
  2319.         return;
  2320.     }
  2321.  
  2322.         XY Point;
  2323.     ResolvePoint(Point, cpPoint);
  2324.     
  2325. #ifdef LAYERS
  2326.     
  2327.     if (GetContext()->compositor) {
  2328.         CL_Event event;
  2329.         fe_EventStruct fe_event;
  2330.         
  2331.         fe_event.uFlags = uFlags;
  2332.         fe_event.x = cpPoint.x;
  2333.         fe_event.y = cpPoint.y;
  2334.         fe_event.pbReturnImmediately = bReturnImmediately;
  2335.  
  2336.         event.type = CL_EVENT_MOUSE_BUTTON_UP;
  2337.         event.fe_event = (void *)&fe_event;
  2338.         event.fe_event_size = sizeof(fe_EventStruct);
  2339.         event.x = Point.x;
  2340.         event.y = Point.y;
  2341.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  2342.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  2343.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  2344.         event.which = 1;
  2345.     
  2346.         CL_DispatchEvent(GetContext()->compositor,
  2347.                  &event);
  2348.  
  2349.         bReturnImmediately = fe_event.pbReturnImmediately;
  2350.     }
  2351.     else 
  2352.         OnLButtonUpForLayerCX(uFlags, cpPoint, Point, NULL, bReturnImmediately);
  2353.  
  2354.     //  Have the mouse timer handler do some dirty work.
  2355.     MouseTimerData mt(GetContext());
  2356.     FEU_MouseTimer(&mt);
  2357.     return;
  2358. }
  2359.  
  2360.  
  2361. void
  2362. CWinCX::OnLButtonUpForLayerCX(UINT uFlags, CPoint& cpPoint, XY& Point,
  2363.                   CL_Layer *layer, BOOL &bReturnImmediately)
  2364. {
  2365.  
  2366.     History_entry *pHist = NULL;
  2367.     click_closure * pClosure = NULL;
  2368.  
  2369.     // With LAYERS turned on, the orginal method 
  2370.     // OnLButtonUpCX is separated into two methods,
  2371.     // one of which is a per-layer method.
  2372.     if (GetContext()->compositor)
  2373.         CL_GrabMouseEvents(GetContext()->compositor, NULL);
  2374. #endif /* LAYERS */
  2375.  
  2376. #ifdef LAYERS
  2377.     LO_Element *pElement = GetLayoutElement(Point, layer);
  2378. #else
  2379.     LO_Element *pElement = GetLayoutElement(Point);
  2380. #endif /* LAYERS */
  2381.  
  2382.    if (pElement != NULL && pElement->type == LO_FORM_ELE &&
  2383.         (Point.x - pElement->lo_form.x - pElement->lo_form.x_offset < pElement->lo_form.width) &&
  2384.         (Point.x - pElement->lo_form.x - pElement->lo_form.x_offset > 0) &&
  2385.         (Point.y - pElement->lo_form.y - pElement->lo_form.y_offset < pElement->lo_form.height) &&
  2386.         (Point.y - pElement->lo_form.y - pElement->lo_form.y_offset > 0)) {
  2387.        
  2388.        CFormElement * pFormElement;
  2389.        CNetscapeButton * pButton;
  2390.        switch (pElement->lo_form.element_data->type) {
  2391.            case FORM_TYPE_BUTTON:
  2392.            case FORM_TYPE_RESET:
  2393.            case FORM_TYPE_SUBMIT:
  2394.            case FORM_TYPE_CHECKBOX:
  2395.            case FORM_TYPE_RADIO:
  2396.                pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  2397.                ((CNetscapeButton *)CButton::FromHandlePermanent(pFormElement->GetRaw()))
  2398.                 ->OnButtonEvent(CL_EVENT_MOUSE_BUTTON_UP, uFlags, cpPoint);
  2399.                break;
  2400.        case FORM_TYPE_FILE:
  2401.                pFormElement=(CFormElement *)pElement->lo_form.element_data->ele_minimal.FE_Data;
  2402.            pButton = (CNetscapeButton *)pFormElement->GetSecondaryWidget();
  2403.            if (pButton)
  2404.             pButton->OnButtonEvent(CL_EVENT_MOUSE_BUTTON_UP, uFlags, cpPoint);
  2405.                break;
  2406.            default:
  2407.                break;
  2408.     }
  2409.     m_bLBDown = FALSE;
  2410.     m_bLBUp = TRUE;
  2411.     return;
  2412.  
  2413.    }
  2414.  
  2415.     //    Wait to set these until we know the event hasn't be cancelled
  2416.     //  by JS or really meant for a form element.  Remember....
  2417.     m_LastMouseEvent = m_LBUp;
  2418.     m_cpLBUp = cpPoint;
  2419.     m_uMouseFlags = uFlags;
  2420.     m_bLBDown = FALSE;
  2421.     m_bLBUp = TRUE;
  2422.  
  2423.     // JS needs screen coords for click events.
  2424.     CPoint cpScreenPoint(cpPoint);
  2425.     ClientToScreen(GetPane(), &cpScreenPoint);
  2426.  
  2427. #ifdef EDITOR
  2428.  
  2429.     m_pStartSelectionCell = NULL;
  2430.     MWContext *pMWContext = GetContext();
  2431.  
  2432.     // Finish sizing an object only if we moved enough
  2433.     if( EDT_IS_SIZING ){
  2434.         // Remove last sizing feedback
  2435.         DisplaySelectionFeedback(LO_ELE_SELECTED, m_rectSizing);
  2436.  
  2437.         // We need this check or it is impossible to place a caret between
  2438.         //  adjacent objects)
  2439.         if(abs(m_cpLBUp.x - m_cpLBDown.x) > CLICK_THRESHOLD ||
  2440.             abs(m_cpLBUp.y - m_cpLBDown.y) > CLICK_THRESHOLD)    {
  2441.             ASSERT(cpPoint.y == Point.y - GetOriginY()); // REMOVEME
  2442.  
  2443.             // Resize the object
  2444.             EDT_EndSizing(pMWContext);
  2445.  
  2446.             // See comment at end - shouldn't return here???
  2447.             //  (many other places below do return!)
  2448.             goto MOUSE_TIMER;
  2449.         } else {
  2450.             EDT_CancelSizing(pMWContext);
  2451.             // Move caret to where cursor is
  2452.             EDT_StartSelection(pMWContext, Point.x, Point.y);
  2453.         }
  2454.     } else if(!m_bDragging && !m_bSelectingCells) {
  2455.         // If within an existing selection, we didn't trigger StartSelection
  2456.         //   on MouseDown, so do it now
  2457.         if( m_bMouseInSelection ){
  2458.             if( EDT_IS_EDITOR(pMWContext) ) {
  2459.                 EDT_StartSelection(pMWContext, Point.x, Point.y);
  2460.             } else {
  2461. #ifdef LAYERS 
  2462.                 LO_StartSelection(GetDocumentContext(), Point.x, Point.y, layer);
  2463. #else
  2464.                 LO_StartSelection(GetDocumentContext(), Point.x, Point.y);
  2465. #endif /* LAYERS */
  2466.             }
  2467.         }
  2468.         // Cleanup selection - check if start=end
  2469.         if( EDT_IS_EDITOR(pMWContext) )
  2470.             EDT_EndSelection(pMWContext, Point.x, Point.y);
  2471.  
  2472.     }
  2473.     if( EDT_IS_EDITOR(pMWContext) )
  2474.     {
  2475.         if( EDT_CanPasteStyle(pMWContext) )
  2476.         {
  2477.             // Apply style if available
  2478.             EDT_PasteStyle(pMWContext, TRUE);
  2479.         }
  2480.         // Cancel any attempt to drag a table or cell
  2481.         EDT_StopDragTable(pMWContext);
  2482.     }
  2483. #endif // EDITOR
  2484.  
  2485.     m_bMouseInSelection = FALSE;
  2486.     m_bDragging = FALSE;
  2487.     m_bSelectingCells = FALSE;
  2488.  
  2489.     //    If we previously highlighted an anchor in button down, unhighlight it.
  2490.     if(m_pLastArmedAnchor != NULL)    {
  2491.         LO_HighlightAnchor(GetDocumentContext(), m_pLastArmedAnchor, FALSE);
  2492.         m_pLastArmedAnchor = NULL;
  2493.     }
  2494.  
  2495.     //    If the user moved the mouse beyond the clicking threshold, then consider
  2496.     //        this a text selection operation and don't continue.
  2497.     if(abs(m_cpLBUp.x - m_cpLBDown.x) > CLICK_THRESHOLD ||
  2498.     abs(m_cpLBUp.y - m_cpLBDown.y) > CLICK_THRESHOLD)    {
  2499.         return;
  2500.     }
  2501. #ifdef EDITOR
  2502.     // Done with possible drag image
  2503.     m_pLastImageObject = NULL;
  2504. #endif
  2505.  
  2506.     //    If there's no element, there's no need to see if we should load something.
  2507.     //  Just send a JS Click event to the document and return.
  2508.     if(pElement == NULL) {
  2509.         JSEvent *event;
  2510.         event = XP_NEW_ZAP(JSEvent);
  2511.         event->type = EVENT_CLICK;
  2512.         event->which = 1;
  2513.         event->x = Point.x;
  2514.         event->y = Point.y;
  2515.         event->docx = Point.x + CL_GetLayerXOrigin(layer);
  2516.         event->docy = Point.y + CL_GetLayerYOrigin(layer);
  2517.         event->screenx = cpScreenPoint.x;
  2518.         event->screeny = cpScreenPoint.y;
  2519.         event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  2520.  
  2521.         ET_SendEvent(GetContext(), NULL, event, NULL, NULL);
  2522.         return;
  2523.     }
  2524.  
  2525. // 
  2526. // Control click to chase anchors in the editor
  2527. //
  2528. #ifdef EDITOR
  2529.     if((uFlags & MK_CONTROL) == 0 && EDT_IS_EDITOR(GetContext())){
  2530.         m_pLastImageObject = NULL;
  2531.         return;
  2532.     }
  2533. #endif
  2534.  
  2535.     //    It's probably we're loading.
  2536.     //    Figure out what we'll be sending as the referrer field.
  2537.     pHist = SHIST_GetCurrent(&GetContext()->hist);
  2538.     pClosure = XP_NEW_ZAP(click_closure);
  2539.     pClosure->pWin = this;
  2540.     pClosure->pElement = NULL;
  2541.     if(pHist != NULL && pHist->address != NULL)
  2542.         pClosure->szRefer = strdup(pHist->origin_url ? pHist->origin_url : pHist->address);
  2543.     else
  2544.     pClosure->szRefer = NULL;
  2545.  
  2546.     //    To find out what to do, switch on the element's type.
  2547.     switch(pElement->type)
  2548.     {
  2549.         case LO_TEXT:
  2550.             if(pElement->lo_text.anchor_href && pElement->lo_text.anchor_href->anchor)
  2551.             {
  2552.                 // set tab_focus to this text element with a link.
  2553.                 //#52932 setFormElementTabFocus( (LO_Element *) pElement );
  2554.  
  2555.                 // if the shift-key is down save the object --- don't load it
  2556.                 if(uFlags & MK_SHIFT && NOT_A_DIALOG(this))
  2557.                 {
  2558.                     //  Should Mocha block save operations too?
  2559.                     CSaveCX::SaveAnchorObject((const char *)pElement->lo_text.anchor_href->anchor, NULL);
  2560.                     XP_FREE(pClosure);
  2561.                     return;
  2562.                 } 
  2563.  
  2564.                 // we are about to follow a link via a user click -- 
  2565.                 //   tell the mocha library.  Don't follow the link
  2566.                 //   until we get to our closure
  2567.                 JSEvent *event;
  2568.                 event = XP_NEW_ZAP(JSEvent);
  2569.                 event->type = EVENT_CLICK;
  2570.                 event->which = 1;
  2571.                 event->x = Point.x;
  2572.                 event->y = Point.y;
  2573.                 event->docx = Point.x + CL_GetLayerXOrigin(layer);
  2574.                 event->docy = Point.y + CL_GetLayerYOrigin(layer);
  2575.                 event->screenx = cpScreenPoint.x;
  2576.                 event->screeny = cpScreenPoint.y;
  2577.                 event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  2578.  
  2579.                 ET_SendEvent(GetContext(), pElement, event, win_click_callback, pClosure);
  2580.                 return;
  2581.             }
  2582.             break;
  2583.         
  2584.         case LO_IMAGE:    
  2585.         {
  2586.             //    Glean the FE data.
  2587.  
  2588.             //    Figure out where the click occurred.
  2589.             LO_ImageStruct* pImage = &pElement->lo_image;
  2590.  
  2591.             //    Layout wants this in pixels, not FE units.
  2592.             //  Point is in layer coordinates, as is the position of the image
  2593.             CPoint cpMap((int) (Point.x - Twips2PixX(pImage->x + pImage->x_offset + pImage->border_width)), 
  2594.                          (int) (Point.y - Twips2PixY(pImage->y + pImage->y_offset + pImage->border_width)));
  2595.  
  2596.             pClosure->x = cpMap.x;
  2597.             pClosure->y = cpMap.y;
  2598.  
  2599.             //    Check for usemaps (client side ismaps).
  2600.             if(pElement->lo_image.image_attr->usemap_name != NULL)
  2601.             {
  2602.                 LO_AnchorData *pAnchorData = LO_MapXYToAreaAnchor(GetDocumentContext(), 
  2603.                                         &pElement->lo_image, cpMap.x, cpMap.y);
  2604.                 if(pAnchorData != NULL)
  2605.                 {
  2606.  
  2607.                     // set tab_focus to this image element with a link. todo need to get the area index
  2608.                     //setFormElementTabFocus( (LO_Element *) pElement );
  2609.  
  2610.                     if(uFlags & MK_SHIFT && NOT_A_DIALOG(this)) {
  2611.                         //    Save it.
  2612.                         CSaveCX::SaveAnchorObject((const char *)pAnchorData->anchor, NULL);
  2613.                         XP_FREE(pClosure);
  2614.                     }
  2615.                     else {
  2616.                         LO_Element * pDummy;
  2617.  
  2618.                         // Imagemap area pretend to be links for JavaScript.
  2619.                         pDummy = (LO_Element *) XP_NEW_ZAP(LO_Element);
  2620.                         pDummy->lo_text.type = LO_TEXT;
  2621.                         pDummy->lo_text.anchor_href = pAnchorData;
  2622.                         // We use the text of the element to determine if it is still
  2623.                         // valid later so give the dummy text struct's text a value.
  2624.                         if (pDummy->lo_text.anchor_href->anchor)
  2625.                             pDummy->lo_text.text = pDummy->lo_text.anchor_href->anchor;
  2626.  
  2627.                         // We'll need the image element later in the callback.
  2628.                         pClosure->pElement = pElement;
  2629.  
  2630.                         // we are about to follow a link via a user click -- 
  2631.                         //   tell the mocha library.  Don't follow the link
  2632.                         //   until we get to our closure
  2633.                         JSEvent *event;
  2634.                         event = XP_NEW_ZAP(JSEvent);
  2635.                         event->type = EVENT_CLICK;
  2636.                         event->which = 1;
  2637.                             event->x = Point.x;
  2638.                         event->y = Point.y;
  2639.                         event->docx = Point.x + CL_GetLayerXOrigin(layer);
  2640.                         event->docy = Point.y + CL_GetLayerYOrigin(layer);
  2641.                         event->screenx = cpScreenPoint.x;
  2642.                         event->screeny = cpScreenPoint.y;
  2643.                         event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  2644.  
  2645.                         ET_SendEvent(GetContext(), pDummy, event, 
  2646.                                  win_click_callback, pClosure);
  2647.                     }
  2648.                     //    We're out, don't fall through.
  2649.                     return;
  2650.                 }
  2651.             }
  2652.             //    Check for ismaps, normal image anchors
  2653.             else if(pElement->lo_image.anchor_href != NULL && 
  2654.                 pElement->lo_image.anchor_href->anchor != NULL)
  2655.             {
  2656.                 // set tab_focus to this image element with a link.
  2657.                 //#52932 setFormElementTabFocus( (LO_Element *) pElement );
  2658.  
  2659.                 //    Ismap?
  2660.                 if(pElement->lo_image.image_attr->attrmask & LO_ATTR_ISMAP)
  2661.                 {
  2662.  
  2663.                     if(uFlags & MK_SHIFT && NOT_A_DIALOG(this))
  2664.                     {
  2665.                         char * pAnchor = PR_smprintf("%s?%d,%d", 
  2666.                                 pElement->lo_image.anchor_href->anchor, cpMap.x, cpMap.y);
  2667.                         CSaveCX::SaveAnchorObject(pAnchor, NULL);
  2668.                         XP_FREE(pClosure);
  2669.                         XP_FREE(pAnchor);
  2670.                     } 
  2671.                     else {
  2672.                         // set tab_focus to this image element with a link.
  2673.                         //#52932 setFormElementTabFocus((LO_Element *) pElement);
  2674.  
  2675.                         // remember where we are going
  2676.                         pClosure->x = cpMap.x;
  2677.                         pClosure->y = cpMap.y;
  2678.  
  2679.                         // we are about to follow a link via a user click -- 
  2680.                         //   tell the mocha library.  Don't follow the link
  2681.                         //   until we get to our closure
  2682.                         JSEvent *event;
  2683.                         event = XP_NEW_ZAP(JSEvent);
  2684.                         event->type = EVENT_CLICK;
  2685.                         event->which = 1;
  2686.                             event->x = Point.x;
  2687.                         event->y = Point.y;
  2688.                         event->docx = Point.x + CL_GetLayerXOrigin(layer);
  2689.                         event->docy = Point.y + CL_GetLayerYOrigin(layer);
  2690.                         event->screenx = cpScreenPoint.x;
  2691.                         event->screeny = cpScreenPoint.y;
  2692.                         event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  2693.  
  2694.                         ET_SendEvent(GetContext(), pElement, event, 
  2695.                                  win_click_callback, pClosure);
  2696.                     }
  2697.                 }
  2698.                 //    Anchor.
  2699.                 else {
  2700.                     if(uFlags & MK_SHIFT && NOT_A_DIALOG(this)) {
  2701.                         //  Should mocha block save operations too?
  2702.                         CSaveCX::SaveAnchorObject((const char *)pElement->lo_image.anchor_href->anchor, NULL);
  2703.                         XP_FREE(pClosure);
  2704.                     }
  2705.                     else {
  2706.                         // we are about to follow a link via a user click -- 
  2707.                         //   tell the mocha library.  Don't follow the link
  2708.                         //   until we get to our closure
  2709.                         JSEvent *event;
  2710.                         event = XP_NEW_ZAP(JSEvent);
  2711.                         event->type = EVENT_CLICK;
  2712.                         event->which = 1;
  2713.                         event->x = Point.x;
  2714.                         event->y = Point.y;
  2715.                         event->docx = Point.x + CL_GetLayerXOrigin(layer);
  2716.                         event->docy = Point.y + CL_GetLayerYOrigin(layer);
  2717.                         event->screenx = cpScreenPoint.x;
  2718.                         event->screeny = cpScreenPoint.y;
  2719.                         event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  2720.                             
  2721.                         ET_SendEvent(GetContext(), pElement, event, 
  2722.                                  win_click_callback, pClosure);
  2723.                     }
  2724.                 }
  2725.  
  2726.                 //    We're out, don't fall through.
  2727.                 return;
  2728.             }
  2729.  
  2730.             //    Check for images as submit buttons.
  2731.             //    Lot's of these on test pages, but in the real world?
  2732.             if(pElement->lo_image.image_attr && 
  2733.               (pElement->lo_image.image_attr->attrmask & LO_ATTR_ISFORM))
  2734.             {
  2735.                 pClosure->x = cpMap.x;
  2736.                 pClosure->y = cpMap.y;
  2737.  
  2738.                 JSEvent *event;
  2739.                 event = XP_NEW_ZAP(JSEvent);
  2740.                 event->type = EVENT_SUBMIT;
  2741.                     event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  2742.  
  2743.                 ET_SendEvent(GetContext(), (LO_Element *)&pElement->lo_image, event,
  2744.                          image_form_click_callback, pClosure);
  2745.  
  2746.                 return;
  2747.             }
  2748.             break; // case LO_IMAGE
  2749.         }
  2750.  
  2751.         default:
  2752.             //    nothing doing.
  2753.             XP_FREE(pClosure);        
  2754.             break;
  2755.     }
  2756.  
  2757. MOUSE_TIMER:
  2758.     //  Have the mouse timer handler do some dirty work.
  2759.     //  Please don't return in the above code, I'd like this to get called
  2760.     //      in all cases with the state of the buttons set correctly.
  2761.     MouseTimerData mt(GetContext());
  2762.     FEU_MouseTimer(&mt);
  2763. }
  2764.  
  2765.  
  2766. // convert LO_Text to a bookmark object we can drag into
  2767. //  the bookmark window
  2768. PRIVATE HGLOBAL 
  2769. wfe_textObjectToBookmarkHandle(LO_TextStruct * text, char * title)
  2770. {
  2771.     if(!text)
  2772.         return(NULL);
  2773.  
  2774.     HGLOBAL hBookmark = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(BOOKMARKITEM));
  2775.     if(!hBookmark)
  2776.         return(NULL);
  2777.  
  2778.     LPBOOKMARKITEM pBookmark = (LPBOOKMARKITEM)GlobalLock(hBookmark);
  2779.  
  2780.     if(text->anchor_href && text->anchor_href->anchor)
  2781.         PR_snprintf(pBookmark->szAnchor,sizeof(pBookmark->szAnchor),"%s",text->anchor_href->anchor);
  2782.  
  2783.     if( title ) {
  2784.         // First try to use the title supplied,
  2785.         // This may contain more text than the text structure has
  2786.         PR_snprintf(pBookmark->szText,sizeof(pBookmark->szText),"%s",title);
  2787.     } else if(text->text) {
  2788.         PR_snprintf(pBookmark->szText,sizeof(pBookmark->szText),"%s",text->text);
  2789.     }
  2790.  
  2791.     GlobalUnlock(hBookmark);
  2792.  
  2793.     return hBookmark;
  2794. }
  2795.  
  2796. // Creates OLE drag data source for selected text
  2797. void CWinCX::DragSelection()
  2798. {            
  2799.     // Begin the drag and drop operation
  2800.     // REMEMBER: OnDrop: Check if end pt is withing selection,
  2801.     //   if yes, ignore drop
  2802.     MWContext  * pMWContext = GetContext();
  2803.  
  2804. #ifdef EDITOR
  2805.     // Don't bother if no selection or not allowed in Editor
  2806.     if ( EDT_IS_EDITOR(pMWContext) && 
  2807.          EDT_COP_OK != EDT_CanCopy(pMWContext, TRUE))
  2808.       return;
  2809. #endif // EDITOR
  2810.     
  2811.     // Here's where we put the data
  2812.     COleDataSource * pDataSource = new COleDataSource;  
  2813.     // This is used to override cursors during dragging
  2814.     UINT nDragType = FE_DRAG_TEXT;
  2815. #ifdef EDITOR
  2816.     if( EDT_IS_EDITOR(pMWContext) )
  2817.     {
  2818.         nDragType = EDT_IsDraggingTable(pMWContext) ? FE_DRAG_TABLE : FE_DRAG_HTML;
  2819.     }
  2820. #endif    
  2821.     CViewDropSource * pDropSource = new CViewDropSource(nDragType);
  2822.     
  2823.     char* pText = NULL;
  2824.     XP_HUGE_CHAR_PTR pGlobal;
  2825.     XP_HUGE_CHAR_PTR pHTML;
  2826.     int32  textLen = 0;
  2827.     int32  htmlLen;
  2828.     m_bDragging = FALSE;
  2829. #ifdef EDITOR
  2830.     if( EDT_IS_EDITOR(pMWContext) ){
  2831.         if( EDT_COP_OK == EDT_CanCopy(pMWContext, TRUE) &&
  2832.             EDT_COP_OK == EDT_CopySelection(pMWContext, &pText, &textLen, &pHTML, &htmlLen) ){
  2833.             // Put HTML-formated text in OLE data object
  2834.             HGLOBAL hHTML = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, (int)htmlLen);
  2835.             if(hHTML) {
  2836.                 pGlobal = (char *) GlobalLock(hHTML);
  2837.                 XP_HUGE_MEMCPY(pGlobal, pHTML, (int) htmlLen);
  2838.                 XP_HUGE_FREE(pHTML);
  2839.                 GlobalUnlock(hHTML);
  2840.                 pDataSource->CacheGlobalData(RegisterClipboardFormat(NETSCAPE_EDIT_FORMAT), hHTML);
  2841.                 m_bDragging = TRUE;
  2842.             }
  2843.         }
  2844.     }
  2845.     else 
  2846. #endif // EDITOR
  2847.     {
  2848.         // Browser-only
  2849.         pText = (char *) LO_GetSelectionText(GetDocumentContext());
  2850.         if( pText )
  2851.             textLen = XP_STRLEN(pText);
  2852.     }
  2853.  
  2854.     // Put unformated text in OLE data object - may be dropped in other containers
  2855.     HGLOBAL hText = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, (int)textLen+1);
  2856.     DROPEFFECT res = 0;
  2857.     if( pText && textLen > 0 ){
  2858.  #ifdef XP_WIN32
  2859.     // Also try to put CF_UNICODETEXT
  2860.         int datacsid = INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo( GetDocumentContext() )) & ~CS_AUTO;
  2861.         if((CS_USER_DEFINED_ENCODING != datacsid) && (0 != datacsid))
  2862.         {
  2863.             int len = (INTL_StrToUnicodeLen(datacsid, (unsigned char*)pText)+1) * 2;
  2864.             HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (DWORD) len);
  2865.             if(hData)
  2866.             {
  2867.                 unsigned char* string = (unsigned char *) GlobalLock(hData);
  2868.                 if(string)
  2869.                 {
  2870.                     INTL_StrToUnicode(datacsid, (unsigned char*)pText, (INTL_Unicode*)string, len);
  2871.             
  2872.                     GlobalUnlock(hData);    
  2873.                     pDataSource->CacheGlobalData(CF_UNICODETEXT, hData);
  2874.                 }
  2875.             }
  2876.         }
  2877. #endif
  2878.         if(hText) {
  2879.             pGlobal = (char *) GlobalLock(hText);
  2880.             XP_MEMCPY(pGlobal, pText, (int) textLen+1);
  2881.             XP_FREE(pText);
  2882.             GlobalUnlock(hText);
  2883.             pDataSource->CacheGlobalData(CF_TEXT, hText);
  2884.             m_bDragging = TRUE;
  2885.         }
  2886.     }
  2887.  
  2888.     if( m_bDragging ){
  2889.         BOOL bWaitingMode = pMWContext->waitingMode;
  2890.         // Prevent closing/interaction with source window while dragging
  2891.         pMWContext->waitingMode = TRUE;
  2892.         
  2893.         res = pDataSource->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_SCROLL,
  2894.                                                  NULL, pDropSource);
  2895.         pMWContext->waitingMode = bWaitingMode;
  2896.     }
  2897.     m_bDragging = FALSE;
  2898.  
  2899. #ifdef EDITOR
  2900.     if( EDT_IS_EDITOR(pMWContext) ){
  2901.         EDT_StopDragTable(pMWContext);
  2902.     }
  2903. #endif
  2904.     // Prevent selection-extension when finished
  2905.     m_bLBDown = FALSE;
  2906.     m_bLBUp = TRUE;
  2907.     
  2908.     // its over so clean up
  2909.     pDataSource->Empty();
  2910.     delete pDataSource;
  2911.     delete pDropSource;
  2912. }
  2913.  
  2914. // Triggered on button up on our bitmap on the menu
  2915. void CWinCX::CopyCurrentURL()
  2916. {
  2917.     MWContext *pMWContext = GetContext();
  2918.     if ( pMWContext == NULL ) {
  2919.         return;
  2920.     } 
  2921.  
  2922.     History_entry * hist_ent = SHIST_GetCurrent(&(pMWContext->hist));
  2923.     if ( hist_ent == NULL || hist_ent->address == NULL ){
  2924.         return;
  2925.     }
  2926.     HGLOBAL hData = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, 
  2927.                                 XP_STRLEN((char *) hist_ent->address) + 2);
  2928.     if(!hData) {
  2929.         return;
  2930.     }
  2931.     // lock the string and copy the data over
  2932.     char * pString = (char *) GlobalLock(hData);
  2933.     strcpy(pString, (char *) hist_ent->address);
  2934.     GlobalUnlock(hData);
  2935.  
  2936.     GetFrame()->GetFrameWnd()->OpenClipboard();
  2937.     ::EmptyClipboard();
  2938.     ::SetClipboardData(CF_TEXT, hData);
  2939.  
  2940.     // Also copy bookmark-formatted data so we can paste full link,
  2941.     //  not just text, into the Editor
  2942.     hData = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(BOOKMARKITEM));
  2943.     if(hData){
  2944.         LPBOOKMARKITEM pBookmark = (LPBOOKMARKITEM)GlobalLock(hData);
  2945.         PR_snprintf(pBookmark->szAnchor, sizeof(pBookmark->szAnchor), "%s",
  2946.                     hist_ent->address);
  2947.         PR_snprintf(pBookmark->szText, sizeof(pBookmark->szText), "%s",
  2948.                     hist_ent->title);
  2949.         GlobalUnlock(hData);
  2950.         ::SetClipboardData(RegisterClipboardFormat(NETSCAPE_BOOKMARK_FORMAT), hData);
  2951.     }
  2952.     ::CloseClipboard();
  2953. }
  2954.  
  2955. // Drag from the Bitmap Menu item or URL bar icon
  2956. void CWinCX::DragCurrentURL()
  2957. {
  2958.     MWContext *pMWContext = GetContext();
  2959.     if ( pMWContext == NULL ) {
  2960.         return;
  2961.     } 
  2962.  
  2963.     History_entry * hist_ent = SHIST_GetCurrent(&(pMWContext->hist));
  2964.     if ( hist_ent == NULL || hist_ent->address == NULL ){
  2965.         return;
  2966.     }
  2967.     HGLOBAL hAddrString = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, 
  2968.                                       XP_STRLEN((char *) hist_ent->address) + 2);
  2969.     if(!hAddrString) {
  2970.         return;
  2971.     }
  2972.  
  2973.     // lock the string and copy the data over
  2974.     char * pAddrString = (char *) GlobalLock(hAddrString);
  2975.     strcpy(pAddrString, (char *) hist_ent->address);
  2976.  
  2977.     GlobalUnlock(hAddrString);
  2978.  
  2979.     HGLOBAL hBookmark = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(BOOKMARKITEM));
  2980.     if(!hBookmark) {
  2981.         return;
  2982.     }
  2983.     LPBOOKMARKITEM pBookmark = (LPBOOKMARKITEM)GlobalLock(hBookmark);
  2984.     PR_snprintf(pBookmark->szAnchor,sizeof(pBookmark->szAnchor),"%s",hist_ent->address);
  2985.     PR_snprintf(pBookmark->szText,sizeof(pBookmark->szText),"%s",hist_ent->title);
  2986.     GlobalUnlock(hBookmark);
  2987.  
  2988.     // Create the DataSourceObject
  2989.     COleDataSource * pDataSource = new COleDataSource;  
  2990.     pDataSource->CacheGlobalData(CF_TEXT, hAddrString);
  2991.     pDataSource->CacheGlobalData(RegisterClipboardFormat(NETSCAPE_BOOKMARK_FORMAT), hBookmark);
  2992.     // This is used to override cursors during dragging
  2993.     CViewDropSource * pDropSource = new CViewDropSource(FE_DRAG_LINK);
  2994.  
  2995.     DragInternetShortcut ( pDataSource,
  2996.         (char*)hist_ent->title,
  2997.         (char*)hist_ent->address );
  2998.  
  2999.     // do the drag/drop operation.
  3000.     // set the m_bDragging flag so that we can prevent ourseleves from dropping on
  3001.     //   ourselves                
  3002.     
  3003.     m_bDragging = TRUE;
  3004.     // no saved image for next time
  3005.     // Must do this before DoDragDrop to prevent
  3006.     //  arriving here again!
  3007.     m_pLastImageObject = NULL;
  3008.     m_pLastArmedAnchor = NULL;
  3009.  
  3010.     // Don't start drag until outside this rect    
  3011.     RECT rectDragStart = {0,0,20,20};
  3012.  
  3013.     // We supply the DropSource object instead of default behavior
  3014.     // This prevents closing source frame during drag and drop
  3015.     BOOL bWaitingMode = pMWContext->waitingMode;
  3016.     pMWContext->waitingMode = TRUE;
  3017.     
  3018.     pDataSource->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_SCROLL,
  3019.                             &rectDragStart, pDropSource);
  3020.     
  3021.     pMWContext->waitingMode = bWaitingMode;
  3022.     m_bDragging = FALSE;
  3023.  
  3024.     // After dragging, moving mouse in browser acts like button is down,
  3025.     //  and ugly selection extension happens. This prevents that.
  3026.     m_bLBDown = FALSE;
  3027.     m_bLBUp = TRUE;
  3028.  
  3029.     // its over so clean up
  3030.     pDataSource->Empty();
  3031.     delete pDataSource;
  3032.     delete pDropSource;
  3033. }
  3034.  
  3035. void wfe_Progress(MWContext *pContext, const char *pMessage);
  3036.  
  3037. void CWinCX::OnMouseMoveCX(UINT uFlags, CPoint cpPoint, BOOL &bReturnImmediately)    
  3038. {
  3039.     //    Must have a view to continue.
  3040.     if(GetPane() == NULL)    {
  3041.         return;
  3042.     }
  3043.  
  3044.     //    Don't continue if this context is destroyed.
  3045.     if(IsDestroyed())    {
  3046.         return;
  3047.     }
  3048.  
  3049.     // This is set TRUE only by CNetscapeEditView::OnRButtonDown
  3050.     //   while popup menu is active
  3051.     // We ignore this message else it changes cursor to something inappropriate
  3052.     if( m_bInPopupMenu )
  3053.         return;
  3054.  
  3055.     //    Remember....
  3056.     m_LastMouseEvent = m_MMove;
  3057.     m_cpMMove = cpPoint;
  3058.     m_uMouseFlags = uFlags;
  3059.  
  3060.     // Convert from screen to window coordinates
  3061.     XY xyPoint;
  3062.     ResolvePoint(xyPoint, cpPoint);
  3063.  
  3064. #ifdef LAYERS
  3065.     MWContext  * context  = GetContext();
  3066.     if (context->compositor) {
  3067.         CL_Event event;
  3068.         fe_EventStruct fe_event;
  3069.         
  3070.         fe_event.uFlags = uFlags;
  3071.         fe_event.x = cpPoint.x;
  3072.         fe_event.y = cpPoint.y;
  3073.         fe_event.pbReturnImmediately = bReturnImmediately;
  3074.         
  3075.         event.type = CL_EVENT_MOUSE_MOVE;
  3076.         event.fe_event = (void *)&fe_event;
  3077.         event.fe_event_size = sizeof(fe_EventStruct);
  3078.         event.x = xyPoint.x;
  3079.         event.y = xyPoint.y;
  3080.         event.which = 1;
  3081.             event.modifiers = 0;
  3082.         
  3083.         CL_DispatchEvent(context->compositor, &event);
  3084.     }
  3085.     else 
  3086.         OnMouseMoveForLayerCX(uFlags, cpPoint, xyPoint, NULL, bReturnImmediately);
  3087.  
  3088.     //  Have the mouse timer handler do some dirty work.
  3089.     MouseTimerData mt(GetContext());
  3090.     FEU_MouseTimer(&mt);
  3091.     return;
  3092. }
  3093.  
  3094. void
  3095. CWinCX::OnMouseMoveForLayerCX(UINT uFlags, CPoint& cpPoint,
  3096.                   XY& xyPoint, CL_Layer *layer, BOOL &bReturnImmediately)
  3097. {
  3098. // With LAYERS turned on, the orginal method 
  3099. // OnMouseMoveCX is separated into two methods,
  3100. // one of which is a per-layer method.
  3101. #endif /* LAYERS */
  3102.  
  3103.     MWContext  * context  = GetContext();
  3104.  
  3105.     BOOL bTextSet = FALSE;
  3106.  
  3107.     LO_Element *pElement = GetLayoutElement(xyPoint, layer);
  3108.     if (pElement && (pElement->type == LO_IMAGE)) {
  3109.         LO_ImageStruct* pImage = &pElement->lo_image;
  3110.         if (pImage) {
  3111.             CreateToolTip(pImage, cpPoint, layer);
  3112.             RelayToolTipEvent(cpPoint, WM_MOUSEMOVE);
  3113.         }
  3114.     }
  3115.  
  3116.     int32 xVal = xyPoint.x;
  3117.     int32 yVal = xyPoint.y;
  3118.  
  3119.     // don't do anything if we are waiting for the netlib to get
  3120.     //   into gear
  3121.     if (context->waitingMode) {
  3122.         // Change cursor only if not doing internal drag
  3123.         if( !m_bDragging ){
  3124.             SetCursor(theApp.LoadStandardCursor(IDC_WAIT));
  3125.         }
  3126.         return;  // can't load while loading
  3127.     }
  3128.  
  3129.     // Note: don't use (uFlags & MK_LBUTTON) because this is
  3130.     //    reported as TRUE on a mouse move message
  3131.     //    following a click off of a dialog or popup menu
  3132.     //
  3133.     if ( m_bLBDown )
  3134.     {
  3135. #ifdef EDITOR
  3136.         // If we are selecting cells, skip the rest
  3137.         if( m_bSelectingCells )
  3138.         {
  3139.             // We must fire an event to setup CLOSURE struct
  3140.             //   and call mouse_closure_callback
  3141.             FireMouseOverEvent(NULL, xVal, yVal, layer);
  3142.             goto MOUSE_TIMER;
  3143.         }
  3144.         if( EDT_IS_SIZING )
  3145.         {
  3146.             // We are sizing 
  3147.             
  3148.             BOOL bLock = !(BOOL)(uFlags & MK_CONTROL);
  3149.             XP_Rect new_rect;
  3150.             if( EDT_GetSizingRect(context, xVal, yVal, bLock, &new_rect) )
  3151.             {
  3152.                 // Remove last sizing feedback
  3153.                 DisplaySelectionFeedback(LO_ELE_SELECTED, m_rectSizing);
  3154.                 // Save the new rect.
  3155.                 m_rectSizing.left = new_rect.left;
  3156.                 m_rectSizing.right = new_rect.right;
  3157.                 m_rectSizing.top = new_rect.top;
  3158.                 m_rectSizing.bottom = new_rect.bottom;
  3159.                 // then draw new feedback
  3160.                 DisplaySelectionFeedback(LO_ELE_SELECTED, m_rectSizing);
  3161.  
  3162.             }
  3163.             // Status text was set by XP code, so set flag here
  3164.             bTextSet = TRUE;
  3165.             goto MOUSE_TIMER;
  3166.         }
  3167.         // Check for cell selection only if not starting drag of table cells
  3168.         if( !EDT_IsDraggingTable(context) )
  3169.         {
  3170.             // We are not currently selecting cells, so get the cell we may be over
  3171.             // Note: This will return cell and ED_HIT_SIZE_COL if inbetween columns,
  3172.             //    so check that because we don't want to select cell if just before the left edge
  3173.             LO_Element *pCellElement = NULL;
  3174.             // Mouse move test with left button down - extend selection to other cells
  3175.             ED_HitType iTableHit = EDT_GetTableHitRegion(context, xVal, yVal, &pCellElement, FALSE);
  3176.             if( m_pStartSelectionCell && pCellElement && 
  3177.                 (iTableHit != ED_HIT_SIZE_COL) &&
  3178.                 pCellElement->type == LO_CELL && (pCellElement != m_pStartSelectionCell) )
  3179.             {
  3180.                 m_bSelectingCells = TRUE;
  3181.                 if( m_pStartSelectionCell )
  3182.                 {
  3183.                     // Mouse is in a different cell then when we started selecting
  3184.                     // So switch to cell-selection mode. 
  3185.                     // 1st FALSE param means clear any other selection (shouldn't be any)
  3186.                     //     (last param is used to extend selection)
  3187.                     EDT_SelectTableElement(context, m_pStartSelectionCell->lo_any.x, m_pStartSelectionCell->lo_any.y,
  3188.                                            m_pStartSelectionCell, ED_HIT_SEL_CELL, FALSE, FALSE);
  3189.                 }
  3190.                 // Select new cell as well: If previously selecting, last param = TRUE
  3191.                 //  and we append this cell
  3192.                 EDT_SelectTableElement(context, xVal, yVal, pCellElement, ED_HIT_SEL_CELL, 
  3193.                                        FALSE, m_pStartSelectionCell != NULL);
  3194.                 goto MOUSE_TIMER;
  3195.             }
  3196.         }
  3197. #endif // EDITOR
  3198.  
  3199.         // Don't bother to do selection or dragging unless we actually moved
  3200.         if( (abs(cpPoint.x - m_cpLBDown.x) > 5)
  3201.               || (abs(cpPoint.y - m_cpLBDown.y) > 5) )
  3202.         {
  3203.             if( m_bMouseInSelection )
  3204.             {
  3205.                 // release the mouse capture
  3206.                 ::ReleaseCapture();
  3207.                 m_bMouseInSelection = FALSE;
  3208.  
  3209.                 // Get and drag the selection
  3210.                 DragSelection();
  3211.                 // Don't do anything else if we are dragging!
  3212.                 goto MOUSE_TIMER;
  3213.             }
  3214.             // Extend the selection
  3215. #ifdef EDITOR
  3216.             if( EDT_IS_EDITOR(context) )
  3217.             {
  3218.                 EDT_ExtendSelection(context, xVal, yVal);
  3219.             } else 
  3220. #endif // EDITOR
  3221.             {
  3222.                 LO_ExtendSelection(GetDocumentContext(), xVal, yVal);
  3223.             }
  3224.         }
  3225.  
  3226.         int32 lYPos = GetOriginY();
  3227.         int32 lXPos = GetOriginX();
  3228.         int32 xCur = xVal;
  3229.         int32 yCur = yVal;
  3230. #ifdef LAYERS
  3231.         if (layer)
  3232.         {
  3233.             int32 layer_x_offset = CL_GetLayerXOrigin(layer);
  3234.             int32 layer_y_offset = CL_GetLayerYOrigin(layer);
  3235.  
  3236.             xCur += layer_x_offset;
  3237.             yCur += layer_y_offset;
  3238.         }
  3239. #endif // LAYERS
  3240.         if(xCur < GetOriginX())    {
  3241.             lXPos = xCur;
  3242.         }
  3243.         else if(xCur > GetWidth() + GetOriginX())    {
  3244.             lXPos = xCur - GetWidth();
  3245.         }
  3246.  
  3247.         if(yCur < GetOriginY())    {
  3248.             lYPos = yCur;
  3249.         }
  3250.         else if(yVal > GetHeight() + GetOriginY())    {
  3251.             lYPos = yCur - GetHeight();
  3252.         }
  3253.  
  3254.         //    Validate position recommendations, and reposition if necessary.
  3255.         if(lXPos > GetDocumentWidth() - GetWidth())    {
  3256.             lXPos = GetDocumentWidth() - GetWidth();
  3257.         }
  3258.         if(lXPos < 0)    {
  3259.             lXPos = GetOriginX();
  3260.         }
  3261.         if(lYPos > GetDocumentHeight() - GetHeight())    {
  3262.             lYPos = GetDocumentHeight() - GetHeight();
  3263.         }
  3264.         if(lYPos < 0)    {
  3265.             lYPos = GetOriginY();
  3266.         }
  3267.  
  3268.         if(lYPos != GetOriginY() || lXPos != GetOriginX())    {
  3269.             //    Reposition.
  3270.             SetDocPosition(context, FE_VIEW, lXPos, lYPos);
  3271.         }
  3272.  
  3273.         // We need to unhighlight an anchor if we highlighted it on buttonDown
  3274.         // The anchor element is held within the last_armed_xref global
  3275.         // If last_armed_xref is non-null then the anchor is highlighted and
  3276.         // needs to be unhighlighted and a drag and drop operation started.
  3277.         if( m_pLastArmedAnchor && !EDT_IS_EDITOR(context) ) {
  3278.             if(abs(m_cpMMove.x - m_cpLBDown.x) > CLICK_THRESHOLD ||
  3279.                 abs(m_cpMMove.y - m_cpLBDown.y) > CLICK_THRESHOLD)    {
  3280.  
  3281.                 LO_HighlightAnchor(GetDocumentContext(), m_pLastArmedAnchor, FALSE);
  3282.  
  3283.                 // Convert the selection into stuff other people can understand
  3284.  
  3285.                 LO_TextStruct * text = (LO_TextStruct *) m_pLastArmedAnchor;
  3286.                 if(!text)
  3287.                     goto MOUSE_TIMER;
  3288.  
  3289.                 int len = XP_STRLEN((char *) text->anchor_href->anchor) + 2;
  3290.  
  3291.                 // make an assumption that will bite us later.  Shove everything into
  3292.                 //   global space cuz it will be small
  3293.                 HGLOBAL hAddrString = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, len);
  3294.                 if(!hAddrString)
  3295.                     goto MOUSE_TIMER;
  3296.  
  3297.                 // lock the string and copy the data over
  3298.                 char * pAddrString = (char *) GlobalLock(hAddrString);
  3299.                 strcpy(pAddrString, (char *) text->anchor_href->anchor);
  3300.  
  3301.                 GlobalUnlock(hAddrString);
  3302.  
  3303.                 //CLM: Select the full link object, which scans  neighboring text elements
  3304.                 //     to gather text that may have different formatting but same HREF
  3305.                 XY Point;
  3306.                 ResolvePoint(Point, m_cpLBDown);
  3307. #ifdef LAYERS
  3308.                 LO_SelectObject(GetDocumentContext(), Point.x, Point.y, NULL);
  3309. #else
  3310.                 LO_SelectObject(GetDocumentContext(), Point.x, Point.y);
  3311. #endif /* LAYERS */
  3312.                 // check to see if its an address book url.  If it is convert it to 
  3313.                 // vcard clipboard format
  3314.                 COleDataSource * pDataSource = NULL;
  3315.                 CViewDropSource * pDropSource = NULL;
  3316.                 char * url = (char*) text->anchor_href->anchor;
  3317.                 char * path = NET_ParseURL((char *) text->anchor_href->anchor, GET_PATH_PART);
  3318.                 char * search = NET_ParseURL((char *) text->anchor_href->anchor, GET_SEARCH_PART);
  3319.                 if (!XP_STRNCASECMP(path,"add",3)) {
  3320.                     if (!XP_STRNCASECMP (search, "?vcard=", 7)) {
  3321.                         // Create the DataSourceObject
  3322.                         CLIPFORMAT mVcardClipboardFormat = (CLIPFORMAT)RegisterClipboardFormat(vCardClipboardFormat);
  3323.                         char * escVcard = XP_STRDUP (search+7);
  3324.                         if (escVcard) {
  3325.                             escVcard = NET_UnEscape(escVcard);
  3326.                             HANDLE hString = 0;
  3327.                             hString = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT,strlen(escVcard)+1);
  3328.                             LPSTR lpszString = (LPSTR)GlobalLock(hString);
  3329.                             strcpy(lpszString, escVcard);
  3330.                             GlobalUnlock(hString);
  3331.                             XP_FREEIF (escVcard);
  3332.                             pDataSource = new COleDataSource;  
  3333.                             pDataSource->CacheGlobalData(mVcardClipboardFormat, hString);
  3334.                             pDataSource->CacheGlobalData(CF_TEXT, hString);
  3335.                             pDropSource = new CViewDropSource(FE_DRAG_VCARD);
  3336.                         }
  3337.                     }
  3338.                 }
  3339.                 else {
  3340.  
  3341.                     char *pFullLink = (char *) LO_GetSelectionText(GetDocumentContext());
  3342.  
  3343.                     HGLOBAL hBookmark = wfe_textObjectToBookmarkHandle(text, pFullLink);
  3344.  
  3345.                     // make sure we have a bookmark format defined
  3346.                     CLIPFORMAT mBookmarkClipboardFormat = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_BOOKMARK_FORMAT);
  3347.  
  3348.                     // Create the DataSourceObject
  3349.                     pDataSource = new COleDataSource;  
  3350.                     pDataSource->CacheGlobalData(CF_TEXT, hAddrString);
  3351.                     pDataSource->CacheGlobalData(mBookmarkClipboardFormat, hBookmark);
  3352.  
  3353.                     // This is used to override cursors during dragging
  3354.                     pDropSource = new CViewDropSource(FE_DRAG_LINK);
  3355.  
  3356.                     DragInternetShortcut ( pDataSource,
  3357.                         pFullLink ? pFullLink : (char*)text->text,
  3358.                         (char*)text->anchor_href->anchor );
  3359.                 }
  3360.  
  3361.                 // do the drag/drop operation.
  3362.                 // set the m_bDragging flag so that we can prevent ourseleves from dropping on
  3363.                 //   ourselves                
  3364.                 m_bDragging = TRUE;
  3365.                // Must do this before DoDragDrop to prevent
  3366.                //  arriving here again!
  3367.                 m_pLastArmedAnchor = NULL;
  3368.                 m_pLastImageObject = NULL;
  3369.                 
  3370.                 // This prevents closing source frame during drag and drop
  3371.                 BOOL bWaitingMode = context->waitingMode;
  3372.                 context->waitingMode = TRUE;
  3373.                 
  3374.                 // We supply the DropSource object instead of default behavior
  3375.                 // (we don't need return value, do we?)
  3376.                 pDataSource->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_SCROLL,
  3377.                                         NULL, pDropSource);
  3378.                 
  3379.                 context->waitingMode = bWaitingMode;
  3380.                 m_bDragging = FALSE;
  3381.  
  3382.                 // After dragging, moving mouse in browser acts like button is down,
  3383.                 //  and ugly selection extension happens. This prevents that.
  3384.                 m_bLBDown = FALSE;
  3385.                 m_bLBUp = TRUE;
  3386.  
  3387.                 // its over so clean up
  3388.                 pDataSource->Empty();
  3389.                 delete pDataSource;
  3390.                 delete pDropSource;
  3391.             }
  3392.         }
  3393. #ifdef EDITOR
  3394.         // Drag image from an Editor or Browser
  3395.         else if ( m_pLastImageObject &&
  3396.                   (abs(m_cpMMove.x - m_cpLBDown.x) > CLICK_THRESHOLD ||
  3397.                    abs(m_cpMMove.y - m_cpLBDown.y) > CLICK_THRESHOLD) ) {
  3398.             
  3399.             LO_ImageStruct *pImage = (LO_ImageStruct *)m_pLastImageObject;
  3400.             char *pImageURL = NULL;
  3401.  
  3402.             HGLOBAL hImageData = WFE_CreateCopyImageData(context, pImage);
  3403.             if ( hImageData ) {
  3404.  
  3405.                 // make sure we have a clipboard format defined
  3406.                 CLIPFORMAT mImageFormat = (CLIPFORMAT)RegisterClipboardFormat(
  3407.                                                 NETSCAPE_IMAGE_FORMAT);
  3408.  
  3409.                 // Create the DataSourceObject
  3410.                 COleDataSource * pDataSource = new COleDataSource;  
  3411.                 pDataSource->CacheGlobalData(mImageFormat, hImageData);
  3412.  
  3413.                 // This is used to override cursors during dragging
  3414.                 CViewDropSource * pDropSource = new CViewDropSource(FE_DRAG_IMAGE);
  3415.  
  3416.                 // do the drag/drop operation.
  3417.                 // set the m_bDragging flag so that we can prevent ourseleves from dropping on
  3418.                 //   ourselves                
  3419.                 m_bDragging = TRUE;
  3420.                 // no saved image for next time
  3421.                 m_pLastImageObject = NULL;
  3422.                 m_pLastArmedAnchor = NULL;
  3423.  
  3424.                 //Weird problem:
  3425.                 //  Return from dropping after InsertImage
  3426.                 //  sometimes results in hourglass cursor
  3427.                 // So save and restore after DoDragDrop
  3428.                 HCURSOR hCursor = GetCursor();
  3429.  
  3430.                 // This prevents closing source frame during drag and drop
  3431.                 BOOL bWaitingMode = context->waitingMode;
  3432.                 context->waitingMode = TRUE;
  3433.  
  3434.                 pDataSource->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_SCROLL,
  3435.                                         NULL, pDropSource);
  3436.                 
  3437.                 context->waitingMode = bWaitingMode;
  3438.                 SetCursor(hCursor);
  3439.                 m_bDragging = FALSE;
  3440.  
  3441.                 // Prevent selection mode when returning to browser
  3442.                 m_bLBDown = FALSE;
  3443.                 m_bLBUp = TRUE;
  3444.  
  3445.                 // its over so clean up
  3446.                 pDataSource->Empty();
  3447.                 delete pDataSource;
  3448.                 delete pDropSource;
  3449.             }
  3450.         }
  3451. #endif // EDITOR
  3452.     }
  3453.     else {    // Left button is not down...
  3454.  
  3455.         // If there are connections being initiated (i.e. the watch 
  3456.         //   cursor is up) don't blow away the text so that the netlib 
  3457.         //   messages persist in the status bar
  3458.         if(context->waitingMode)
  3459.             goto MOUSE_TIMER;
  3460.  
  3461. #ifdef LAYERS
  3462.         LO_Element *lo_element = LO_XYToElement(GetDocumentContext(), xVal, yVal, layer);
  3463. #else
  3464.         LO_Element *lo_element = LO_XYToElement(GetDocumentContext(), xVal, yVal);
  3465. #endif /* LAYERS */
  3466.  
  3467.         //  Handle mouse over event processing with back end libs.
  3468.         if(!bTextSet)   {
  3469.             // Let the backend take a crack at handling the text
  3470.             FireMouseOverEvent(lo_element,xVal, yVal, layer);
  3471.  
  3472.             // if the backend didn't set the text we will set the
  3473.             //   text in our closure --- don't do anything else
  3474.             //   in this routine
  3475.         }
  3476.     }
  3477.  
  3478. MOUSE_TIMER:
  3479.     //  Have the mouse timer handler do some dirty work.
  3480.     //  Please don't return in the above code, I'd like this to get called
  3481.     //      in all cases with the state of the buttons set correctly.
  3482.     MouseTimerData mt(context);
  3483.     FEU_MouseTimer(&mt);
  3484.  
  3485. }
  3486.  
  3487. void CWinCX::OnRButtonDblClkCX(UINT uFlags, CPoint cpPoint)    {
  3488.     //    Only do this if clicking is enabled.
  3489.     if(IsClickingEnabled() == FALSE)    {
  3490.         return;
  3491.     }
  3492.  
  3493.     //    Don't continue if this context is destroyed.
  3494.     if(IsDestroyed())    {
  3495.         return;
  3496.     }
  3497.  
  3498.     XY xyPoint;
  3499.     ResolvePoint(xyPoint, cpPoint);
  3500.  
  3501.     if (GetContext()->compositor) {
  3502.         CL_Event event;
  3503.         fe_EventStruct fe_event;
  3504.         
  3505.         fe_event.uFlags = uFlags;
  3506.         fe_event.x = cpPoint.x;
  3507.         fe_event.y = cpPoint.y;
  3508.         
  3509.         event.type = CL_EVENT_MOUSE_BUTTON_MULTI_CLICK;
  3510.         event.fe_event = (void *)&fe_event;
  3511.         event.fe_event_size = sizeof(fe_EventStruct);
  3512.         event.x = xyPoint.x;
  3513.         event.y = xyPoint.y;
  3514.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  3515.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  3516.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  3517.         event.which = 3;
  3518.         event.data = 2;
  3519.     
  3520.         CL_DispatchEvent(GetContext()->compositor, &event);
  3521.     }
  3522.     else 
  3523.         OnRButtonDblClkForLayerCX(uFlags, cpPoint, xyPoint, NULL);
  3524.  
  3525.  
  3526.     //  Have the mouse timer handler do some dirty work.
  3527.     //  Please don't return in the above code, I'd like this to get called
  3528.     //      in all cases with the state of the buttons set correctly.
  3529.     MouseTimerData mt(GetContext());
  3530.     FEU_MouseTimer(&mt);
  3531. }
  3532.  
  3533. void
  3534. CWinCX::OnRButtonDblClkForLayerCX(UINT uFlags, CPoint& cpPoint,
  3535.                 XY& Point, CL_Layer *layer)
  3536. {
  3537. // With LAYERS turned on, the orginal method 
  3538. // OnRButtonDblClkCX is separated into two methods,
  3539. // one of which is a per-layer method.
  3540.  
  3541.     //    Remember....
  3542.     m_LastMouseEvent = m_RBDClick;
  3543.     m_cpRBDClick = cpPoint;
  3544.     m_uMouseFlags = uFlags;
  3545. }
  3546.  
  3547. void CWinCX::OnRButtonDownCX(UINT uFlags, CPoint cpPoint)
  3548. {
  3549.     RelayToolTipEvent(cpPoint, WM_RBUTTONDOWN);
  3550.  
  3551.     MWContext * pMWContext = GetContext();
  3552.     
  3553.     //    Only do this if clicking is enabled, we have a context,
  3554.     //   or context is not destoyed
  3555.     if(IsClickingEnabled() == FALSE ||
  3556.        pMWContext == NULL ||
  3557.        IsDestroyed()) {
  3558.             return;
  3559.     }
  3560.  
  3561.     XY xyPoint;
  3562.     ResolvePoint(xyPoint, cpPoint);
  3563.  
  3564. #ifdef LAYERS
  3565.     if (pMWContext->compositor) {
  3566.         CL_Event event;
  3567.         fe_EventStruct fe_event;
  3568.         
  3569.         fe_event.uFlags = uFlags;
  3570.         fe_event.x = cpPoint.x;
  3571.         fe_event.y = cpPoint.y;
  3572.         
  3573.         event.type = CL_EVENT_MOUSE_BUTTON_DOWN;
  3574.         event.fe_event = (void *)&fe_event;
  3575.         event.fe_event_size = sizeof(fe_EventStruct);
  3576.         event.x = xyPoint.x;
  3577.         event.y = xyPoint.y;
  3578.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  3579.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  3580.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  3581.         event.which = 3;
  3582.     
  3583.         CL_DispatchEvent(pMWContext->compositor, &event);
  3584.     }
  3585.     else 
  3586.         OnRButtonDownForLayerCX(uFlags, cpPoint, xyPoint, NULL);
  3587.  
  3588.     //  Have the mouse timer handler do some dirty work.
  3589.     MouseTimerData mt(pMWContext);
  3590.     FEU_MouseTimer(&mt);
  3591.     return;
  3592. }
  3593.  
  3594. BOOL
  3595. CWinCX::OnRButtonDownForLayerCX(UINT uFlags, CPoint& cpPoint,
  3596.                 XY& Point, CL_Layer *layer)
  3597. {
  3598. // With LAYERS turned on, the orginal method 
  3599. // OnRButtonDownCX is separated into two methods,
  3600. // one of which is a per-layer method.
  3601. #endif /* LAYERS */
  3602.     //    Remember....
  3603.     m_LastMouseEvent = m_RBDown;
  3604.     m_cpRBDown = cpPoint;
  3605.     m_uMouseFlags = uFlags;
  3606.  
  3607.     return FALSE;
  3608. }
  3609.  
  3610. void CWinCX::OnRButtonUpCX(UINT uFlags, CPoint cpPoint)
  3611. {
  3612.     RelayToolTipEvent(cpPoint, WM_RBUTTONUP);
  3613.  
  3614.     //    Only do this if clicking is enabled.
  3615.     if(IsClickingEnabled() == FALSE)    {
  3616.         return;
  3617.     }
  3618.  
  3619.     //    Don't continue if this context is destroyed.
  3620.     if(IsDestroyed())    {
  3621.         return;
  3622.     }
  3623.  
  3624.     XY xyPoint;
  3625.     ResolvePoint(xyPoint, cpPoint);
  3626.  
  3627.     if (GetContext()->compositor) {
  3628.     CL_Event event;
  3629.     fe_EventStruct fe_event;
  3630.     
  3631.     fe_event.uFlags = uFlags;
  3632.     fe_event.x = cpPoint.x;
  3633.     fe_event.y = cpPoint.y;
  3634.     
  3635.     event.type = CL_EVENT_MOUSE_BUTTON_UP;
  3636.     event.fe_event = (void *)&fe_event;
  3637.     event.fe_event_size = sizeof(fe_EventStruct);
  3638.     event.x = xyPoint.x;
  3639.     event.y = xyPoint.y;
  3640.     event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  3641.             | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  3642.             | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  3643.     event.which = 3;
  3644.     
  3645.     CL_DispatchEvent(GetContext()->compositor, &event);
  3646.     }
  3647.     else 
  3648.     OnRButtonUpForLayerCX(uFlags, cpPoint, xyPoint, NULL);
  3649.  
  3650.     //  Have the mouse timer handler do some dirty work.
  3651.     //  Please don't return in the above code, I'd like this to get called
  3652.     //      in all cases with the state of the buttons set correctly.
  3653.     MouseTimerData mt(GetContext());
  3654.     FEU_MouseTimer(&mt);
  3655. }
  3656.  
  3657. void
  3658. CWinCX::OnRButtonUpForLayerCX(UINT uFlags, CPoint& cpPoint,
  3659.                 XY& Point, CL_Layer *layer)
  3660. {
  3661. // With LAYERS turned on, the orginal method 
  3662. // OnRButtonUpCX is separated into two methods,
  3663. // one of which is a per-layer method.
  3664.  
  3665.     //    Remember....
  3666.     m_LastMouseEvent = m_RBUp;
  3667.     m_cpLBUp = cpPoint;
  3668.     m_uMouseFlags = uFlags;
  3669. }
  3670.  
  3671. CWnd *CWinCX::GetDialogOwner() const    {
  3672.     CGenericView *pView = m_pGenView;
  3673.     CWnd *pOwner = NULL;
  3674.     CWnd *pWnd;
  3675.  
  3676.     if(pView)   {
  3677.         pOwner = pView->GetOwner();
  3678.     }
  3679.  
  3680.     if(pOwner == NULL)  {
  3681.         //  No owner, we must take it.
  3682.         CWnd * pWnd = pView->GetParentFrame();
  3683.         if (pWnd)
  3684.             pOwner = pWnd;
  3685.         pOwner = (CWnd *)pView;
  3686.     }
  3687.     pWnd = pOwner->GetParentFrame();
  3688.     if (pWnd)
  3689.         pOwner = pWnd;
  3690.     
  3691.     // When a modal dialog (usually a preference dialog) is active, 
  3692.     //     it should be the message diaolg's parent,
  3693.     //     else user can loose alert message behind it and user can interact
  3694.     //     with preference dialog with bad consequences!
  3695.     return(pOwner->GetLastActivePopup());
  3696. }
  3697.  
  3698. int CWinCX::GetUrl(URL_Struct *pUrl, FO_Present_Types iFormatOut, BOOL bReallyLoading, BOOL bForceNew)   
  3699. {
  3700.     // If we are POSTing data (publishing), or forcing a new page, don't ask user to save current page first
  3701.     //  If user cancels when being prompted to save current document, return without action
  3702. #ifdef EDITOR
  3703.     if ( !bForceNew && pUrl->method != URL_POST_METHOD 
  3704.         && !FE_CheckAndSaveDocument(GetContext()) 
  3705.         ) {
  3706.         return( MK_NO_ACTION );
  3707.     }
  3708. #endif // EDITOR
  3709. //    ResetToolTipImg();
  3710.  
  3711. #ifdef EDITOR
  3712. #ifdef XP_WIN32
  3713.     // If we are talking to LiveWire communications system,
  3714.     //  tell Site Manager we are about to load a new URL
  3715.     //  if we are NOT simply creating a new document
  3716.     if ( GetContext() &&
  3717.          pUrl && pUrl->address && 
  3718.          0 != XP_STRCMP(pUrl->address, EDT_NEW_DOC_URL) &&
  3719.          bSiteMgrIsActive ) {
  3720.         pITalkSMClient->LoadingURL(pUrl->address);
  3721.     }
  3722. #endif // XP_WIN32
  3723. #endif // EDITOR
  3724.  
  3725.     //  Enable the wait cursor.
  3726.     SetCursor(theApp.LoadStandardCursor(IDC_WAIT));
  3727.  
  3728.     //  We need to disable/deactivate any embedded items.
  3729.     OnDeactivateEmbedCX();
  3730.  
  3731. #ifdef EDITOR
  3732.     if( EDT_IS_EDITOR(GetContext()) ){
  3733.         FE_DestroyCaret(GetContext());
  3734.     }
  3735. #endif
  3736.     //Caret will be shown automatically after new URL is loaded
  3737.     //    Save the frame's URL bar text.
  3738.     //    We use this to determine wether or not the user has
  3739.     //        changed the URL bar since the new load began, if
  3740.     //        if so, we won't blow away what they've typed.
  3741.  
  3742.     if(GetContext()->type == MWContextBrowser && !EDT_IS_EDITOR(GetContext())){
  3743.         IChrome *pChrome = GetFrame()->GetChrome();
  3744.         CWnd *pWnd = pChrome ? pChrome->GetToolbar(ID_LOCATION_TOOLBAR) : NULL;
  3745.  
  3746.         if (pWnd && pWnd->IsKindOf(RUNTIME_CLASS(CURLBar))){
  3747.             CURLBar *pUrlBar = (CURLBar *) pWnd;
  3748.  
  3749.             if(pUrlBar != NULL)
  3750.                 pUrlBar->m_pBox->GetWindowText(m_csSaveLocationBarText);
  3751.             else
  3752.                 m_csSaveLocationBarText.Empty();
  3753.         }
  3754.         else
  3755.             m_csSaveLocationBarText.Empty();
  3756.     }
  3757.     else
  3758.         m_csSaveLocationBarText.Empty();
  3759.     //    For dialog context's, we want to raise them to the top when they
  3760.     //        begin a load (view source, doc info, html dialogs).
  3761.     if(GetContext()->type == MWContextDialog && GetFrame()->GetFrameWnd() != NULL &&
  3762.         GetFrame()->GetFrameWnd()->IsWindowEnabled())    {        
  3763.         //    Bring it to the front.
  3764.         GetFrame()->GetFrameWnd()->BringWindowToTop();
  3765.  
  3766.         //    Now if it was an icon, bring it back up.
  3767.         if(GetFrame()->GetFrameWnd()->IsIconic())    {
  3768.             GetFrame()->GetFrameWnd()->ShowWindow(SW_RESTORE);
  3769.         }
  3770.     }
  3771.  
  3772.  
  3773.     //  Call the base.                          
  3774.     return(CPaneCX::GetUrl(pUrl, iFormatOut, bReallyLoading, bForceNew));
  3775. }
  3776.  
  3777. CNSToolTip*    CWinCX::CreateToolTip(LO_ImageStruct* pImage, CPoint& cpPoint, CL_Layer *layer)
  3778. {
  3779.     // Added tool tip to the image.
  3780.     if ((!pImage || !pImage->image_attr) ) return NULL; // image is not ready yet.
  3781.  
  3782.     //    Layout wants this in pixels, not FE units.
  3783.     LTRB Rect;
  3784.     ResolveElement(Rect, IL_GetImagePixmap(pImage->image_req), pImage->x_offset, pImage->y_offset, 
  3785.                         pImage->x, pImage->y, pImage->width, pImage->height);
  3786.     CPoint cpMap((int) (cpPoint.x - Twips2PixX(Rect.left)), 
  3787.                  (int) (cpPoint.y - Twips2PixY(Rect.top)));
  3788.     char* alt_text;
  3789.     lo_MapRec *map;
  3790.     lo_MapAreaRec_struct* loMapRec;
  3791.     LO_AnchorData *pAnchorData = LO_MapXYToAreaAnchor(GetDocumentContext(), pImage,
  3792.              cpMap.x, cpMap.y);
  3793.  
  3794.     if(pImage == pLastToolTipImg && m_pLastToolTipAnchor == pAnchorData)
  3795.     {
  3796.         return NULL;
  3797.  
  3798.     }    
  3799.  
  3800.     if(pAnchorData != NULL)    
  3801.         PA_LOCK(alt_text, char *, pAnchorData->alt);
  3802.     else
  3803.         PA_LOCK(alt_text, char *, pImage->alt);
  3804.  
  3805.     pLastToolTipImg = pImage;
  3806.     m_pLastToolTipAnchor = pAnchorData;
  3807.     delete m_ToolTip;
  3808.  
  3809.     if (alt_text && (*alt_text)) {
  3810.  
  3811.         m_ToolTip = new CNSToolTip();
  3812.  
  3813.         m_ToolTip->Create(CWnd::FromHandle(GetPane()), TTS_ALWAYSTIP);
  3814.         if (::IsWindow(m_ToolTip->GetSafeHwnd())){
  3815.             m_ToolTip->SetCSID( INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo( GetDocumentContext() )));
  3816.             CRect rect(0, 0, 30, 10);
  3817.             m_ToolTip->AddTool(CWnd::FromHandle(GetPane()), "", &rect, 1);
  3818.             m_ToolTip->Activate(TRUE);
  3819.             m_ToolTip->SetDelayTime(250);
  3820.             if(pAnchorData != NULL)    {
  3821.                 map = (lo_MapRec*)pImage->image_attr->usemap_ptr;
  3822.                 loMapRec = map->areas;
  3823.                 BOOL done = FALSE;
  3824.                 int tempPoint[4];
  3825.  
  3826.                 while (loMapRec != map->areas_last) {
  3827.                     if (loMapRec->anchor == pAnchorData && loMapRec->coords) {
  3828.                         tempPoint[0] = *(loMapRec->coords);
  3829.                         tempPoint[1] = *(loMapRec->coords+1);
  3830.                         tempPoint[2] = *(loMapRec->coords+2);
  3831.                         tempPoint[3] = *(loMapRec->coords+3);
  3832.                         m_ToolTip->SetBounding(tempPoint, loMapRec->coord_cnt, pImage->x, pImage->y);
  3833.                         break;
  3834.                     }
  3835.                     loMapRec = loMapRec->next;
  3836.                 }
  3837.                 if ((loMapRec == map->areas_last) && (loMapRec->anchor == pAnchorData) &&
  3838.                     loMapRec->coords) {
  3839.                     tempPoint[0] = *(loMapRec->coords);
  3840.                     tempPoint[1] = *(loMapRec->coords+1);
  3841.                     tempPoint[2] = *(loMapRec->coords+2);
  3842.                     tempPoint[3] = *(loMapRec->coords+3);
  3843.                     m_ToolTip->SetBounding(tempPoint, loMapRec->coord_cnt, pImage->x, pImage->y);
  3844.                 }
  3845.             }
  3846.             else {
  3847.                 RECT rect;
  3848.                 ::SetRect(&rect, CASTINT(pImage->x - GetOriginX()), 
  3849.                                  CASTINT(pImage->y - GetOriginY()),
  3850.                                  CASTINT(pImage->x - GetOriginX() + pImage->width),
  3851.                                  CASTINT(pImage->y - GetOriginY() + pImage->height));
  3852.                 int32 x_offset = CL_GetLayerXOrigin(layer);
  3853.                 int32 y_offset = CL_GetLayerYOrigin(layer);
  3854.  
  3855.                 ::OffsetRect(&rect, (int)x_offset, (int)y_offset);
  3856.                 m_ToolTip->SetBounding((int*)&rect, 4);
  3857.             }
  3858.             m_ToolTip->UpdateTipText(alt_text, CWnd::FromHandle(GetPane()), 1);
  3859.         }
  3860.         else {
  3861.             delete m_ToolTip;
  3862.             m_ToolTip = NULL;
  3863.         }
  3864.     }
  3865.     else
  3866.         m_ToolTip = NULL;
  3867.     if(pAnchorData != NULL)    
  3868.         PA_UNLOCK(pAnchorData->alt);
  3869.     else
  3870.         PA_UNLOCK(pImage->alt);
  3871.     return m_ToolTip;
  3872. }
  3873.  
  3874. void CWinCX::ClipChildren(CWnd *pWnd, BOOL bSet)
  3875. {
  3876.     CFrameGlue *pGlue = GetFrame();
  3877.     if (pGlue) {
  3878.     pGlue->ClipChildren(pWnd, bSet);
  3879.     }
  3880. }
  3881. #ifdef DDRAW
  3882. void CWinCX::BltToScreen(LTRB& rect, DDBLTFX* fx)
  3883. {
  3884.     if (m_physicWinRect.IsEmpty())
  3885.        CalcWinPos();
  3886.  
  3887.     if (m_lpDDSPrimary)    {
  3888.         RECT destRect;
  3889.         RECT rcRect;
  3890.         destRect.left = rect.left + GetWindowsXPos();
  3891.         destRect.top = rect.top + GetWindowsYPos();
  3892.         destRect.right = rect.right + GetWindowsXPos();
  3893.         destRect.bottom = rect.bottom + GetWindowsYPos();
  3894.         if (destRect.bottom > m_physicWinRect.bottom) {
  3895.             destRect.bottom = m_physicWinRect.bottom;
  3896.         }
  3897.         if (destRect.right > m_physicWinRect.right) {
  3898.             destRect.right = m_physicWinRect.right;
  3899.         }
  3900.         if (destRect.top > destRect.bottom) {  // for scrolling case
  3901.             destRect.top = destRect.top % (destRect.bottom - destRect.top);
  3902.         }
  3903.         if (destRect.left > destRect.right) {  // for scrolling case
  3904.             destRect.left = destRect.left % (destRect.right - destRect.left);
  3905.         }
  3906.         rcRect.left = rect.left;
  3907.         rcRect.top = rect.top;
  3908.         rcRect.right = rect.right;
  3909.         rcRect.bottom = rect.bottom;
  3910.         HRESULT err;
  3911.         err = m_lpDDSBack->ReleaseDC(m_offScreenDC);
  3912.         err = m_lpDDSPrimary->Blt(&destRect, m_lpDDSBack, &rcRect, DDBLT_WAIT, NULL);
  3913.         if (err == DDERR_SURFACELOST) {
  3914.             RestoreAllDrawSurface();
  3915.             err = m_lpDDSPrimary->Blt(&destRect, m_lpDDSBack, &rcRect, DDBLT_WAIT, NULL);
  3916.         }
  3917. #ifdef DEBUG_mhwang
  3918.         if ( err != DD_OK) {
  3919.         TRACE("CWinCX::BlttoScreen err = %x\n",
  3920.                 err);
  3921.         }
  3922. #endif
  3923.         m_lpDDSBack->GetDC(&m_offScreenDC);
  3924.     }
  3925. }
  3926. #endif
  3927.  
  3928.  
  3929. #ifdef DDRAW
  3930. int     CWinCX::DisplayPixmap(NI_Pixmap* image, NI_Pixmap* mask, int32 x, int32 y, int32 x_offset, int32 y_offset, int32 width, int32 height, LTRB& rect)
  3931. {
  3932.     SetClipOnDrawSurface(m_lpDDSBack, (HRGN)m_pDrawable->GetClip());
  3933.     CDCCX::DisplayPixmap(image, mask, x, y, x_offset, y_offset, width, height, rect);
  3934.     BOOL offScreenDrawing = m_pDrawable && (m_pDrawable  == m_pOffscreenDrawable); 
  3935.     if (m_lpDDSPrimary && !offScreenDrawing && !m_ScrollWindow) { 
  3936.         BltToScreen(rect, NULL);
  3937.     }
  3938.     return (1);
  3939. }
  3940. #endif
  3941.  
  3942.  
  3943. ////////////////////////////////////////////////////////////////////////////////
  3944. // Embedded Stuff
  3945. ////////////////////////////////////////////////////////////////////////////////
  3946.  
  3947.  
  3948. /*
  3949.  * Front-end callback from lib/plugin that creates the window for a
  3950.  * brand new plugin
  3951.  */
  3952. void CWinCX::CreateEmbedWindow(MWContext *pContext, NPEmbeddedApp *pApp)
  3953. {
  3954.     if (XP_FAIL_ASSERT(pContext != NULL && pApp != NULL && pApp->np_data != NULL))
  3955.         return;
  3956.  
  3957.     LO_EmbedStruct *pEmbed = ((np_data *) pApp->np_data)->lo_struct;
  3958.     if (XP_FAIL_ASSERT(pEmbed != NULL))
  3959.         return;
  3960.  
  3961.     // Register the window class    
  3962.     HINSTANCE hinst = AfxGetInstanceHandle();
  3963.     char szClassName[] = "aPluginWinClass";
  3964.     WNDCLASS wc;
  3965.     
  3966.     if(! GetClassInfo(hinst, szClassName, &wc)) {
  3967.         wc.style         = 0;
  3968.         wc.lpfnWndProc   = DefWindowProc;
  3969.         wc.cbClsExtra    = 0;
  3970.         wc.cbWndExtra    = 0;
  3971.         wc.hInstance     = hinst;
  3972.         wc.hIcon         = NULL;
  3973.         wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  3974.         wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  3975.         wc.lpszMenuName  = (LPCSTR) NULL;
  3976.         wc.lpszClassName = szClassName;
  3977.  
  3978.         if (XP_FAIL_ASSERT(RegisterClass(&wc) != 0))
  3979.             return;
  3980.     }
  3981.  
  3982.     // get the current view for param 5 of CreateWindow() below
  3983.     HWND cView = PANECX(pContext)->GetPane();
  3984.  
  3985.     //  Determine location of plugin rect in PIXELS
  3986.     RECT rect;
  3987.  
  3988.     // XXX This is a hack to get stuff working. The iLocation
  3989.     // parameter is passed to FE_GetEmbedSize(); unfortunately, I
  3990.     // don't yet pass it down through to NPL_CreatePlugin(). As far as
  3991.     // I can tell, it's always set to FE_VIEW, so I'll just hack it
  3992.     // for now.
  3993.     //
  3994.     //GetPluginRect(pContext, pEmbed, rect, iLocation, TRUE);
  3995.     GetPluginRect(pContext, pEmbed, rect, FE_VIEW, TRUE);
  3996.  
  3997.     HWND hWnd = ::CreateWindow(szClassName,
  3998.                                "a Plugin Window",
  3999.                                WS_CHILD | (pEmbed->ele_attrmask & LO_ELE_INVISIBLE ? 0 : WS_VISIBLE),
  4000.                                rect.left,
  4001.                           rect.top,
  4002.                           rect.right - rect.left,
  4003.                           rect.bottom - rect.top,
  4004.                           cView,
  4005.                           NULL,
  4006.                           hinst,
  4007.                           NULL);
  4008.  
  4009.     if (XP_FAIL_ASSERT(hWnd != NULL))
  4010.         return;
  4011.  
  4012.     // Allocate a new NPWindow structure to hold the plugin's window
  4013.     // information.
  4014.     NPWindow* pAppWin = XP_NEW(NPWindow);
  4015.     if (XP_FAIL_ASSERT(pAppWin != NULL)) {
  4016.         ::DestroyWindow(hWnd);
  4017.         return;
  4018.     }
  4019.  
  4020.     pAppWin->window = (void*)hWnd;
  4021.  
  4022.     // set the NPWindow rect
  4023.     pAppWin->x      = rect.left;
  4024.     pAppWin->y      = rect.top;
  4025.     pAppWin->width  = rect.right - rect.left;
  4026.     pAppWin->height = rect.bottom - rect.top;
  4027.     pAppWin->type   = NPWindowTypeWindow;
  4028.         
  4029.     // Adobe hack. Turn on clip children
  4030.     CFrameGlue *pGlue = WINCX(pContext)->GetFrame();
  4031.     if (pGlue)
  4032.         pGlue->ClipChildren(CWnd::FromHandle((HWND)pAppWin->window), TRUE);
  4033.  
  4034.     pApp->wdata = pAppWin;
  4035. }
  4036.  
  4037. /*
  4038.  * Front-end callback from lib/plugin that saves a plug-in's window in
  4039.  * a safe place to be restored (or destroyed) later.
  4040.  */
  4041. void CWinCX::SaveEmbedWindow(MWContext *pContext, NPEmbeddedApp *pApp)
  4042. {
  4043.     if (XP_FAIL_ASSERT(pContext != NULL && pApp != NULL))
  4044.         return;
  4045.  
  4046.     NPWindow* pAppWin = pApp->wdata;
  4047.     if (XP_FAIL_ASSERT(pAppWin != NULL))
  4048.         return;
  4049.  
  4050.     // If this isn't a windowed plugin, we've got nothing to do...
  4051.     if (pAppWin->type != NPWindowTypeWindow)
  4052.         return;
  4053.  
  4054.     // Find the first non-grid parent of the applet window
  4055.     MWContext* pSafeContext = XP_GetNonGridContext(pContext);
  4056.     if (XP_FAIL_ASSERT(pSafeContext != NULL))
  4057.         return;
  4058.  
  4059.     HWND parent = PANECX(pSafeContext)->GetPane();
  4060.     if (XP_FAIL_ASSERT(parent != NULL))
  4061.         return;
  4062.  
  4063.     // Hide and re-parent the window. We'll restore it in GetEmbedSize()
  4064.     ::ShowWindow((HWND)pAppWin->window, SW_HIDE);
  4065.     ::SetParent((HWND)pAppWin->window, parent);
  4066. }
  4067.  
  4068. /*
  4069.  * Front-end callback from lib/plugin that tells us to restore a
  4070.  * previously saved window and reparent it to the current context.
  4071.  */
  4072. void CWinCX::RestoreEmbedWindow(MWContext *pContext, NPEmbeddedApp *pApp)
  4073. {
  4074.     if (XP_FAIL_ASSERT(pContext != NULL && pApp != NULL))
  4075.         return;
  4076.  
  4077.     NPWindow* pAppWin = pApp->wdata;
  4078.     if (XP_FAIL_ASSERT(pAppWin != NULL))
  4079.         return;
  4080.  
  4081.     HWND parent = WINCX(pContext)->GetPane();
  4082.     if (XP_FAIL_ASSERT(parent != NULL))
  4083.         return;
  4084.  
  4085.     ::SetParent((HWND)pAppWin->window, parent);
  4086.     ::ShowWindow((HWND)pAppWin->window, SW_SHOW);
  4087. }
  4088.  
  4089. /*
  4090.  * Front-end callback from lib/plugin that tells us to destroy
  4091.  * an embedded window
  4092.  */
  4093. void CWinCX::DestroyEmbedWindow(MWContext *pContext, NPEmbeddedApp *pApp)
  4094. {
  4095.     if (XP_FAIL_ASSERT(pContext != NULL && pApp != NULL))
  4096.         return;
  4097.  
  4098.     NPWindow* pAppWin = pApp->wdata;
  4099.     if (XP_FAIL_ASSERT(pAppWin != NULL))
  4100.         return;
  4101.  
  4102.     if((pAppWin->window != NULL) && (pAppWin->type == NPWindowTypeWindow)) {
  4103.         // the Shockwave and WebFX plugins have bugs that set
  4104.         // WS_CLIPCHILDREN without clearing it so do it for them
  4105.         HWND hWndParent = ::GetParent((HWND)(DWORD)pAppWin->window);
  4106.         ::SetWindowLong(hWndParent, GWL_STYLE,
  4107.                         ::GetWindowLong(hWndParent, GWL_STYLE) & ~WS_CLIPCHILDREN);
  4108.  
  4109.         // Clear the WS_CLIPCHILDREN style for all parent windows. This
  4110.         // was set to satify the Adobe wankers who create a child window that's
  4111.         // in a separate process
  4112.         if (! IsPrintContext()) {
  4113.             CWinCX *pGCX = WINCX(pContext);
  4114.             if(pGCX) {
  4115.                 CFrameGlue *pGlue = pGCX->GetFrame();
  4116.                 if(pGlue) {
  4117.                     pGlue->ClipChildren(CWnd::FromHandle((HWND)pAppWin->window), FALSE);
  4118.                 }
  4119.             }
  4120.         }
  4121.  
  4122.         // destroy the plugin client area
  4123.         DestroyWindow((HWND)(DWORD)pAppWin->window);
  4124.         pAppWin->window = NULL;
  4125.     }    
  4126.     XP_FREE(pAppWin);    
  4127.  
  4128.     // turn scrollbars back on
  4129.     if(pApp->pagePluginType == NP_FullPage)
  4130.         FE_ShowScrollBars(pContext, TRUE);
  4131. }
  4132.  
  4133.  
  4134.  
  4135.  
  4136. ////////////////////////////////////////////////////////////////////////////////
  4137. // Java Stuff
  4138. ////////////////////////////////////////////////////////////////////////////////
  4139.  
  4140. #ifdef JAVA
  4141.  
  4142. void PR_CALLBACK 
  4143. FE_DisplayNoJavaIcon(MWContext *pContext, LO_JavaAppStruct *java_struct)
  4144. {
  4145.     /* write me */
  4146. }
  4147.  
  4148. void* PR_CALLBACK 
  4149. FE_CreateJavaWindow(MWContext *pContext, LO_JavaAppStruct *java_struct,
  4150.             int32 xp, int32 yp, int32 xs, int32 ys)
  4151. {
  4152.     CWinCX* ctxt = WINCX(pContext);
  4153.     LJAppletData* ad = (LJAppletData*)java_struct->session_data;
  4154.     HWND parent;
  4155.  
  4156.     PR_ASSERT(ad);
  4157.  
  4158.     // get the current view 
  4159.     parent = ctxt->GetPane();
  4160.  
  4161.     /* Adjust xp and yp for their offsets within the window */
  4162.     xp -= ctxt->m_lOrgX;
  4163.     yp -= ctxt->m_lOrgY;
  4164.  
  4165.     // Register the window class
  4166.     HINSTANCE hinst = AfxGetInstanceHandle();
  4167.     HWND hWnd = NULL;
  4168.     char szClassName[] = "aJavaAppletWinClass";
  4169.     WNDCLASS wc;
  4170.     BOOL result = FALSE;
  4171.  
  4172.     if((result = GetClassInfo(hinst, szClassName, &wc)) == FALSE)
  4173.     {
  4174.     wc.style         = 0;
  4175.     wc.lpfnWndProc   = DefWindowProc;
  4176.     wc.cbClsExtra    = 0;
  4177.     wc.cbWndExtra    = 0;
  4178.     wc.hInstance     = hinst;
  4179.     wc.hIcon         = NULL;
  4180.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  4181.     wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  4182.     wc.lpszMenuName  = (LPCSTR) NULL;
  4183.     wc.lpszClassName = szClassName;
  4184.     result = RegisterClass(&wc);
  4185.     }
  4186.     if(result != FALSE) {
  4187.     hWnd = ::CreateWindow(szClassName,
  4188.                   "a JavaApplet Window",
  4189.                   WS_CHILD | WS_CLIPCHILDREN,
  4190.                   xp,
  4191.                   yp,
  4192.                   xs,
  4193.                   ys,
  4194.                   parent,
  4195.                   NULL,
  4196.                   hinst,
  4197.                   NULL);
  4198.     }
  4199.     /* set the default naviagtor palette for use by awt */
  4200.     ad->fe_data = (void*)ctxt->GetPalette();
  4201.  
  4202.     return (void*)hWnd;
  4203. }
  4204.  
  4205. void* PR_CALLBACK
  4206. FE_GetAwtWindow(MWContext *pContext, LJAppletData* ad)
  4207. {
  4208.     if (::GetWindow((HWND)ad->window,GW_CHILD)==NULL) {
  4209.     return NULL;
  4210.     }
  4211.     
  4212.     /* Above was added as an interim fix just so we can release 4.02.
  4213.        The problem was that GetWindow is returning a near pointer and
  4214.        this routine is simply putting DS into DX so it can return a far
  4215.        pointer to its caller.  But if GetWindow returns null (AX=0), it
  4216.        is still putting DS into DX so it returns DS:0 to it s caller
  4217.        rather than 0:0.  Probably a casting bug but it needs further
  4218.        investigation before a final fix is made -- Steve Morse */
  4219.  
  4220.     return (void*)::GetWindow((HWND)ad->window, GW_CHILD);
  4221. }
  4222.  
  4223. void PR_CALLBACK 
  4224. FE_RestoreJavaWindow(MWContext *pContext, LJAppletData* ad,
  4225.              int32 xp, int32 yp, int32 xs, int32 ys)
  4226. {
  4227.     CWinCX* ctxt = WINCX(pContext);
  4228.  
  4229.     /* Adjust xp and yp for their offsets within the window */
  4230.     xp -= ctxt->m_lOrgX;
  4231.     yp -= ctxt->m_lOrgY;
  4232.  
  4233.     XP_TRACE(("Restore: win=%x isWin=%d\n", ad->window, ::IsWindow((HWND)ad->window)));
  4234.  
  4235.     if (pContext->is_grid_cell) {
  4236.     /*
  4237.     ** Reparent the window onto the current window in case it got
  4238.     ** moved from a grid cell when stopped.
  4239.     */
  4240.     HWND parent = ctxt->GetPane();
  4241.     PR_ASSERT( ::IsWindow( (HWND)ad->window) );
  4242.     ::SetParent( (HWND)ad->window, parent );
  4243.     }
  4244.     /*
  4245.     ** Set the CLIPCHILDREN style for the parent window to prevent
  4246.     ** EraseBackground events from obliterating the java window
  4247.     */
  4248.     ctxt->ClipChildren(CWnd::FromHandle((HWND)ad->window), TRUE);
  4249.  
  4250.     ::SetWindowPos((HWND)ad->window, NULL, xp, yp, xs, ys, SWP_NOZORDER);
  4251. }
  4252.  
  4253. void PR_CALLBACK 
  4254. FE_SetJavaWindowPos(MWContext *pContext, void* window,
  4255.             int32 xp, int32 yp, int32 xs, int32 ys)
  4256. {
  4257.     CWinCX* ctxt = WINCX(pContext);
  4258.  
  4259.     /* Adjust xp and yp for their offsets within the window */
  4260.     xp -= ctxt->m_lOrgX;
  4261.     yp -= ctxt->m_lOrgY;
  4262.  
  4263.     ::SetWindowPos((HWND)window, NULL, xp, yp, xs, ys, SWP_NOZORDER);
  4264. }
  4265.  
  4266. void PR_CALLBACK 
  4267. FE_SetJavaWindowVisibility(MWContext *context, void* window, PRBool visible)
  4268. {
  4269.     if (visible && !::IsWindowVisible((HWND)window))
  4270.     ::ShowWindow((HWND)window, SW_SHOW);
  4271.     else if (!visible && ::IsWindowVisible((HWND)window))
  4272.     ::ShowWindow((HWND)window, SW_HIDE);
  4273. }
  4274.  
  4275. void PR_CALLBACK
  4276. FE_SaveJavaWindow(MWContext *pContext, LJAppletData* ad, void* pWindow)
  4277. {
  4278.     CWinCX* ctxt = WINCX(pContext);
  4279.     HWND window = (HWND)pWindow;
  4280.  
  4281.     if (window == NULL || 0 == ::IsWindow(window)) return;
  4282.  
  4283.     /* Hide the java applet window */
  4284.     ::ShowWindow( window, SW_HIDE );
  4285.  
  4286.     /*
  4287.     ** Clear the WS_CLIPCHILDREN style for all parent windows.  This 
  4288.     ** was set to prevent EraseBackground events from obliterating
  4289.     ** the java window...
  4290.     */
  4291.     ctxt->ClipChildren(CWnd::FromHandle(window), FALSE);
  4292.             
  4293.     if (pContext->is_grid_cell) {
  4294.     /*
  4295.     ** Reparent the applet window to the first non-grid window
  4296.     ** if it was on a grid cell because the grid will be
  4297.     ** destroyed.
  4298.     **
  4299.     ** Note: The ad->context contains the non-grid context at this point.
  4300.     */
  4301.     PR_ASSERT(!ad->context->is_grid_cell);
  4302.     HWND parent = PANECX(ad->context)->GetPane();
  4303.  
  4304.     ::SetParent( window, parent );
  4305.     }
  4306.  
  4307.     /* Move the java applet window off screen - for now */
  4308.     ::SetWindowPos(window, NULL, -100, -100, 10, 10, 
  4309.            SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOZORDER);
  4310. }
  4311.  
  4312. void PR_CALLBACK
  4313. FE_FreeJavaWindow(MWContext *context, struct LJAppletData *appletData,
  4314.           void* window)
  4315. {
  4316.     HWND hwndFrame = (HWND)(DWORD)window;
  4317.     if( hwndFrame ) {
  4318.         DestroyWindow(hwndFrame);
  4319.     }
  4320. }
  4321.  
  4322. #endif  /* JAVA */
  4323.  
  4324. void CWinCX::DisplayJavaApp(MWContext *pContext, int iLocation, LO_JavaAppStruct *java_struct)
  4325. {
  4326. #ifdef JAVA
  4327.     LJ_DisplayJavaApp(pContext, java_struct,
  4328.               FE_DisplayNoJavaIcon,
  4329.               FE_GetFullWindowSize,
  4330.               FE_CreateJavaWindow,
  4331.               FE_GetAwtWindow,
  4332.               FE_RestoreJavaWindow,
  4333.               FE_SetJavaWindowPos,
  4334.               FE_SetJavaWindowVisibility);
  4335. #endif  /* JAVA */
  4336. }
  4337.  
  4338. void CWinCX::HideJavaAppElement(MWContext *pContext, LJAppletData * session_data)
  4339. {
  4340. #ifdef JAVA
  4341.     LJ_HideJavaAppElement(pContext, session_data, FE_SaveJavaWindow);
  4342. #endif /* JAVA */
  4343. }
  4344.  
  4345. void CWinCX::FreeJavaAppElement(MWContext *pContext, LJAppletData *ad)
  4346. {
  4347. #ifdef JAVA
  4348.     LJ_FreeJavaAppElement(pContext, ad,
  4349.               FE_SaveJavaWindow,
  4350.               FE_FreeJavaWindow);
  4351. #endif  /* JAVA */
  4352. }
  4353.  
  4354. void CWinCX::GetJavaAppSize(MWContext *pContext, LO_JavaAppStruct *java_struct,
  4355.                             NET_ReloadMethod reloadMethod)
  4356. {
  4357. #ifdef JAVA
  4358.     LJ_GetJavaAppSize(pContext, java_struct, reloadMethod);
  4359. #else
  4360. // jevering: should this be inside ifdef JAVA?
  4361. //    FE_DisplayNoJavaIcon(pContext, java_struct);
  4362.     java_struct->width = 1;
  4363.     java_struct->height = 1;
  4364. #endif  /* ! JAVA */
  4365. }
  4366.  
  4367. ////////////////////////////////////////////////////////////////////////////////
  4368. // End of Java Stuff
  4369. ////////////////////////////////////////////////////////////////////////////////
  4370.  
  4371. void CWinCX::HandleClippingView(MWContext *pContext, LJAppletData *appletD, int x, int y, int width, int height)
  4372. {
  4373. }
  4374.  
  4375. void CWinCX::LayoutNewDocument(MWContext *pContext, URL_Struct *pURL, int32 *pWidth, int32 *pHeight, int32 *pmWidth, int32 *pmHeight)
  4376. {
  4377.     //  Call the base.
  4378.     CPaneCX::LayoutNewDocument(pContext, pURL, pWidth, pHeight, pmWidth, pmHeight);
  4379.  
  4380.     //    Set our security indicators.
  4381.     if(GetFrame()->GetMainContext() != NULL)    {
  4382.         GetFrame()->SetSecurityStatus(XP_GetSecurityStatus(GetFrame()->GetMainContext()->GetContext()));
  4383.     }
  4384.  
  4385.     //  We're beginning to layout.
  4386.     m_bIsLayingOut = TRUE;
  4387.  
  4388.     //  Make sure we have our normal arrow cursor loaded (we loaded the wait
  4389.     //      in GetUrl).
  4390.     SetCursor(theApp.LoadStandardCursor(IDC_ARROW));
  4391.  
  4392.     //    No old progress;
  4393.     m_lOldPercent = 0;
  4394.  
  4395.     //    Update the Frame's URL bar,
  4396.     //        only if what is currently there hasn't changed, and only
  4397.     //        if we're not a grid cell.
  4398.     CString csText;
  4399.  
  4400.     if(GetContext()->type == MWContextBrowser && !EDT_IS_EDITOR(GetContext()))    {
  4401.         LPCHROME pChrome = GetFrame()->GetChrome();
  4402.         if(pChrome) {
  4403.             CWnd *pWnd = pChrome->GetToolbar(ID_LOCATION_TOOLBAR);
  4404.  
  4405.             if (pWnd && pWnd->IsKindOf(RUNTIME_CLASS(CURLBar))){
  4406.                 CURLBar *pUrlBar = (CURLBar *) pWnd;
  4407.  
  4408.                 if(pUrlBar != NULL) {
  4409.                     pUrlBar->m_pBox->GetWindowText(csText);
  4410.                     if(m_csSaveLocationBarText == csText && IsGridCell() == FALSE)    {
  4411.                         pUrlBar->UpdateFields(pURL->address);
  4412.                     }
  4413.                 }
  4414.                 else
  4415.                     csText.Empty();
  4416.             }
  4417.             else
  4418.                 csText.Empty();
  4419.         }
  4420.     }
  4421.     else
  4422.         csText.Empty();
  4423.  
  4424.     //  Clear those old elements that we tracked in the previously
  4425.     //      loaded page (see FireMouseOverEvent....)
  4426.     m_pLastOverAnchorData = NULL;
  4427.     m_pLastOverElement = NULL;
  4428.     m_pStartSelectionCell = NULL;
  4429.     m_bLastOverTextSet = FALSE;
  4430.     m_pLastImageObject = NULL;
  4431.  
  4432. //#ifndef NO_TAB_NAVIGATION
  4433.     m_lastTabFocus.pElement        = NULL;
  4434.     m_lastTabFocus.mapAreaIndex    = 0;        // 0 means no focus, start with index 1.
  4435.     m_lastTabFocus.pAnchor            = NULL;
  4436.     m_isReEntry_setLastTabFocusElement  = 0;     // to provent re-entry
  4437.     SetMainFrmTabFocusFlag(CMainFrame::TAB_FOCUS_IN_NULL);  // I don't have focus.
  4438.  
  4439. //#endif    /* NO_TAB_NAVIGATION */
  4440.     ::SetTextAlign(GetContextDC(),TA_NOUPDATECP);
  4441. }  // LayoutNewDocument()
  4442.  
  4443. void CWinCX::SetMainFrmTabFocusFlag( int nn )
  4444. {
  4445.  
  4446.     CFrameGlue * pFrame = GetFrame();
  4447.     if( pFrame ) {
  4448.         CFrameWnd * pFrameWindow = pFrame->GetFrameWnd();
  4449.         if( pFrameWindow && pFrameWindow->IsKindOf(RUNTIME_CLASS(CMainFrame)))    {
  4450.             ((CMainFrame *)pFrameWindow)->SetTabFocusFlag( nn );
  4451.         }
  4452.     }
  4453. }
  4454.  
  4455. void CWinCX::FinishedLayout(MWContext *pContext)    {
  4456.     //  Call the base.
  4457.     CPaneCX::FinishedLayout(pContext);
  4458.  
  4459.     //  We're no longer laying out.
  4460.     m_bIsLayingOut = FALSE;
  4461.  
  4462.     //    Progress should be maxed.
  4463.     m_lOldPercent = 100;
  4464. }
  4465.  
  4466. void CWinCX::AllConnectionsComplete(MWContext *pContext)    
  4467. {
  4468.     //  Call the base.
  4469.     CDCCX::AllConnectionsComplete(pContext);
  4470.  
  4471.     //    Stop our frame's animation, if the main context of the frame is no longer busy.
  4472.     if(GetFrame()->GetMainContext()) {
  4473.         if(XP_IsContextBusy(GetFrame()->GetMainContext()->GetContext()) == FALSE) {
  4474.             //    Okay, stop the animation.
  4475.             StopAnimation();
  4476.  
  4477.             //    Also, we can clear the progress bar now.
  4478.             LPCHROME pChrome = GetFrame()->GetChrome();
  4479.             if(pChrome) {
  4480.                 LPNSSTATUSBAR pIStatusBar = NULL;
  4481.                 pChrome->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar );
  4482.                 if ( pIStatusBar ) {
  4483.                     pIStatusBar->SetProgress(0);
  4484.                     pIStatusBar->Release();
  4485.                 }
  4486.             }
  4487.  
  4488.             // We need to make sure the toolbar buttons are correctly updated. If we
  4489.             // don't force it now it won't happen until the app goes idle (which could
  4490.             // be when the user moves the mouse over the window, for example)
  4491.             CGenericView *pView = GetView();
  4492.             ASSERT(pView);
  4493.  
  4494.             CFrameWnd*    pFrameWnd = pView->GetParentFrame();
  4495.  
  4496.             ASSERT(pFrameWnd);
  4497.             if (pFrameWnd) {
  4498.                 pFrameWnd->SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  4499.             }
  4500.         }
  4501.     }
  4502.  
  4503.     if( theGlobalNSFont.WebfontsNeedReload( pContext ) )
  4504.     {
  4505.         // need to remove all font cache before reload.
  4506.         ClearFontCache();
  4507.         int usePassInType = 1;
  4508.         NiceReload(usePassInType, NET_RESIZE_RELOAD );
  4509.     }
  4510. }
  4511.  
  4512. void CWinCX::UpdateStopState(MWContext *pContext)
  4513. {
  4514. #ifdef XP_WIN32
  4515.     // Force the toolbar buttons to be correctly updated. If we
  4516.     // don't force it now it won't happen until the app goes idle (which could
  4517.     // be when the user moves the mouse over the window, for example)
  4518.     CGenericView *pView = GetView();
  4519.     if(pView) {
  4520.         CFrameGlue *pGlue = GetFrame();
  4521.         CFrameWnd *pFWnd = pGlue->GetFrameWnd();
  4522.         if(pFWnd) {
  4523.             pFWnd->SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  4524.         }
  4525.     }
  4526. #endif
  4527. }
  4528.  
  4529. // Note: We now use pTitle = NULL to clear an existing title
  4530. void CWinCX::SetDocTitle(MWContext *pContext, char *pTitle) 
  4531. {
  4532.     //  Call the base.
  4533.     CDCCX::SetDocTitle(pContext, pTitle);
  4534.     MWContext * pMWContext = GetContext();
  4535.     BOOL        bIsPageComposer = EDT_IS_EDITOR(pMWContext) && (pMWContext->type != MWContextMessageComposition);
  4536.                                 
  4537.     // Guard against the case where our window has gone away and the
  4538.     //   closing of the window causes the stream to complete which
  4539.     //   causes us to get back in here with a half torn down window
  4540.     if( GetDocumentContext() == NULL )
  4541.     return;
  4542.  
  4543.     //    We need to be the main context in order to set a
  4544.     //        frames title.
  4545.     if( GetFrame()->GetMainContext() == this ) {
  4546.         //  Munge the title string.
  4547.         CString csTitle;
  4548.  
  4549.           CString csUrlTitle = pTitle;
  4550.         // This should be set at end of GetUrl so we
  4551.         //  don't have to depend on history
  4552.         CString csBaseURL = LO_GetBaseURL( GetDocumentContext() );
  4553.  
  4554.         BOOL bTitleIsSameAsUrl = (csBaseURL == csUrlTitle);
  4555.  
  4556.         if(!csUrlTitle.IsEmpty()) {
  4557.             if ( bTitleIsSameAsUrl ) {
  4558.                 // We won't be adding on the URL after this,
  4559.                 //  so make a bigger title
  4560.                 // If we are a URL, cut from the middle
  4561.                  WFE_CondenseURL(csUrlTitle, 50, FALSE);
  4562.             } else {
  4563.                 if ( bIsPageComposer ) {
  4564.                     // Use just left portion of title
  4565.                     csUrlTitle = csUrlTitle.Left(30);
  4566.                 } else {
  4567.                     // We won't add URL to Browser, so use more
  4568.                     csUrlTitle = csUrlTitle.Left(100);
  4569.                 }
  4570.             }
  4571.             csTitle += csUrlTitle;
  4572.         }
  4573.  
  4574.         if( bIsPageComposer && !bTitleIsSameAsUrl ){
  4575.             // Append URL if we didn't already use it as the title
  4576.             // Limit text inside of ( )
  4577.             if( !csUrlTitle.IsEmpty() ){
  4578.                 csTitle += " : ";
  4579.             }
  4580.             // Strip off username and password from URL
  4581.             char * pStripped = NULL;
  4582.             NET_ParseUploadURL( (char*)LPCSTR(csBaseURL), &pStripped, NULL, NULL );
  4583.             csBaseURL = pStripped;
  4584.             XP_FREEIF(pStripped);
  4585.             WFE_CondenseURL(csBaseURL, 50 - (min(csUrlTitle.GetLength(),20)), FALSE);
  4586.             csTitle += csBaseURL;
  4587.         }
  4588.  
  4589.         LPCHROME pChrome = GetFrame()->GetChrome();
  4590.         if(pChrome) {
  4591.             pChrome->SetDocumentTitle(csTitle);
  4592.         }
  4593.     }
  4594. }
  4595.  
  4596. void CWinCX::ClearView(MWContext *pContext, int iView)  {
  4597.     //  Call the base.
  4598.     CDCCX::ClearView(pContext, iView);
  4599.  
  4600.     //  Have the view erase it's background to clear.
  4601.     RECT crClear;
  4602.     ::SetRect(&crClear, 0, 0, (int) GetWidth(), (int) GetHeight());
  4603.     if(GetPane())    {
  4604.         //    Must first update the window, to get rid of any
  4605.         //        queud erase backgrounds and stuff which will
  4606.         //        cause the display to become corrupted.
  4607.         RECT tempRect;
  4608.         ::SetRect(&tempRect,0, 0, CASTINT(GetWidth()), CASTINT(GetHeight()));
  4609.         ::InvalidateRect(GetPane(), &tempRect, FALSE);
  4610. //        ::UpdateWindow(GetPane());
  4611.     }
  4612.     else    {
  4613.         //  Tell layout to specifically refresh our area.
  4614.         RefreshArea(GetOriginX(), GetOriginY(), GetWidth(), GetHeight());
  4615.     }
  4616. }
  4617.  
  4618. void CWinCX::SetDocDimension(MWContext *pContext, int iLocation, int32 lWidth, int32 lLength)   {
  4619.     // This saves old Y, which changes under certain delete situations...
  4620.     int32 iOriginY = GetOriginY();
  4621.  
  4622.     // Make sure that the origin is still visible. (This case only matters when the document
  4623.     // height shrinks, which currently only happens when editing.)
  4624.     m_lOrgY = max(0, min(m_lOrgY, lLength - m_lHeight));
  4625.  
  4626.     // Anytime we change the scrolling origin, we have to tell the compositor.
  4627.     if ( GetContext()->compositor)
  4628.         CL_ScrollCompositorWindow(GetContext()->compositor, m_lOrgX, m_lOrgY);
  4629.  
  4630.     //  Call the base.
  4631.     CPaneCX::SetDocDimension(pContext, iLocation, lWidth, lLength);
  4632.  
  4633. #ifdef EDITOR
  4634.     if(EDT_IS_EDITOR(pContext) &&
  4635.        GetOriginY() != iOriginY ) {
  4636.         // Redraw entire view
  4637.         // This is needed instead to be sure caret is moved to correct location
  4638.         //   after doc size has changed, like after a deletion 
  4639.         //   at bottom of doc (bug 65199)
  4640.         EDT_RefreshLayout(pContext);
  4641.     }
  4642. #endif /* EDITOR */    
  4643. }
  4644.  
  4645. //
  4646. // Fake scroll messages so that we use scrollwindowex() to move the window
  4647. //   so that our form elements actually move
  4648. // 
  4649. void CWinCX::SetDocPosition(MWContext *pContext, int iLocation, int32 lX, int32 lY) 
  4650. {
  4651.     int iPos;
  4652.  
  4653.     //    If we're (the window) wider than the document (layout),
  4654.     //        then don't use the X value.
  4655.     if(GetDocumentWidth() <= GetWidth())    {
  4656.         lX = GetOriginX();
  4657.     }
  4658.  
  4659.     int32 lRemY = GetOriginY();
  4660.     int32 lRemX = GetOriginX();
  4661.  
  4662.     //  Call the base.
  4663.     CDCCX::SetDocPosition(pContext, iLocation, lX, lY);
  4664.  
  4665.     // LTNOTE: in the editor documents can shrink.  Editor contexts therefor
  4666.     //  must always scroll.
  4667.  
  4668.     //  Scrolling in On?ScrollCX is lossy, and causes wild results
  4669.     //      (scrolling right will cause to scroll right and up).
  4670.     //  Make sure there is a need to scroll before attempting to scroll.
  4671.  
  4672.     // scroll to the correct Y location
  4673.     if((m_lDocHeight - m_lHeight > 0) && lRemY != lY) {
  4674.         iPos = (int) ((double) lY * (double) GetPageY() / (double) (m_lDocHeight - m_lHeight));
  4675.         Scroll(SB_VERT, SB_THUMBTRACK, iPos, NULL);
  4676.     }
  4677.     else if ( EDT_IS_EDITOR( pContext ) ){
  4678.         if((m_lDocHeight - m_lHeight > 0)) {
  4679.             iPos = (int) ((double) lY * (double) GetPageY() / (double) (m_lDocHeight - m_lHeight));
  4680.             Scroll(SB_VERT, SB_THUMBTRACK, iPos, NULL);
  4681.         }
  4682.         else    {
  4683.             Scroll(SB_VERT, SB_THUMBTRACK, 0, NULL);
  4684.         }
  4685.     }
  4686.         
  4687.  
  4688.     // now do X
  4689.     if((m_lDocWidth - m_lWidth > 0) && lRemX != lX) {
  4690.         iPos = (int) ((double) lX * (double) GetPageX() / (double) (m_lDocWidth - m_lWidth));
  4691.         Scroll(SB_HORZ, SB_THUMBTRACK, iPos, NULL);
  4692.     }
  4693.     else if( EDT_IS_EDITOR(pContext) ){
  4694.         if((m_lDocWidth - m_lWidth > 0)) {
  4695.             iPos = (int) ((double) lX * (double) GetPageX() / (double) (m_lDocWidth - m_lWidth));
  4696.             Scroll(SB_HORZ, SB_THUMBTRACK, iPos, NULL);
  4697.         }
  4698.         else    {
  4699.             Scroll(SB_HORZ, SB_THUMBTRACK, 0, NULL);
  4700.         }
  4701.     }
  4702.     // realize scrollbars will have been called by the scrolling routines
  4703. }
  4704.  
  4705. //#ifndef NO_TAB_NAVIGATION 
  4706. // CWinCX::DisplayFeedback() is called by CFE_DisplayFeedback() to draw image selection feedback,
  4707. // and tab focus.
  4708. //
  4709. // For clear calling relation, CDCCX::DisplayFeedback() is renamed to CDCCX::DisplayImageFeedback() 
  4710. // and added theArea, drawFlag parameters.
  4711. void CWinCX::DisplayFeedback(MWContext *pContext, int iLocation, LO_Element *pElement)
  4712. {
  4713.     if( pElement->lo_any.type == LO_IMAGE ) {
  4714.         // Only if the pImage has the tab focus, can we get the tab focus area.
  4715.         // otherwise it will return NULL.
  4716.         lo_MapAreaRec * theArea = NULL;
  4717.         uint32            drawFlag = 0;
  4718.         getImageDrawFlag(pContext, (LO_ImageStruct *)pElement, &theArea, &drawFlag);
  4719.         
  4720.         CDCCX::DisplayImageFeedback(pContext, iLocation, pElement, theArea, drawFlag );
  4721.     }
  4722.     // do nothing if it is not image.
  4723. }
  4724. //#endif /* NO_TAB_NAVIGATION */
  4725.  
  4726. void CWinCX::SetProgressBarPercent(MWContext *pContext, int32 lPercent)    {
  4727.     //    Enusre the safety of the value.
  4728.     lPercent = lPercent < -1 ? 0 : ( lPercent > 100 ? 100 : lPercent );
  4729.  
  4730.     if ( m_lOldPercent == lPercent ) {
  4731.         return;
  4732.     }
  4733.  
  4734.     m_lOldPercent = lPercent;
  4735.     if (GetFrame()) {
  4736.         LPCHROME pChrome = GetFrame()->GetChrome();
  4737.         if(pChrome) {
  4738.             LPNSSTATUSBAR pIStatusBar = NULL;
  4739.             pChrome->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar );
  4740.             if ( pIStatusBar ) {
  4741.                 pIStatusBar->SetProgress(CASTINT(lPercent));
  4742.                 pIStatusBar->Release();
  4743.             }
  4744.         }
  4745.     }
  4746. }
  4747.  
  4748. void CWinCX::Progress(MWContext *pContext, const char *pMessage) {
  4749.     if (GetFrame()) {
  4750.         LPCHROME pChrome = GetFrame()->GetChrome();
  4751.         if(pChrome) {
  4752.             LPNSSTATUSBAR pIStatusBar = NULL;
  4753.             pChrome->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar );
  4754.             if ( pIStatusBar ) {
  4755.                 pIStatusBar->SetStatusText(pMessage);
  4756.                 pIStatusBar->Release();
  4757.             }
  4758.         }
  4759.     }
  4760. }
  4761.  
  4762. void CWinCX::DisplayEdge(MWContext *pContext, int iLocation, LO_EdgeStruct *pEdge)    {
  4763.     //    Create an edge window if none currently exists.
  4764.     if(pEdge->FE_Data == NULL)    {
  4765.         CGridEdge *pNewEdge = new CGridEdge(pEdge, this);
  4766.         pEdge->FE_Data = pNewEdge;
  4767.     }
  4768.     else    {
  4769.         //    Update the object's idea of it's owner in case layout is swapping objects on us,
  4770.         //        this in turn causes the edge to display in a possibly new location.
  4771.         ((CGridEdge *)pEdge->FE_Data)->UpdateEdge(pEdge);
  4772.     }
  4773. }
  4774.  
  4775. void CWinCX::FreeEdgeElement(MWContext *pContext, LO_EdgeStruct *pEdge)    {
  4776.     //    Get rid of the Edge.
  4777.     if(pEdge && pEdge->FE_Data)    {
  4778.         delete((CGridEdge *)(pEdge->FE_Data));
  4779.         pEdge->FE_Data = NULL;
  4780.     }
  4781. }
  4782.  
  4783. CWinCX *CWinCX::DetermineTarget(const char *pTargetName)    {
  4784.     //    This function decides what target will load a URL.
  4785.     //    This is to facilitate grids loading into targeted locations.
  4786.  
  4787.     //    Ensure the target name exists.
  4788.     if(pTargetName == NULL || *pTargetName == '\0')    {
  4789.         //  If we're a dialog, and we can not close ourselves, and we're modal over another
  4790.         //      window context, send the url to that context instead.
  4791.         if(GetContext()->type == MWContextDialog &&
  4792.            m_cplModalOver.IsEmpty() == FALSE &&
  4793.            GetDocument() &&
  4794.            GetDocument()->CanClose() == FALSE)   {
  4795.             HWND hDestination = (HWND)m_cplModalOver.GetHead();
  4796.             if(IsWindow(hDestination))  {
  4797.                CWnd *pDestination = CWnd::FromHandlePermanent(hDestination);
  4798.                 if(pDestination && pDestination->IsKindOf(RUNTIME_CLASS(CGenericFrame)))    {
  4799.                     CGenericFrame *pFrame = (CGenericFrame *)pDestination;
  4800.                     if(pFrame->GetActiveContext() &&
  4801.                        pFrame->GetActiveContext()->IsWindowContext() &&
  4802.                        pFrame->GetActiveContext()->IsDestroyed() == FALSE)  {
  4803.                         //  GARRETT:  This needs to support PANECX
  4804.                         return(VOID2CX(pFrame->GetActiveContext(), CWinCX)->DetermineTarget(pTargetName));
  4805.                     }
  4806.                 }
  4807.             }
  4808.         }
  4809.         return(this);
  4810.     }
  4811.  
  4812.     //    Attempt to find the context already in existance.
  4813.     MWContext *pCandidate = XP_FindNamedContextInList(GetContext(), (char *)pTargetName);
  4814.     if(pCandidate != NULL)    {
  4815.         if(ABSTRACTCX(pCandidate)->IsWindowContext() == FALSE)    {
  4816.             //    Don't allow anything but windows to take this burden.
  4817.             return(this);
  4818.         }
  4819.         else    {
  4820.             return(VOID2CX(pCandidate->fe.cx, CWinCX));
  4821.         }
  4822.     }
  4823.  
  4824.     //    Create a new one, dammit.
  4825.     pCandidate = FE_MakeBlankWindow(GetContext(), NULL, (char *)pTargetName);
  4826.     if(pCandidate == NULL)    {
  4827.         //    Just use ourselves, I see no way out.
  4828.         return(this);
  4829.     }
  4830.     return(VOID2CX(pCandidate->fe.cx, CWinCX));
  4831. }
  4832.  
  4833. int32 CWinCX::QueryProgressPercent()    {
  4834.     //    If we've no children, return our percentage.
  4835.     if(IsGridParent() == FALSE)    {
  4836.         return(m_lOldPercent);
  4837.     }
  4838.  
  4839.     //    It's not empty.
  4840.     //    We need to return the sum of each of our grid children, divided by the number
  4841.     //        of the grid children.
  4842.     int32 lCount = XP_ListCount(GetContext()->grid_children);
  4843.     int32 lSum = 0;
  4844.     
  4845.     //    Go through each child.
  4846.     MWContext *pChild;
  4847.     XP_List *pTraverse = GetContext()->grid_children;
  4848.     while (pChild = (MWContext *)XP_ListNextObject(pTraverse)) {
  4849.         ASSERT(ABSTRACTCX(pChild)->IsWindowContext());
  4850.         lSum += WINCX(pChild)->QueryProgressPercent();
  4851.     }
  4852.  
  4853.     // just in case...
  4854.     if (lCount < 1)
  4855.         return(m_lOldPercent);
  4856.  
  4857.     //    Return the sum divided by the count.
  4858.     return(lSum / lCount);
  4859. }
  4860.  
  4861. void CWinCX::StopAnimation()
  4862. {
  4863.     LPCHROME pChrome = GetFrame()->GetChrome();
  4864.     if(pChrome) {
  4865.         pChrome->StopAnimation();
  4866.     }
  4867. }
  4868.  
  4869. void CWinCX::StartAnimation()
  4870. {
  4871.     LPCHROME pChrome = GetFrame()->GetChrome();
  4872.     if(pChrome) {
  4873.         pChrome->StartAnimation();
  4874.     }
  4875. }
  4876.  
  4877. void CWinCX::OpenFile()    {
  4878.     //    If we've a parent context, let them deal with this.
  4879.     if(GetParentContext())    {
  4880.         if(ABSTRACTCX(GetParentContext())->IsWindowContext())    {
  4881.             WINCX(GetParentContext())->OpenFile();
  4882.         }
  4883.         else    {
  4884.             ASSERT(0);
  4885.         }
  4886.     }
  4887.     else if(IsDestroyed() == FALSE)    {
  4888.         //    Have the frame bring up the open file dialog.
  4889.         if(GetFrame()->GetFrameWnd())    {
  4890.             MWContext * pMWContext = GetContext();
  4891.             
  4892.             // Restrict opening to only HTML files if initiated from Composer frame
  4893.             BOOL bOpenIntoEditor = EDT_IS_EDITOR(pMWContext) && (pMWContext->type == MWContextBrowser);
  4894.             CWnd * cWnd = GetFrame()->GetFrameWnd();
  4895.             
  4896.             char * pName = wfe_GetExistingFileName(
  4897.                                 cWnd->m_hWnd,
  4898.                                 szLoadString(IDS_OPEN), bOpenIntoEditor ? HTM_ONLY : HTM, TRUE);
  4899.  
  4900.             if(pName == NULL) {
  4901.                 //    Canceled.
  4902.                 return;
  4903.             }
  4904. #ifdef EDITOR
  4905.             if( bOpenIntoEditor ){
  4906.                 FE_LoadUrl(pName, LOAD_URL_COMPOSER);
  4907.             } else {
  4908.                 if( EDT_IS_EDITOR(pMWContext) ){
  4909.                     // Open a file into a new browse window from an Editor
  4910.                     FE_LoadUrl(pName, LOAD_URL_NAVIGATOR);
  4911.                 } else {
  4912.                     // Load URL into existing Browser window
  4913.                     NormalGetUrl(pName);
  4914.                 }
  4915.             }
  4916. #else
  4917.             NormalGetUrl(pName);
  4918. #endif // EDITOR
  4919.             XP_FREE(pName);
  4920.         }
  4921.         else    {
  4922.             ASSERT(0);
  4923.         }
  4924.     }
  4925. }
  4926.  
  4927. BOOL CWinCX::CanOpenFile()    {
  4928.     //    If we've a parent context, let them deal with this.
  4929.     if(GetParentContext())    {
  4930.         if(ABSTRACTCX(GetParentContext())->IsWindowContext())    {
  4931.             return(WINCX(GetParentContext())->CanOpenFile());
  4932.         }
  4933.         else    {
  4934.             ASSERT(0);
  4935.             return(FALSE);
  4936.         }
  4937.     }
  4938.     else if(IsDestroyed() == TRUE)    {
  4939.         return(FALSE);
  4940.     }
  4941.     else    {
  4942.         //    Can always open a file.
  4943.         //    Perhaps not if we're in some kiosk mode.
  4944.         return(TRUE);
  4945.     }
  4946. }
  4947.  
  4948. BOOL CWinCX::SaveOleDocument() {
  4949.     CGenericDoc * pDoc = GetDocument();  
  4950.  
  4951.     return pDoc->OnSaveDocument(NULL);
  4952.     
  4953. }
  4954. void CWinCX::SaveAs()    {
  4955.     if (!SaveOleDocument()) {
  4956.         if(IsDestroyed() == FALSE && IsGridParent() == FALSE)    {
  4957.             //    Make sure we have a history entry.
  4958.             History_entry *pHist = SHIST_GetCurrent(&(GetContext()->hist));
  4959.             if(pHist != NULL && pHist->address != NULL)    {
  4960.                 //    Can save.
  4961.                 //    Don't care if GetFrameWnd returns NULL.
  4962.                 CSaveCX::SaveAnchorObject((const char *)pHist->address,
  4963.                     pHist,  GetFrame()->m_iCSID, GetFrame()->GetFrameWnd());
  4964.             }
  4965.         }
  4966.     }
  4967. }
  4968.  
  4969. BOOL CWinCX::CanSaveAs()    {
  4970.  
  4971.     // if there is only 1 ole item there, don't save the documant.
  4972.     CGenericDoc * pDoc = GetDocument();
  4973.     POSITION pos = pDoc->GetStartPosition(); 
  4974.     CNetscapeCntrItem *pItem;
  4975.     CDocItem* item = pDoc->GetNextItem(pos );
  4976.     // If the current embed item is full page OLE and is not in-placed actived, return FALSE
  4977.     // so the saveAs menu item will be disabled.
  4978.     while (item && item->IsKindOf(RUNTIME_CLASS(CNetscapeCntrItem))) {
  4979.         pItem = (CNetscapeCntrItem*)item;
  4980.         if (pItem->m_isFullPage && !pItem->IsInPlaceActive( ))
  4981.             return FALSE;   
  4982.         item = pDoc->GetNextItem(pos );
  4983.     }
  4984.     pItem = (CNetscapeCntrItem *)pDoc->GetInPlaceActiveItem(CWnd::FromHandle(GetPane()));
  4985.     if (pItem) { 
  4986.         if (pItem->m_bCanSavedByOLE)   // see can this item be saved.
  4987.             return TRUE;
  4988.         else
  4989.             return FALSE;
  4990.     }
  4991.     if(IsDestroyed() == TRUE || IsGridParent() == TRUE)    {
  4992.         return(FALSE);
  4993.     }
  4994.     else    {
  4995.         //    Can't save if there's no history entry.
  4996.         History_entry *pHist = SHIST_GetCurrent(&(GetContext()->hist));
  4997.         if(pHist == NULL)    {
  4998.             return(FALSE);
  4999.         }
  5000.         else if(pHist->address == NULL)    {
  5001.             return(FALSE);
  5002.         }
  5003.         else    {
  5004.             return(TRUE);
  5005.         }
  5006.     }
  5007. }
  5008.  
  5009. void CWinCX::PrintContext() {
  5010.     //Abstraction layer has context type print which
  5011.     //conflicts with abstracting the Print() function
  5012.     Print();
  5013. }
  5014.  
  5015. void CWinCX::Print()    {
  5016.     if(IsDestroyed() == TRUE || CanPrint() == FALSE)    {
  5017.         return;
  5018.     }
  5019.     MWContext *pMWContext = GetContext();
  5020.     if( !pMWContext )
  5021.         return;
  5022.     // Note: We no longer have to force saving a page 
  5023.     //  before printing because we use a temporary file instead
  5024.     
  5025.     //  Always pass the WYSIWYG attribute for printing URLs (javascript).
  5026.     SHIST_SavedData SavedData;
  5027.     URL_Struct *pUrl = CreateUrlFromHist(TRUE, &SavedData, TRUE);
  5028.  
  5029.     char *pDisplayUrl = NULL;
  5030. #ifdef EDITOR
  5031.     if( EDT_IS_EDITOR(pMWContext) )
  5032.     {
  5033.         // Save actual address we want to show in header or footer
  5034.         //  to pass on to print context
  5035.         if( pUrl->address )
  5036.             pDisplayUrl = XP_STRDUP(pUrl->address);
  5037.  
  5038.         // Save current contents to a temporary file if
  5039.         //  we are a Mail Message, a New Document, or there are changes to current page
  5040.         // This will change pUrl->address to temp filename
  5041.         if( !FE_PrepareTempFileUrl(pMWContext, pUrl) )
  5042.         {
  5043.             XP_FREEIF(pDisplayUrl);
  5044.             // Failed to save to the temp file - abort
  5045.             return;
  5046.         }
  5047.     }
  5048. #endif //EDITOR
  5049.  
  5050.     // Copy the necessary information into the URL's saved data so that we don't
  5051.     // make a copy of the plug-ins when printing
  5052.     NPL_PreparePrint(pMWContext, &pUrl->savedData);
  5053.  
  5054.     CGenericView *pView = GetView();
  5055.     if(pView)   {
  5056.         CPrintCX::PrintAnchorObject(pUrl, pView, &SavedData, pDisplayUrl);
  5057.     }
  5058.     XP_FREEIF(pDisplayUrl);
  5059. }
  5060.  
  5061. BOOL CWinCX::CanPrint(BOOL bPreview)    {
  5062.     //    Can't print if we're destroyed, if there's no view, or if we've no
  5063.     //        history or we're a grid parent.
  5064.     BOOL bRetval = TRUE;
  5065.     if(FALSE == sysInfo.m_bPrinter) {
  5066.         bRetval = FALSE;
  5067.     }
  5068.     else if(IsDestroyed())    {
  5069.         bRetval = FALSE;
  5070.     }
  5071.     else if(GetPane() == NULL)    {
  5072.         bRetval = FALSE;
  5073.     }
  5074.     else if(CanCreateUrlFromHist() == FALSE)    {
  5075.         bRetval = FALSE;
  5076.     }
  5077.     else if(IsGridParent() == TRUE)    {
  5078.         bRetval = FALSE;
  5079.     }
  5080.  
  5081.     //    Lastly, we only allow one print context at a time.
  5082.     //    There can be multiple print preview context's however.
  5083.     if(bRetval && bPreview == FALSE)    {
  5084.         MWContext *pTraverseContext = NULL;
  5085.         CAbstractCX *pTraverseCX = NULL;
  5086.         XP_List *pTraverse = XP_GetGlobalContextList();
  5087.         while (pTraverseContext = (MWContext *)XP_ListNextObject(pTraverse)) {
  5088.             if(pTraverseContext != NULL && ABSTRACTCX(pTraverseContext) != NULL)    {
  5089.                 pTraverseCX = ABSTRACTCX(pTraverseContext);
  5090.                 if(pTraverseCX->IsPrintContext() == TRUE)    {
  5091.                     CPrintCX *pPrintCX = VOID2CX(pTraverseCX, CPrintCX);
  5092.                     if(pPrintCX->IsPrintPreview() == FALSE)    {
  5093.                         //    Already a print job in progress.
  5094.                         bRetval = FALSE;
  5095.                         break;
  5096.                     }
  5097.                 }
  5098.             }
  5099.         }
  5100.     }
  5101.  
  5102.     return(bRetval);
  5103. }
  5104.  
  5105. void CWinCX::AllFind(MWContext *pSearchContext)    {
  5106.     //    If we've got a parent context, let it deal.
  5107.     if(GetParentContext())    {
  5108.         if(ABSTRACTCX(GetParentContext())->IsWindowContext())    {
  5109.             WINCX(GetParentContext())->AllFind(pSearchContext);
  5110.         }
  5111.         else    {
  5112.             ASSERT(0);
  5113.         }
  5114.     }
  5115.     else if(CanAllFind())    {
  5116.         if(GetFrame()->GetFrameWnd())    {
  5117.             CNetscapeFindReplaceDialog *dlg;
  5118.       
  5119.             dlg = new CNetscapeFindReplaceDialog();
  5120.             UINT flags = FR_DOWN | FR_NOWHOLEWORD | FR_HIDEWHOLEWORD;
  5121.             BOOL bBrowser = TRUE;
  5122. #ifdef EDITOR
  5123.             if( pSearchContext )
  5124.             {
  5125.                 bBrowser = !EDT_IS_EDITOR(pSearchContext);
  5126.             } else {
  5127.                 bBrowser = !EDT_IS_EDITOR(GetContext());
  5128.             }
  5129. #endif
  5130.             dlg->Create(bBrowser,
  5131.                         theApp.m_csFindString, 
  5132.                         bBrowser ? NULL : (LPCTSTR)theApp.m_csReplaceString,
  5133.                         flags,
  5134.                         GetFrame()->GetFrameWnd());
  5135.  
  5136.             //    Let them know who the frame is.
  5137.             dlg->SetFrameGlue(GetFrame());
  5138.             // If a frame was specified as a search context then perform
  5139.             // the search there.  If no context was specified or if 
  5140.             // the search context is a top level window then don't set
  5141.             // the search context and we'll search normally on the focused frame.
  5142.             if (pSearchContext && pSearchContext->grid_parent)
  5143.                 dlg->SetSearchContext(pSearchContext);
  5144.         }
  5145.         else    {
  5146.             ASSERT(0);
  5147.         }
  5148.     }
  5149. }
  5150.  
  5151. BOOL CWinCX::CanAllFind()    {
  5152.     //    If we've a parent context, let them deal with this.
  5153.     if(GetParentContext())    {
  5154.         if(ABSTRACTCX(GetParentContext())->IsWindowContext())    {
  5155.             return(WINCX(GetParentContext())->CanAllFind());
  5156.         }
  5157.         else    {
  5158.             ASSERT(0);
  5159.             return(FALSE);
  5160.         }
  5161.     }
  5162.     else if(IsDestroyed() == TRUE)    {
  5163.         return(FALSE);
  5164.     }
  5165.     else    {
  5166.         BOOL bRetval = TRUE;
  5167.         //    Can't find if there's no history entry.
  5168.         History_entry *pHist = SHIST_GetCurrent(&(GetContext()->hist));
  5169.         if(pHist == NULL)    {
  5170.             bRetval = FALSE;
  5171.         }
  5172.         else if(pHist->address == NULL)    {
  5173.             bRetval = FALSE;
  5174.         }
  5175.         else if(GetFrame()->CanFindReplace() == FALSE)    {
  5176.             //    Frame already is finding/replacing.
  5177.             bRetval = FALSE;
  5178.         }
  5179.         else    {
  5180.             bRetval = TRUE;
  5181.         }
  5182.  
  5183.         return(bRetval);
  5184.     }
  5185. }
  5186.  
  5187. //
  5188. // Find again using the settings from last time
  5189. //
  5190. void CWinCX::FindAgain()
  5191. {
  5192.     DoFind(NULL, (const char *) theApp.m_csFindString, theApp.m_bMatchCase, 
  5193.                         theApp.m_bSearchDown, TRUE);
  5194. }
  5195.  
  5196. //
  5197. // Actually do the find operation
  5198. //
  5199. BOOL CWinCX::DoFind(CWnd * pWnd, const char * pFindString, BOOL bMatchCase, 
  5200.                         BOOL bSearchDown, BOOL bAlertOnNotFound)
  5201. {
  5202.  
  5203.     int32 start_position, end_position;
  5204.     LO_Element * start_ele_loc = NULL;
  5205.     LO_Element * end_ele_loc = NULL;
  5206.         CL_Layer *sel_layer = NULL;
  5207.  
  5208.     // Start the search from the current selection location    
  5209.     LO_GetSelectionEndpoints(GetDocumentContext(), 
  5210.                              &start_ele_loc, 
  5211.                              &end_ele_loc, 
  5212.                              &start_position, 
  5213.                              &end_position,
  5214.                                  &sel_layer);
  5215.  
  5216.     // look for the text                             
  5217.     if (LO_FindText(GetDocumentContext(),
  5218.                     (char *) pFindString,
  5219.                     &start_ele_loc, 
  5220.                     &start_position, 
  5221.                     &end_ele_loc, 
  5222.                     &end_position,
  5223.                     bMatchCase,
  5224.                     bSearchDown) == 1)
  5225.     {   
  5226.         int32 x, y;
  5227.               
  5228.         LO_SelectText(GetDocumentContext(), 
  5229.                       start_ele_loc, 
  5230.                       start_position, 
  5231.                       end_ele_loc,
  5232.                       end_position, 
  5233.                       &x, 
  5234.                       &y);  
  5235.         
  5236.         // TODO: This is not correct - it scrolls over unnecessarily
  5237.         //FE_SetDocPosition(GetContext(), FE_VIEW, x, y);
  5238.  
  5239.         // Get current location and scroll only as necessary
  5240.         int32 iViewLeft, iViewTop, iViewWidth, iViewHeight;
  5241.         
  5242.         FE_GetDocAndWindowPosition(GetContext(), &iViewLeft, &iViewTop, &iViewWidth, &iViewHeight);
  5243.         int32 iViewBottom = iViewTop + iViewHeight;
  5244.         int32 iViewRight = iViewLeft + iViewWidth;
  5245.         BOOL bScroll = FALSE;
  5246.         if( x < iViewLeft || x > iViewRight  )
  5247.         {
  5248.             iViewLeft = max(0,(x - iViewWidth/4));
  5249.             bScroll = TRUE;
  5250.         }
  5251.         // Place found text at 1/4 of window height
  5252.         if( y < iViewTop || y > iViewBottom )
  5253.         {
  5254.             iViewTop = max(0,(y - iViewHeight/4));
  5255.             bScroll = TRUE;
  5256.         }
  5257.         if( bScroll )
  5258.             FE_SetDocPosition(GetContext(), FE_VIEW, iViewLeft, iViewTop);
  5259.         
  5260.         //
  5261.         // Ensure the Find/Replace dlg doesn't cover the selection
  5262.         //
  5263.         CNetscapeFindReplaceDialog *pDlg = GetFrame() ? GetFrame()->GetFindReplace() : NULL;
  5264.         if( pDlg )
  5265.         {
  5266.             RECT rcDlg;
  5267.             pDlg->GetWindowRect( &rcDlg );
  5268.  
  5269.             RECT rcView;
  5270.             ::GetWindowRect( GetPane(), &rcView );
  5271.             
  5272.             int32 iTextY = rcView.top + (y - GetOriginY());
  5273.             
  5274.             if( (rcDlg.top < iTextY) && (rcDlg.bottom > iTextY) )
  5275.             {
  5276.                 CRect rcDlgNew( rcDlg );
  5277.                 
  5278.                 rcDlgNew.OffsetRect( 0, iTextY - rcDlgNew.top + 20 );
  5279.                 if( rcDlgNew.bottom > GetSystemMetrics( SM_CYSCREEN ) )
  5280.                 {
  5281.                     rcDlgNew.CopyRect( &rcDlg );
  5282.                     rcDlgNew.OffsetRect( 0, iTextY - rcDlgNew.bottom - 1 );
  5283.                 }
  5284.                 pDlg->SetWindowPos( NULL, rcDlgNew.left, rcDlgNew.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
  5285.             }
  5286.         }
  5287.         
  5288.         return TRUE;
  5289.     
  5290.     } 
  5291.     else if(bAlertOnNotFound){
  5292.         HWND hBox = NULL;
  5293.         if(NULL == pWnd)    {
  5294.             hBox = GetPane();
  5295.         }
  5296.         else    {
  5297.             hBox = pWnd->m_hWnd;
  5298.         }
  5299.  
  5300.         if(hBox)
  5301.             ::MessageBox(hBox, szLoadString(IDS_FIND_NOT_FOUND), szLoadString(AFX_IDS_APP_TITLE), MB_ICONEXCLAMATION | MB_OK);
  5302.  
  5303.     }
  5304.     return FALSE;
  5305.  
  5306. }
  5307.  
  5308. //
  5309. // cause the form containing the given element to be submitted
  5310. //
  5311. void FE_SubmitInputElement(MWContext * pContext, LO_Element * pElement)
  5312. {
  5313.  
  5314.     LO_FormSubmitData * submit;
  5315.     URL_Struct        * URL_s;
  5316.  
  5317.     if(!pContext || !pElement)
  5318.         return;
  5319.  
  5320.     submit = LO_SubmitForm(ABSTRACTCX(pContext)->GetDocumentContext(), (LO_FormElementStruct *) pElement);
  5321.     if(!submit)
  5322.         return;
  5323.  
  5324.     // Create the URL to load
  5325.     URL_s = NET_CreateURLStruct((char *)submit->action, NET_DONT_RELOAD); 
  5326.  
  5327.     // attach form data to the URL
  5328.     NET_AddLOSubmitDataToURLStruct(submit, URL_s);
  5329.  
  5330.     // add referer field if we've got it
  5331.     {
  5332.         History_entry *he = SHIST_GetCurrent (&pContext->hist);
  5333.         if(he && he->address)
  5334.             URL_s->referer = XP_STRDUP(he->address);
  5335.         else
  5336.             URL_s->referer = NULL;
  5337.     }
  5338.  
  5339.     // start the spinning icon
  5340.     //    Load up.
  5341.     ABSTRACTCX(pContext)->GetUrl(URL_s, FO_CACHE_AND_PRESENT);
  5342.  
  5343.     LO_FreeSubmitData(submit);
  5344.  
  5345. }
  5346.  
  5347. //    Say wether or not view source is allowed.
  5348. BOOL CWinCX::CanViewSource()
  5349. {
  5350.     //    If we've got a parent context, we need to pass it on up the chain.
  5351.     if(GetParentContext() != NULL)    {
  5352.         return(WINCX(GetParentContext())->CanViewSource());
  5353.     }
  5354.  
  5355.     //    We're the top level context, make sure we're not destroyed.
  5356.     if(IsDestroyed())    {
  5357.         return(FALSE);
  5358.     }
  5359.  
  5360.     //    Don't let this happen while a context is loading otherwise,
  5361.     //        not all the document source is present, and we interrupt
  5362.     //        the load.
  5363.     if(XP_IsContextBusy(GetContext()) == TRUE)    {
  5364.         return(FALSE);
  5365.     }
  5366.  
  5367.     //    All that matters now is wether or not we can create a URL struct from
  5368.     //        our history.
  5369.     return(CanCreateUrlFromHist());
  5370. }
  5371.  
  5372. //    View the source.
  5373. void CWinCX::ViewSource()
  5374. {
  5375.     //    If we've a parent context, we need to pass it on up the chain.
  5376.     if(GetParentContext() != NULL)    {
  5377.         WINCX(GetParentContext())->ViewSource();
  5378.         return;
  5379.     }
  5380.  
  5381.     if(CanViewSource())    {
  5382.         //    Clear the state data.
  5383.         URL_Struct *pUrl = CreateUrlFromHist(TRUE);
  5384.  
  5385.         if(pUrl != NULL)    {
  5386. #ifdef EDITOR
  5387.             if( EDT_IS_EDITOR(GetContext()) ){
  5388.                 EDT_DisplaySource(GetContext());    //    Make sure that it's okay to do this.
  5389.                 return;
  5390.             }
  5391. #endif //EDITOR
  5392.                 //    Load up.
  5393.             GetUrl(pUrl, FO_CACHE_AND_VIEW_SOURCE);
  5394.         }
  5395.     }
  5396. }
  5397.  
  5398. BOOL CWinCX::CanDocumentInfo()
  5399. {
  5400.     //    If we've got a parent context, we need to pass it on up the chain.
  5401.     if(GetParentContext() != NULL)    {
  5402.         return(WINCX(GetParentContext())->CanDocumentInfo());
  5403.     }
  5404.  
  5405.     //    We're the top level context, make sure we're not destroyed.
  5406.     if(IsDestroyed())    {
  5407.         return(FALSE);
  5408.     }
  5409.  
  5410.     //    Don't allow this while we're loading.
  5411.     //    They won't be able to view the entire document's tree.
  5412.     //    Also, this won't interrupt the current load.
  5413.     if(XP_IsContextBusy(GetContext()) == TRUE)    {
  5414.         return(FALSE);
  5415.     }
  5416.  
  5417.     //    All that matters now is wether or not we can create a URL struct from
  5418.     //        our history.
  5419.     return(CanCreateUrlFromHist());
  5420. }
  5421.  
  5422. void CWinCX::DocumentInfo()
  5423. {
  5424.     //    If we've got a parent context, we need to pass it on up the chain.
  5425.     if(GetParentContext() != NULL)    {
  5426.         WINCX(GetParentContext())->DocumentInfo();
  5427.         return;
  5428.     }
  5429.  
  5430.     //    Make sure it's okay to try this.
  5431.     if(CanDocumentInfo())    {
  5432.         //    Do it.
  5433.         NormalGetUrl("about:document");
  5434.     }
  5435. }
  5436.  
  5437. BOOL CWinCX::CanFrameSource()
  5438. {
  5439.     if(IsDestroyed())    {
  5440.         return(FALSE);
  5441.     }
  5442.  
  5443.     if(IsGridCell() == FALSE)   {
  5444.         return(FALSE);
  5445.     }
  5446.  
  5447.     //    Don't let this happen while a context is loading otherwise,
  5448.     //        not all the document source is present, and we interrupt
  5449.     //        the load.
  5450.     if(XP_IsContextBusy(GetContext()) == TRUE)    {
  5451.         return(FALSE);
  5452.     }
  5453.  
  5454.     //    All that matters now is wether or not we can create a URL struct from
  5455.     //        our history.
  5456.     return(CanCreateUrlFromHist());
  5457. }
  5458.  
  5459. void CWinCX::FrameSource()
  5460. {
  5461.     if(CanFrameSource())    {
  5462.         //    Clear the state data.
  5463.         URL_Struct *pUrl = CreateUrlFromHist(TRUE);
  5464.  
  5465.         if(pUrl != NULL)    {
  5466. #ifdef EDITOR
  5467.             if( EDT_IS_EDITOR(GetContext()) ){
  5468.                 EDT_DisplaySource(GetContext());    //    Make sure that it's okay to do this.
  5469.                 return;
  5470.             }
  5471. #endif
  5472.                 //    Load up.
  5473.             GetUrl(pUrl, FO_CACHE_AND_VIEW_SOURCE);
  5474.         }
  5475.     }
  5476. }
  5477.  
  5478. BOOL CWinCX::CanFrameInfo()
  5479. {
  5480.     if(IsDestroyed())    {
  5481.         return(FALSE);
  5482.     }
  5483.  
  5484.     if(IsGridCell() == FALSE)   {
  5485.         return(FALSE);
  5486.     }
  5487.  
  5488.     //    Don't allow this while we're loading.
  5489.     //    They won't be able to view the entire document's tree.
  5490.     //    Also, this won't interrupt the current load.
  5491.     if(XP_IsContextBusy(GetContext()) == TRUE)    {
  5492.         return(FALSE);
  5493.     }
  5494.  
  5495.     //    All that matters now is wether or not we can create a URL struct from
  5496.     //        our history.
  5497.     return(CanCreateUrlFromHist());
  5498. }
  5499.  
  5500. void CWinCX::FrameInfo()
  5501. {
  5502.     //    Make sure it's okay to try this.
  5503.     if(CanFrameInfo())    {
  5504.         //    Do it.
  5505.         NormalGetUrl("about:document");
  5506.     }
  5507. }
  5508.  
  5509. BOOL CWinCX::CanGoHome()
  5510. {
  5511.     //    Have the parent handle.
  5512.     if(GetParentContext() != NULL)    {
  5513.         return(WINCX(GetParentContext())->CanGoHome());
  5514.     }
  5515.  
  5516.     //    We can't be destroyed.
  5517.     if(IsDestroyed())    {
  5518.         return(FALSE);
  5519.     }
  5520.  
  5521.     //    We need to have a home page defined.
  5522.     if(theApp.m_pHomePage.IsEmpty()) {
  5523.         return(FALSE);
  5524.     }
  5525.     
  5526.     return(TRUE);
  5527. }
  5528.  
  5529. void CWinCX::GoHome()
  5530. {
  5531.     //    Have the parent handle.
  5532.     if(GetParentContext() != NULL)    {
  5533.         WINCX(GetParentContext())->GoHome();
  5534.         return;
  5535.     }
  5536.  
  5537.     //    Make sure we can go home.
  5538.     if(CanGoHome())    {
  5539.         //    Load it.
  5540.         NormalGetUrl(theApp.m_pHomePage);
  5541.     }
  5542. }
  5543.  
  5544. //  This function get's called to size the non client area.
  5545. //  On grid cells, we like to put a pixel border on the outsize so we can show activation.
  5546. void CWinCX::OnNcCalcSizeCX(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
  5547. {
  5548.     if(IsGridCell() == TRUE &&
  5549.         IsGridParent() == FALSE &&
  5550.         GetPane() != NULL &&
  5551.         IsIconic(GetPane()) == FALSE &&
  5552.         IsDestroyed() == FALSE &&
  5553.         m_bHasBorder == TRUE
  5554.         )    {
  5555.         if(lpncsp)  {
  5556.             lpncsp->rgrc[0].left += 1;
  5557.             lpncsp->rgrc[0].top += 1;
  5558.             lpncsp->rgrc[0].right -= 1;
  5559.             lpncsp->rgrc[0].bottom -= 1;
  5560.         }
  5561.     }
  5562. }
  5563.  
  5564.  
  5565. //    This function get's called to draw the area surrounding the client area of
  5566. //        the view, if anything special needs be done.
  5567. void CWinCX::OnNcPaintCX()    {
  5568.     if(IsGridCell() == TRUE &&
  5569.         IsGridParent() == FALSE &&
  5570.         GetPane() != NULL &&        
  5571.         IsDestroyed() == FALSE
  5572. #ifdef XP_WIN16
  5573.         && GetFrame()->GetFrameWnd() != NULL
  5574. #endif
  5575.         && m_bHasBorder == TRUE ) {
  5576.  
  5577.  
  5578.         //    Get a DC from our true window, we'll be using it to do the deed, as
  5579.         //        we're drawing outside of our client region.
  5580.         HDC hDC;
  5581. #ifdef XP_WIN16
  5582.         CDC *pDC = GetFrame()->GetFrameWnd()->GetDC();
  5583.         hDC = pDC->GetSafeHdc();
  5584. #else
  5585.         hDC = ::GetWindowDC(GetPane());
  5586. #endif
  5587.         if(hDC != NULL)    {
  5588.             RECT crWindowRect;
  5589.             ::GetWindowRect(GetPane(), &crWindowRect);
  5590.  
  5591.             RECT crBorder;
  5592.             ::SetRect(
  5593.                 &crBorder,
  5594.                 0,
  5595.                 0,
  5596.                 crWindowRect.right - crWindowRect.left,
  5597.                 crWindowRect.bottom - crWindowRect.top);
  5598.  
  5599. #ifdef XP_WIN16
  5600.             //  16 bit working in frame coordinates.
  5601.             ::MapWindowPoints(
  5602.                 GetPane(),
  5603.                 GetFrame()->GetFrameWnd()->m_hWnd,
  5604.                 (POINT *)&crBorder,
  5605.                 2);
  5606.  
  5607.             //  Need to shift up and left one pixel.
  5608.             crBorder.left -= 1;
  5609.             crBorder.right -= 1;
  5610.             crBorder.top -= 1;
  5611.             crBorder.bottom -= 1;
  5612. #endif
  5613.  
  5614.             //    Figure out what colors we are drawing with.
  5615.             COLORREF rgbOuter = m_rgbBackgroundColor;
  5616.  
  5617.             //    We need to change these if we're active.
  5618.             if(m_bActiveState == TRUE)    {
  5619.                 int iSum =
  5620.                     (int)GetRValue(rgbOuter) +
  5621.                     (int)GetGValue(rgbOuter) +
  5622.                     (int)GetBValue(rgbOuter);
  5623.  
  5624.                 if(iSum > (127 * 3)) {
  5625.                     //  Bright, use black.
  5626.                     rgbOuter = RGB(0, 0, 0);
  5627.                 }
  5628.                 else    {
  5629.                     //  Dark, use white.
  5630.                     rgbOuter = RGB(255, 255, 255);
  5631.                 }
  5632.             }
  5633.  
  5634.             HPEN hpO = ::CreatePen(PS_SOLID, 0, rgbOuter);
  5635.             HPEN pOldPen = (HPEN)::SelectObject(hDC, hpO);
  5636.  
  5637.             //  Careful to avoid scrollers NC paints on NT and 3.1.
  5638.             //  We'll be detecting this by deciding how wide the window borders are,
  5639.             //      these systems report 1, but 95 reports 2 (and probably future versions
  5640.             //      of NT with a the 95 UI).
  5641.             BOOL bFullPaint = FALSE;
  5642.             if(sysInfo.m_iBorderWidth != 1) {
  5643.                 bFullPaint = TRUE;
  5644.             }
  5645.  
  5646.             //  Draw left side.
  5647.             ::MoveToEx(hDC, crBorder.left, crBorder.top, NULL);
  5648.             if(bFullPaint)  {
  5649.                 ::LineTo(hDC, crBorder.left, crBorder.bottom);
  5650.             }
  5651.             else if(IsHScrollBarOn()) {
  5652.                 ::LineTo(hDC, crBorder.left, crBorder.bottom - sysInfo.m_iScrollHeight);
  5653.             }
  5654.             else    {
  5655.                 ::LineTo(hDC, crBorder.left, crBorder.bottom);
  5656.             }
  5657.  
  5658.             //  Draw bottom side.
  5659.             if(bFullPaint)  {
  5660.                 ::MoveToEx(hDC, crBorder.left, crBorder.bottom - 1, NULL);
  5661.                 ::LineTo(hDC, crBorder.right, crBorder.bottom - 1);
  5662.             }
  5663.             else if(!IsHScrollBarOn()) {
  5664.                 ::MoveToEx(hDC, crBorder.left, crBorder.bottom - 1, NULL);
  5665.  
  5666.                 if(IsVScrollBarOn()) {
  5667.                     ::LineTo(hDC, crBorder.right - sysInfo.m_iScrollWidth, crBorder.bottom - 1);
  5668.                 }
  5669.                 else    {
  5670.                     ::LineTo(hDC, crBorder.right, crBorder.bottom - 1);
  5671.                 }
  5672.             }
  5673.             else if(IsHScrollBarOn() && IsVScrollBarOn())    {
  5674.                 ::MoveToEx(hDC, crBorder.right - sysInfo.m_iScrollWidth + 1, crBorder.bottom - 1, NULL);
  5675.                 ::LineTo(hDC, crBorder.right, crBorder.bottom - 1);
  5676.             }
  5677.  
  5678.             //  Draw right side.
  5679.             if(bFullPaint)  {
  5680.                 ::MoveToEx(hDC, crBorder.right- 1, crBorder.top, NULL);
  5681.                 ::LineTo(hDC, crBorder.right - 1, crBorder.bottom);
  5682.             }
  5683.             else if(!IsVScrollBarOn())    {
  5684.                 ::MoveToEx(hDC, crBorder.right - 1, crBorder.top, NULL);
  5685.  
  5686.                 if(IsHScrollBarOn()) {
  5687.                     ::LineTo(hDC, crBorder.right - 1, crBorder.bottom - sysInfo.m_iScrollHeight);
  5688.                 }
  5689.                 else    {
  5690.                     ::LineTo(hDC, crBorder.right - 1, crBorder.bottom);
  5691.                 }
  5692.             }
  5693.             else if(IsVScrollBarOn() && IsHScrollBarOn()) {
  5694.                 ::MoveToEx(hDC, crBorder.right - 1, crBorder.bottom - sysInfo.m_iScrollHeight + 1, NULL);
  5695.                 ::LineTo(hDC, crBorder.right - 1, crBorder.bottom);
  5696.             }
  5697.             
  5698.             //  Draw top side.
  5699.             ::MoveToEx(hDC, crBorder.left, crBorder.top, NULL);
  5700.             if(bFullPaint)  {
  5701.                 ::LineTo(hDC, crBorder.right, crBorder.top);
  5702.             }
  5703.             else if(IsVScrollBarOn()) {
  5704.                 ::LineTo(hDC, crBorder.right - sysInfo.m_iScrollWidth, crBorder.top);
  5705.             }
  5706.             else    {
  5707.                 ::LineTo(hDC, crBorder.right, crBorder.top);
  5708.             }
  5709.  
  5710.             ::SelectObject(hDC, pOldPen);
  5711.             ::DeleteObject(hpO);
  5712.             //    Done with the DC.
  5713. #ifndef XP_WIN16
  5714.             ::ReleaseDC(GetPane(), hDC);
  5715. #else
  5716.             GetFrame()->GetFrameWnd()->ReleaseDC(pDC);
  5717. #endif
  5718.         }
  5719.     }
  5720. }
  5721.  
  5722. //    Tells the context wether it is made active, or inactive.
  5723. //    This function mainly used to give a visual indication of the currently
  5724. //        selected frame cell.
  5725. void CWinCX::ActivateCX(BOOL bNowActive)    {    
  5726.     //    Update our active state.
  5727.     BOOL bOldState = m_bActiveState;
  5728.     m_bActiveState = bNowActive;
  5729.     
  5730.     //    In either event, see if we should update the non client area.
  5731.     if(m_bActiveState != bOldState)    {
  5732.         OnNcPaintCX();
  5733.     }
  5734. }
  5735.  
  5736. //    Clicking is allowed again.
  5737. //    Act as though the mouse moved, so that the correct cursor is put back up.
  5738. void CWinCX::EnableClicking(MWContext *pContext)
  5739. {
  5740.     BOOL bReturnImmediately = FALSE;
  5741.     OnMouseMoveCX(m_uMouseFlags, m_cpMMove, bReturnImmediately);
  5742.     if(bReturnImmediately)  {
  5743.         return;
  5744.     }
  5745. }
  5746.  
  5747. //    Function to get the view's offset into the frame's top left position.
  5748. void CWinCX::GetViewOffsetInFrame(CPoint& cpRetval)    const {
  5749.     //    Init.
  5750.     cpRetval = CPoint(0, 0);
  5751.  
  5752.     if(GetFrame()->GetFrameWnd() != NULL && GetPane() != NULL)    {
  5753.         CRect cr;
  5754.         ::GetWindowRect(GetPane(), cr);
  5755.         GetFrame()->GetFrameWnd()->ScreenToClient(cr);
  5756.         cpRetval = CPoint(cr.left, cr.top);
  5757.     }
  5758. }
  5759.  
  5760. //    Attempt to act modal over the other context.
  5761. //  This is assumming that this is being called from FE_MakeNewWindow after
  5762. //  the popup window is created as a modal dialog.
  5763. void CWinCX::GoModal(MWContext *pParent)
  5764. {
  5765.     //    See if the other context can be told to disable it's UI.
  5766.     if(pParent == NULL || ABSTRACTCX(pParent) == NULL ||
  5767.         ABSTRACTCX(pParent)->IsWindowContext() == FALSE ||
  5768.         WINCX(pParent)->GetFrame()->GetFrameWnd() == NULL)    {
  5769.         
  5770.         //    No way, no UI to deactivate.
  5771.         return;
  5772.     }
  5773.  
  5774.     //    Okay, we can do this.
  5775.     CWinCX *pDisableCX = WINCX(pParent);
  5776.  
  5777.     // Disable their window.
  5778.     // If the frame has an owned window, e.g. a modal property sheet, disable that
  5779.     HWND    popup = ::GetLastActivePopup(pDisableCX->GetFrame()->GetFrameWnd()->m_hWnd);
  5780.     HWND popupOwner = NULL;
  5781.     // Because of the order in which this takes place, the modal dialog has already been added
  5782.     // in FE_MakeNewWindow, therefore it will be the last active popup. So we need to get its
  5783.     // parent.
  5784.     if(popup)
  5785.         popupOwner = ::GetParent(popup);
  5786.     if(popupOwner)
  5787.         ::EnableWindow(popupOwner, FALSE);
  5788.     // The above call will also disable the popup since it is a child of popupOwner.  Therefore
  5789.     // we need to enable the popup.
  5790.     ::EnableWindow(popup, TRUE);
  5791.  
  5792.     //    Mark that we need to re enable the other context when we're destroyed.
  5793.     //    We support modality over any number of context's (in case we need to
  5794.     //        go modal over the application, this allows it).
  5795.     if(popupOwner)
  5796.         m_cplModalOver.AddTail((void *)popupOwner);
  5797. }
  5798.  
  5799. //    Register a function to be called when the DestroyContext is called.
  5800. //    We only support one at a time, so a list implementation will have to
  5801. //        be provided if more than one is needed.
  5802. void CWinCX::CloseCallback(void (*pFunc)(void *), void *pArg)
  5803. {
  5804.     //    Just assign them in.
  5805.     if(pFunc)   {
  5806.         m_cplCloseCallbacks.AddTail((void *)pFunc);
  5807.         m_cplCloseCallbackArgs.AddTail(pArg);
  5808.     }
  5809. }
  5810.  
  5811. //    This simply tells the frame if it should do anything special in it's min max handler.
  5812. //    If you really need each context to not resize (such as in Frames), then you'll have to
  5813. //        redisign this.
  5814. void CWinCX::EnableResize(BOOL bEnable)
  5815. {
  5816.     //    Must have a frame, a CGenericFrame.
  5817.     if(GetFrame()->GetFrameWnd() != NULL &&
  5818.         GetFrame()->GetFrameWnd()->IsKindOf(RUNTIME_CLASS(CGenericFrame)))    {
  5819.         CGenericFrame *pFrame = (CGenericFrame *)GetFrame()->GetFrameWnd();
  5820.         pFrame->EnableResize(bEnable);
  5821.     }
  5822. }
  5823.  
  5824. //    Don't allow the frame to close.
  5825. //    This can't really work on a view by view basis (frames).
  5826. //    Also, this assumes the CWinCX resides in a CFrameWnd, which will
  5827. //        before handling close call CanCloseDocument on the document.
  5828. void CWinCX::EnableClose(BOOL bEnable)
  5829. {
  5830.     //    Get our document, and tell it wether or not it will allow the frame to close.
  5831.     if(GetDocument())    {
  5832.         GetDocument()->EnableClose(bEnable);
  5833.     }
  5834. }
  5835.  
  5836. void CWinCX::DisableHotkeys(BOOL bDisable)
  5837. {
  5838.     //    Must have a frame, a CGenericFrame.
  5839.     if(GetFrame()->GetFrameWnd() != NULL &&
  5840.         GetFrame()->GetFrameWnd()->IsKindOf(RUNTIME_CLASS(CGenericFrame)))    {
  5841.         CGenericFrame *pFrame = (CGenericFrame *)GetFrame()->GetFrameWnd();
  5842.         pFrame->DisableHotkeys(bDisable);
  5843.     }
  5844. }
  5845.  
  5846. //  Do not allow window to change z-ordering
  5847. void CWinCX::SetZOrder(BOOL bZLock, BOOL bBottommost)
  5848. {
  5849.     //    Must have a frame, a CGenericFrame.
  5850.     if(GetFrame()->GetFrameWnd() != NULL &&
  5851.         GetFrame()->GetFrameWnd()->IsKindOf(RUNTIME_CLASS(CGenericFrame)))    {
  5852.         CGenericFrame *pFrame = (CGenericFrame *)GetFrame()->GetFrameWnd();
  5853.         pFrame->SetZOrder(bZLock, bBottommost);
  5854.     }
  5855. }
  5856.  
  5857. //    Determine wether or not we can upload files.
  5858. BOOL CWinCX::CanUploadFile()
  5859. {
  5860.     BOOL bRetval = TRUE;
  5861.  
  5862.     if(IsDestroyed())    {
  5863.         bRetval = FALSE;
  5864.     }
  5865.     else if(GetPane() == NULL)    {
  5866.         bRetval = FALSE;
  5867.     }
  5868.     else if(CanCreateUrlFromHist() == FALSE)    {
  5869.         bRetval = FALSE;
  5870.     }
  5871.     else    {
  5872.         //    Must check to make sure we're on the correct type of FTP
  5873.         //        directory.
  5874.         History_entry *pHistoryEntry = SHIST_GetCurrent(&(GetContext()->hist));
  5875.         if(pHistoryEntry == NULL || pHistoryEntry->address == NULL)    {
  5876.             bRetval = FALSE;
  5877.         }
  5878.         else if(strnicmp(pHistoryEntry->address, "ftp://", 6))    {
  5879.             bRetval = FALSE;
  5880.         }
  5881.         else if(pHistoryEntry->address[strlen(pHistoryEntry->address) - 1] != '/')    {
  5882.             bRetval = FALSE;
  5883.         }
  5884.     }
  5885.  
  5886.     return(bRetval);
  5887. }
  5888.  
  5889. //    Upload files.
  5890. void CWinCX::UploadFile()
  5891. {
  5892.     if(CanUploadFile() == FALSE)    {
  5893.         return;
  5894.     }
  5895.  
  5896.     //    Get the files from the user.
  5897.     char *pFileName = wfe_GetExistingFileName(GetPane(), szLoadString(IDS_FILE_UPLOAD), HTM, TRUE);
  5898.  
  5899.     //    Null if user hit cancel.
  5900.     if(pFileName != NULL)    {
  5901.         URL_Struct *pUrl = CreateUrlFromHist(TRUE);
  5902.         if(pUrl != NULL)    {
  5903.             //    Set this to super reload (per montulli).
  5904.             pUrl->force_reload = NET_SUPER_RELOAD;
  5905.  
  5906.             size_t stAlloc = 2 * sizeof(char *);
  5907.             pUrl->files_to_post = (char **)XP_ALLOC(stAlloc);
  5908.             if(pUrl->files_to_post != NULL)    {
  5909.                 //    Clear the array.
  5910.                 memset(pUrl->files_to_post, 0, stAlloc);
  5911.  
  5912.                 //    Put in the name.
  5913.                 //    It's already been allocated by the prompt routine, no need to free
  5914.                 //        it in this case.
  5915.                 pUrl->files_to_post[0] = pFileName;
  5916.  
  5917.                 //    Ask for it.
  5918.                 GetUrl(pUrl, FO_CACHE_AND_PRESENT);
  5919.             }
  5920.             else    {
  5921.                 NET_FreeURLStruct(pUrl);
  5922.             }
  5923.         }
  5924.     }
  5925. }
  5926.  
  5927. typedef struct mouse_over_closure{
  5928.     int32     xVal, yVal;
  5929.     BOOL      bDeleteLO_Element;  // in case we created a fake one
  5930.     CWinCX  * pWin;
  5931. } mouse_over_closure;
  5932.  
  5933. //
  5934. // The backend just had a chance at a mouse-over event.  If it
  5935. //   didn't set the status bar text take care of setting it now
  5936. //
  5937. static void
  5938. mouse_over_callback(MWContext * context, LO_Element * lo_element, int32 event,
  5939.                      void * pObj, ETEventStatus status)
  5940. {
  5941.     // keep track of what we have done already so that we
  5942.     //   don't thrash
  5943.     BOOL bTextSet = FALSE;
  5944.     BOOL bCursorSet = FALSE;
  5945.     LO_EmbedStruct *pEmbed = NULL;
  5946.     LO_ImageStruct * image_struct = NULL;
  5947.     LO_TextStruct * text_struct = NULL;
  5948.  
  5949.     // get our stashed data
  5950.     mouse_over_closure * pClose = (mouse_over_closure *) pObj;
  5951.     CWinCX * pWin = pClose->pWin;
  5952.     
  5953.     // make sure the document didn't disappear
  5954.     if(status == EVENT_PANIC) {
  5955.         XP_FREE(pClose);
  5956.         return;
  5957.     }
  5958.  
  5959.     // if the status is OK then that means the backend set the
  5960.     //   status bar text
  5961.     if(status == EVENT_OK)
  5962.         bTextSet = TRUE;
  5963.     
  5964.     CPoint DocPoint(CASTINT(pClose->xVal), CASTINT(pClose->yVal));
  5965.     BOOL bMouseInSelection = pClose->pWin->PtInSelectedRegion( DocPoint );
  5966.  
  5967. #ifdef EDITOR
  5968.     // First check for Table mouse-over events - we don't need the current element
  5969.     //  since we will look for closest table hit region
  5970.     // Don't do this if ALT key is pressed - this allows sizing images (and other objects)
  5971.     //   which are tightly surrounded by a cell boundary.
  5972.     //  TODO: Alt key leaves menu select mode on - how do we defeat that behavior?
  5973.  
  5974.     if( EDT_IS_EDITOR(context) && !EDT_IsSizing(context) )
  5975.     {
  5976.         ED_HitType iTableHit = ED_HIT_NONE;
  5977.         if( pWin->m_bSelectingCells )
  5978.         {
  5979.             // User is dragging mouse to select table cells
  5980.             // Return value tells us what kind of cursor to use
  5981.             iTableHit = EDT_ExtendTableCellSelection(context, pClose->xVal, pClose->yVal);
  5982.         }
  5983.         else if( GetAsyncKeyState(VK_MENU) >= 0 ) // Alt key test
  5984.         {
  5985.             // See if we are over a table or cell "hit" region and need a special cursor
  5986.             // Get hit region - we don't need to know element, so use NULL for 4th param
  5987.             // If 5th param is TRUE, then select all cells if in upper left corner of table,
  5988.             //   or select/unselect cell if mouse is ANYWHERE inside of the cell
  5989.             iTableHit = EDT_GetTableHitRegion(context, pClose->xVal, pClose->yVal, NULL, GetAsyncKeyState(VK_CONTROL));
  5990.         }
  5991.         if( iTableHit )
  5992.         {
  5993.             bCursorSet = TRUE;
  5994.             switch( iTableHit )
  5995.             {
  5996.                 case ED_HIT_SEL_TABLE:      // Upper left corner
  5997.                     SetCursor(theApp.LoadCursor(IDC_TABLE_SEL));
  5998.                     break;
  5999.                 case ED_HIT_SEL_ALL_CELLS:  // Upper left corner with Ctrl pressed
  6000.                     SetCursor(theApp.LoadCursor(IDC_ALL_CELLS_SEL));
  6001.                     break;
  6002.                 case ED_HIT_SEL_COL:        // Near Top table border
  6003.                     SetCursor(theApp.LoadCursor(IDC_COL_SEL));
  6004.                     break;
  6005.                 case ED_HIT_SEL_ROW:        // Near left table border
  6006.                     SetCursor(theApp.LoadCursor(IDC_ROW_SEL));
  6007.                     break;
  6008.                 case ED_HIT_SEL_CELL:       // Not sure - remaining cell border not matching other regions
  6009.                     SetCursor(theApp.LoadCursor(IDC_CELL_SEL));
  6010.                     break;
  6011.                 case ED_HIT_SIZE_TABLE_WIDTH:     // Right edge of table
  6012.                     SetCursor(theApp.LoadCursor(IDC_TABLE_SIZE));
  6013.                     break;
  6014.                 case ED_HIT_SIZE_TABLE_HEIGHT:    // Bottom edge of table
  6015.                     SetCursor(theApp.LoadCursor(IDC_TABLE_VSIZE));
  6016.                     break;
  6017.                 case ED_HIT_SIZE_COL:       // Right border of a cell
  6018.                     SetCursor(theApp.LoadCursor(IDC_COL_SIZE));
  6019.                     break;
  6020.                 case ED_HIT_SIZE_ROW:       // Right border of a cell
  6021.                     SetCursor(theApp.LoadCursor(IDC_ROW_SIZE));
  6022.                     break;
  6023.                 case ED_HIT_ADD_ROWS:       // Lower left corner
  6024.                     SetCursor(theApp.LoadCursor(IDC_ADD_ROWS));
  6025.                     break;
  6026.                 case ED_HIT_ADD_COLS:       // Lower right corner
  6027.                     SetCursor(theApp.LoadCursor(IDC_ADD_COLS));
  6028.                     break;
  6029.                 case ED_HIT_DRAG_TABLE: // Near bottom
  6030.                     SetCursor(theApp.LoadCursor(IDC_ARROW_HAND));
  6031.                     break;
  6032.             }
  6033.             goto FINISH_MOUSE_OVER;
  6034.         }
  6035.     }
  6036. #endif
  6037.  
  6038.     // See if we are over some text that is a link
  6039.     text_struct = (LO_TextStruct *) lo_element;
  6040.  
  6041.     // Imagemaps send their mouseover events as dummy text structs.  Be very careful
  6042.     // about what you try to use from this text struct as many of the fields are
  6043.     // invalid.
  6044.     if(text_struct && text_struct->type == LO_TEXT && text_struct->text)
  6045.     {
  6046.         BOOL bIsLink = (text_struct->anchor_href && text_struct->anchor_href->anchor);
  6047.         if(bIsLink && !bTextSet)
  6048.         {
  6049.             wfe_Progress(context, (char *) text_struct->anchor_href->anchor);
  6050.             bTextSet = TRUE;
  6051.         }
  6052.         if( EDT_IS_EDITOR(context) )
  6053.         {
  6054. #ifdef EDITOR
  6055.             if( EDT_CanPasteStyle(context) )
  6056.             {
  6057.                 SetCursor(theApp.LoadCursor(IDC_COPY_STYLE));
  6058.                 bCursorSet = TRUE;
  6059.             }
  6060.             else if( bMouseInSelection )
  6061.             {
  6062.                 // Indicate that user can drag selected text with special cursor
  6063.                 SetCursor(theApp.LoadCursor(IDC_IBEAM_HAND));
  6064.                 bCursorSet = TRUE;
  6065.             }
  6066. #else
  6067.             XP_ASSERT(0);
  6068. #endif 
  6069.         } else if( bIsLink )
  6070.         {
  6071.             // Set anchor cursor only if not in editor
  6072.             SetCursor(theApp.LoadCursor(IDC_SELECTANCHOR));
  6073.             bCursorSet = TRUE;
  6074.         }
  6075.         if( !bCursorSet )
  6076.         {
  6077.             // We have 2 text cursor sizes -- more visible for large fonts
  6078.             SetCursor( theApp.LoadCursor(
  6079.                             text_struct->height > 20 ? IDC_EDIT_IBEAM_LARGE : IDC_EDIT_IBEAM) );
  6080.             bCursorSet = TRUE;
  6081.         }
  6082.     } 
  6083. #ifdef EDITOR
  6084.     else if( EDT_IS_EDITOR(context) &&
  6085.                lo_element && 
  6086.                !EDT_IsSizing(context) )
  6087.     {
  6088.  
  6089.         // Test for proximity to border of sizeable objects
  6090.         // This sets the cursor to system sizing cursor
  6091.         // Note: X, Y are in View coordinates
  6092.  
  6093.         int sizing = EDT_CanSizeObject(context, lo_element, pClose->xVal, pClose->yVal);
  6094.         if( sizing )
  6095.         {
  6096.             switch ( sizing )
  6097.             {
  6098.                 case ED_SIZE_TOP:
  6099.                 case ED_SIZE_BOTTOM:
  6100.                     SetCursor(theApp.LoadStandardCursor(IDC_SIZENS));
  6101.                     break;
  6102.                 case ED_SIZE_RIGHT:
  6103.                     // Tables and cells can only size from the right border
  6104.                     if( lo_element->type == LO_TABLE )
  6105.                     {
  6106.                         SetCursor(theApp.LoadCursor(IDC_TABLE_SIZE));
  6107.                         break;
  6108.                     }
  6109.                     if( lo_element->type == LO_CELL )
  6110.                     {
  6111.                         SetCursor(theApp.LoadCursor(IDC_COL_SIZE));
  6112.                         break;
  6113.                     }
  6114.                     // If not Table or Cell, fall through 
  6115.                     //  to set horizontal sizing cursor
  6116.                 case ED_SIZE_LEFT:
  6117.                     SetCursor(theApp.LoadStandardCursor(IDC_SIZEWE));
  6118.                     break;
  6119.                 case ED_SIZE_TOP_RIGHT:
  6120.                 case ED_SIZE_BOTTOM_LEFT:
  6121.                     SetCursor(theApp.LoadStandardCursor(IDC_SIZENESW));
  6122.                     break;
  6123.                 case ED_SIZE_TOP_LEFT:
  6124.                 case ED_SIZE_BOTTOM_RIGHT:
  6125.                     SetCursor(theApp.LoadStandardCursor(IDC_SIZENWSE));
  6126.                     break;
  6127.             }
  6128.             bCursorSet = TRUE;
  6129.         }
  6130.     }
  6131. #endif // EDITOR
  6132.     // NOTE: We set the imagemap and status line stuff even if we set a "sizing" cursor
  6133.  
  6134.     // See if we are over an image that is a link
  6135.     image_struct = (LO_ImageStruct *) lo_element;
  6136.     if(image_struct && image_struct->type == LO_IMAGE && image_struct->image_attr)    {
  6137.         if(image_struct->image_attr->usemap_name != NULL)    {
  6138.             CPoint image_offset;
  6139.             image_offset.x = CASTINT(pClose->xVal - (image_struct->x + image_struct->x_offset + image_struct->border_width));
  6140.             image_offset.y = CASTINT(pClose->yVal - (image_struct->y + image_struct->y_offset + image_struct->border_width));
  6141.  
  6142.             LO_AnchorData *pAnchorData = LO_MapXYToAreaAnchor(pWin->GetDocumentContext(), image_struct,
  6143.                 image_offset.x, image_offset.y);
  6144.             if(pAnchorData != NULL)    {
  6145.                 if( !EDT_IS_EDITOR(context) && !bMouseInSelection ){
  6146.                     SetCursor(theApp.LoadCursor(IDC_SELECTANCHOR));
  6147.                     bCursorSet = TRUE;
  6148.                 }
  6149.                 if( pAnchorData->anchor && !bTextSet ) {
  6150.                     wfe_Progress(context, (char *) pAnchorData->anchor);
  6151.                     bTextSet = TRUE;
  6152.                 }
  6153.             }
  6154.         }
  6155.         else if((image_struct->image_attr->attrmask & LO_ATTR_ISMAP) && image_struct->anchor_href) {
  6156.             // if its an ismap print the coordinates too
  6157.             char buf[32];
  6158.             CPoint point;
  6159.  
  6160.             point.x = (int) (pClose->xVal - (image_struct->x + image_struct->x_offset));
  6161.             point.y = (int) (pClose->yVal - (image_struct->y + image_struct->y_offset));
  6162.  
  6163.             sprintf(buf, "?%d,%d", point.x, point.y);
  6164.  
  6165.             CString anchor;
  6166.             anchor = (char *) image_struct->anchor_href->anchor;
  6167.             anchor += buf;
  6168.  
  6169.             if( !EDT_IS_EDITOR(context) && !bMouseInSelection ){
  6170.                 SetCursor(theApp.LoadCursor(IDC_SELECTANCHOR));
  6171.                 bCursorSet = TRUE;
  6172.             }
  6173.             //  Set progress text if mocha allows it.
  6174.             if(!bTextSet) {
  6175.                 wfe_Progress(context, (const char *)anchor);
  6176.                 bTextSet = TRUE;
  6177.             }
  6178.         }
  6179.         else if(image_struct->anchor_href) {
  6180.             // Set anchor cursor only if not in editor and not in a selection
  6181.             if( !EDT_IS_EDITOR(context) && !bMouseInSelection ) {
  6182.                 SetCursor(theApp.LoadCursor(IDC_SELECTANCHOR));
  6183.                 bCursorSet = TRUE;
  6184.             }
  6185.             if (image_struct->anchor_href->anchor && !bTextSet) {
  6186.                 wfe_Progress(context, (char *) image_struct->anchor_href->anchor);
  6187.                 bTextSet = TRUE;
  6188.             }
  6189.         }
  6190.         else if(image_struct->image_attr->attrmask & LO_ATTR_INTERNAL_IMAGE 
  6191.                 && EDT_IS_EDITOR(context) 
  6192.                 && image_struct->alt != NULL ){
  6193.  
  6194.             char *str;
  6195.             if(!bTextSet)   {
  6196.                 PA_LOCK(str, char *, image_struct->alt);
  6197.                 if( str != 0 ){
  6198.                     wfe_Progress( context, str );
  6199.                     bTextSet = TRUE;
  6200.                 }
  6201.                 PA_UNLOCK(image_struct->alt);
  6202.             }
  6203.         }
  6204.         if( EDT_IS_EDITOR(context) && !bCursorSet ){
  6205.             // Experimental: Image can  be dragged, so if no cursor set above,
  6206.             // use Open Hand with arrow to indicate "draggability" of the image
  6207.             SetCursor(theApp.LoadCursor(IDC_ARROW_HAND));
  6208.             bCursorSet = TRUE;
  6209.         }
  6210.     }
  6211.  
  6212.     //  See if we are over an embedded item.
  6213.     pEmbed = (LO_EmbedStruct *)lo_element;
  6214.     if(pEmbed && pEmbed->type == LO_EMBED && pEmbed->FE_Data)  {
  6215.         NPEmbeddedApp *pPluginShim = (NPEmbeddedApp *)pEmbed->FE_Data;
  6216.         if(pPluginShim != NULL && wfe_IsTypePlugin(pPluginShim) == FALSE)    {
  6217.             CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pPluginShim->fe_data;
  6218.             if(pItem != NULL && pItem->m_bLoading == FALSE && pItem->m_bBroken == FALSE &&
  6219.                 pItem->m_bDelayed == FALSE && pItem->m_lpObject != NULL)   
  6220.             {
  6221.                 if( !bMouseInSelection ){
  6222.                     SetCursor(theApp.LoadCursor(IDC_ACTIVATE_EMBED));
  6223.                     bCursorSet = TRUE;
  6224.                 }
  6225.  
  6226.                 if(!bTextSet)   {
  6227.                     CString csEmbed;
  6228.                     csEmbed.LoadString(IDS_ACTIVATE_EMBED_STATUS);
  6229.                     CString csDescrip;
  6230.                     pItem->GetUserType(USERCLASSTYPE_FULL, csDescrip);
  6231.                     csEmbed += csDescrip;
  6232.  
  6233.                     wfe_Progress(context, (char *)(const char *)csEmbed);
  6234.                     bTextSet = TRUE;
  6235.                 }
  6236.             }
  6237.         }
  6238.     }
  6239.  
  6240. FINISH_MOUSE_OVER:
  6241.     // If nothing set yet blank it out and make sure we have the 
  6242.     //   normal cursor.  Do we really want to reset the cursor 
  6243.     //   here????
  6244.     // We want to show link text but keep edit cursor in Editor
  6245.     if(!bCursorSet){
  6246.         SetCursor(theApp.LoadStandardCursor(IDC_ARROW));
  6247.     }
  6248.     if(!bTextSet) {
  6249.         wfe_Progress(context, "");
  6250.         bTextSet = TRUE;
  6251.     }
  6252.  
  6253.     // For mouse overs on anchors we may have created a fake
  6254.     //   LO_Element structure.  If so, blow it away now
  6255.     if(pClose->bDeleteLO_Element)
  6256.         XP_FREE(lo_element);
  6257.  
  6258.     XP_FREE(pClose);
  6259.  
  6260.     //  Have the mouse timer handler do some dirty work.
  6261.     //  Please don't return in the above code, I'd like this to get called
  6262.     //      in all cases with the state of the buttons set correctly.
  6263.     MouseTimerData mt(context);
  6264.     FEU_MouseTimer(&mt);
  6265.  
  6266. }
  6267.  
  6268. //  Function to handle the details of the cursor being over an element
  6269. //    and telling the back end about it.  If the backend doesn't
  6270. //    set the text, the text will get set in our clallback routine 
  6271. void CWinCX::FireMouseOverEvent(LO_Element *pElement, int32 xVal, int32 yVal,
  6272.                                 CL_Layer *layer)
  6273. {
  6274.     mouse_over_closure * pClose = NULL;
  6275.     LO_Element * pDummy;
  6276.     BOOL bEventSent = FALSE;
  6277.  
  6278. #define CREATE_CLOSURE() { pClose = XP_NEW_ZAP(mouse_over_closure);  \
  6279.                            pClose->xVal = xVal; pClose->yVal = yVal; \
  6280.                            pClose->pWin = this; }
  6281.  
  6282.     //  The mouse is over nothing, fire an out message for the last element.
  6283.     if(pElement == NULL)    {
  6284.         FireMouseOutEvent(TRUE, TRUE, xVal, yVal, layer);
  6285.     }
  6286.     //  If a different element, fire an out message for the last element,
  6287.     //      and then fire an over message for the new element.
  6288.     else if(pElement != m_pLastOverElement) {
  6289.         FireMouseOutEvent(TRUE, TRUE, xVal, yVal, layer);
  6290.  
  6291.         m_pLastOverElement = pElement;
  6292.         m_pLastOverAnchorData = GetAreaAnchorData(m_pLastOverElement);
  6293.  
  6294.         // JS needs screen coords for click events.
  6295.         CPoint cpScreenPoint(xVal, yVal);
  6296.         ClientToScreen(GetPane(), &cpScreenPoint);
  6297.  
  6298.         //  Fire over messages.
  6299.         if(m_pLastOverAnchorData)
  6300.         {
  6301.             CREATE_CLOSURE();
  6302.             // need to make a fake wrapper for m_pLastOverAnchorData
  6303.             pDummy = (LO_Element *) XP_NEW_ZAP(LO_Element);
  6304.             pDummy->lo_text.type = LO_TEXT;
  6305.             pDummy->lo_text.anchor_href = m_pLastOverAnchorData;
  6306.             // We use the text of the element to determine if it is still
  6307.             // valid later so give the dummy text struct's text a value.
  6308.             if (pDummy->lo_text.anchor_href->anchor)
  6309.                 pDummy->lo_text.text = pDummy->lo_text.anchor_href->anchor;
  6310.  
  6311.             //   need to free fake wrapper for m_pLastOverAnchorData
  6312.             pClose->bDeleteLO_Element = TRUE;
  6313.  
  6314.             // its safe to send the event now
  6315.             JSEvent *event;
  6316.             event = XP_NEW_ZAP(JSEvent);
  6317.             event->type = EVENT_MOUSEOVER;
  6318.             event->x = xVal;
  6319.             event->y = yVal;
  6320.             event->docx = xVal + CL_GetLayerXOrigin(layer);
  6321.             event->docy = yVal + CL_GetLayerYOrigin(layer);
  6322.             event->screenx = cpScreenPoint.x;
  6323.             event->screeny = cpScreenPoint.y;
  6324.  
  6325.             event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  6326.  
  6327.             ET_SendEvent(GetContext(), pDummy, event,
  6328.                          mouse_over_callback, pClose);
  6329.             bEventSent = TRUE;
  6330.         }
  6331.         else if(m_pLastOverElement && (m_pLastOverElement->type == LO_IMAGE || 
  6332.                 m_pLastOverElement->type == LO_FORM_ELE || 
  6333.                 (m_pLastOverElement->type == LO_TEXT 
  6334.                 && m_pLastOverElement->lo_text.anchor_href) 
  6335. #ifdef DOM
  6336.                 || LO_IsWithinSpan(m_pLastOverElement)
  6337. #endif
  6338.                 ))
  6339.         {
  6340.             CREATE_CLOSURE();
  6341.             JSEvent *event;
  6342.             event = XP_NEW_ZAP(JSEvent);
  6343.             event->type = EVENT_MOUSEOVER;
  6344.             event->x = xVal;
  6345.             event->y = yVal;
  6346.             event->docx = xVal + CL_GetLayerXOrigin(layer);
  6347.             event->docy = yVal + CL_GetLayerYOrigin(layer);
  6348.             event->screenx = cpScreenPoint.x;
  6349.             event->screeny = cpScreenPoint.y;
  6350.             event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  6351.  
  6352.             ET_SendEvent(GetContext(), m_pLastOverElement, event,
  6353.                          mouse_over_callback, pClose);
  6354.             bEventSent = TRUE;
  6355.         } 
  6356.     }
  6357.     //  If the same element, they have possibly traversed into a new
  6358.     //      AnchorData AREA, fire an out message, and then fire an
  6359.     //      over message if so.
  6360.     //  DO NOT send redundant over messages.
  6361.     else if(pElement == m_pLastOverElement)   {
  6362.         LO_AnchorData *pAnchorData = GetAreaAnchorData(pElement);
  6363.         if(pAnchorData != m_pLastOverAnchorData)    {
  6364.             if(m_pLastOverAnchorData)   {
  6365.                 //  Only do this if there is last anchor data, or we
  6366.                 //      fire mouse out on the element and not the data.
  6367.                 FireMouseOutEvent(FALSE, TRUE, xVal, yVal, layer);
  6368.             }
  6369.             m_pLastOverAnchorData = pAnchorData;
  6370.             if(m_pLastOverAnchorData)   {
  6371.                 // JS needs screen coords for click events.
  6372.                 CPoint cpScreenPoint(xVal, yVal);
  6373.                 ClientToScreen(GetPane(), &cpScreenPoint);
  6374.  
  6375.                 CREATE_CLOSURE();
  6376.                 // need to make a fake wrapper for m_pLastOverAnchorData
  6377.                 pDummy = (LO_Element *) XP_NEW_ZAP(LO_Element);
  6378.                 pDummy->lo_text.type = LO_TEXT;
  6379.                 pDummy->lo_text.anchor_href = m_pLastOverAnchorData;
  6380.  
  6381.                 // We use the text of the element to determine if it is still
  6382.                 // valid later so give the dummy text struct's text a value.
  6383.                 if (pDummy->lo_text.anchor_href->anchor)
  6384.                     pDummy->lo_text.text = pDummy->lo_text.anchor_href->anchor;
  6385.  
  6386.                 //   need to free fake wrapper for m_pLastOverAnchorData
  6387.                 pClose->bDeleteLO_Element = TRUE;
  6388.  
  6389.                 // its safe to send the event now
  6390.                 JSEvent *event;
  6391.                 event = XP_NEW_ZAP(JSEvent);
  6392.                 event->type = EVENT_MOUSEOVER;
  6393.                 event->x = xVal;
  6394.                 event->y = yVal;
  6395.                 event->docx = xVal + CL_GetLayerXOrigin(layer);
  6396.                 event->docy = yVal + CL_GetLayerYOrigin(layer);
  6397.                 event->screenx = cpScreenPoint.x;
  6398.                 event->screeny = cpScreenPoint.y;
  6399.                 event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  6400.                     
  6401.                 ET_SendEvent(GetContext(), pDummy, event,
  6402.                              mouse_over_callback, pClose);
  6403.                 bEventSent = TRUE;
  6404.             }
  6405.         }
  6406.         // If this is an ismap and we've moved within it, we need to 
  6407.         // change status without firing off a mouse over.
  6408.         else if(pElement->lo_any.type == LO_IMAGE) {
  6409.             LO_ImageStruct *image_struct = (LO_ImageStruct *)pElement;
  6410.             if((image_struct->image_attr->usemap_name == NULL) && (image_struct->image_attr->attrmask & LO_ATTR_ISMAP) && image_struct->anchor_href) {
  6411.                 // if its an ismap print the coordinates too
  6412.                 char buf[32];
  6413.                 CPoint point;
  6414.  
  6415.                 point.x = (int) (xVal - (image_struct->x + image_struct->x_offset));
  6416.                 point.y = (int) (yVal - (image_struct->y + image_struct->y_offset));
  6417.  
  6418.                 sprintf(buf, "?%d,%d", point.x, point.y);
  6419.                 
  6420.                 CString anchor;
  6421.                 anchor = (char *) image_struct->anchor_href->anchor;
  6422.                 anchor += buf;
  6423.  
  6424.                 if (!EDT_IS_EDITOR(GetContext())) {
  6425.                     SetCursor(theApp.LoadCursor(IDC_SELECTANCHOR));
  6426.                 }
  6427.  
  6428.                 //  Set progress text
  6429.                 wfe_Progress(GetContext(), (const char *)anchor);
  6430.             }
  6431.         if (!EDT_IS_EDITOR(GetContext()))
  6432.             bEventSent = TRUE;
  6433.         }
  6434.     // Editor wants callback to be callled every time, the Browser does not.  If 
  6435.     // we're over the same element it may have set the status bar message when we 
  6436.     // entered it.  Don't let the Browser set the status bar again until we leave it.  
  6437.     // If the element didn't want to set the status bar, the Browser will have already
  6438.     // set it correctly anyway.
  6439.     else if (!EDT_IS_EDITOR(GetContext()))
  6440.         bEventSent = TRUE;
  6441.     }
  6442.  
  6443.     // In the Editor, ALWAYS call the final callback
  6444.     //   so we can monitor mouse location for dynamic resizing of elements
  6445.     if( !bEventSent ) {
  6446.         CREATE_CLOSURE();
  6447.         // Note: param 3 ("event") isn't used in mouse_over_callback
  6448.         mouse_over_callback(GetContext(), pElement, 0, (void*)pClose, EVENT_CANCEL);
  6449.     }
  6450.  
  6451.  
  6452.     // We're using a timer to deal with the lack of a Windows call for entrance
  6453.     // and exit for a window.  Deal with it here.
  6454.  
  6455.     if (!m_bMouseMoveTimerSet) {
  6456.         // This is our first time into the document or our last.  Start the timer to check
  6457.         // for our exit and fire a mouseover for the window.
  6458.         POINT mp;
  6459.         // get mouse position
  6460.         ::GetCursorPos(&mp);
  6461.  
  6462.         if (::WindowFromPoint(mp) == GetPane()) {
  6463.             MouseMoveTimerData mt(GetContext());
  6464.             FEU_MouseMoveTimer(&mt);
  6465.         }
  6466.     }
  6467.  
  6468.     /* Unix and Mac are not up to spec on these and won't be for 4.0  Commenting
  6469.      * them out for future use later */
  6470.  
  6471.     /*JSEvent *event;
  6472.     event = XP_NEW_ZAP(JSEvent);
  6473.     event->type = EVENT_MOUSEOVER;
  6474.     event->x = xVal;
  6475.     event->y = yVal;
  6476.     event->layer_id = LO_DOCUMENT_LAYER_ID;
  6477.  
  6478.     ET_SendEvent(GetContext(), 0, event, 0, 0);
  6479.     }
  6480.     else {
  6481.         // We may have left the document. If so, send a mouseout to the window.
  6482.         POINT mp;
  6483.         // get mouse position
  6484.         ::GetCursorPos(&mp);
  6485.  
  6486.         if ((::WindowFromPoint(mp) != GetPane()) && !m_bLBDown) {
  6487.             //Yup, we left.
  6488.             JSEvent *event;
  6489.             event = XP_NEW_ZAP(JSEvent);
  6490.             event->type = EVENT_MOUSEOUT;
  6491.             event->x = xVal;
  6492.             event->y = yVal;
  6493.             event->layer_id = LO_DOCUMENT_LAYER_ID;
  6494.  
  6495.             ET_SendEvent(GetContext(), 0, event, 0, 0);
  6496.         }
  6497.     }    */
  6498.     return;
  6499.  
  6500. #undef CREATE_CLOSURE
  6501. }
  6502.  
  6503. //  Retrieve anchor data out of areas only (usemaps)
  6504. //  Use last known mouse move coordinates to do so.
  6505. LO_AnchorData *CWinCX::GetAreaAnchorData(LO_Element *pElement)  {
  6506.     LO_AnchorData *pRetval = NULL;
  6507.  
  6508.     //  Make sure this is an image element.
  6509.     if(pElement && pElement->lo_any.type == LO_IMAGE)   {
  6510.         //  Determine coordinates in pixels with image as origin and
  6511.         //      ask layout for area anchor data, will return NULL if none.
  6512.         LTRB Rect;
  6513.         LO_ImageStruct *pLOImage = (LO_ImageStruct *)pElement;
  6514.  
  6515.         // Use the returned value to convert the mouse coordinates
  6516.         // to be image relative.
  6517.         ResolveElement(Rect, pLOImage->x, pLOImage->y, 
  6518.                                pLOImage->x_offset + pLOImage->border_width, 
  6519.                                pLOImage->y_offset + pLOImage->border_width, 
  6520.                                0, 0);
  6521.         if (pLOImage->layer) {
  6522.             CL_Layer *parent;
  6523.             int32 x_offset, y_offset;
  6524.  
  6525.             parent = CL_GetLayerParent(pLOImage->layer);
  6526.  
  6527.             if (parent) {
  6528.                 x_offset = CL_GetLayerXOrigin(parent);
  6529.                 y_offset = CL_GetLayerYOrigin(parent);
  6530.  
  6531.                 Rect.left += x_offset;
  6532.                 Rect.right += x_offset;
  6533.                 Rect.top += y_offset;
  6534.                 Rect.bottom += y_offset;
  6535.             }
  6536.         }
  6537.  
  6538.         pRetval = LO_MapXYToAreaAnchor(GetDocumentContext(), pLOImage,
  6539.             m_cpMMove.x - Rect.left, m_cpMMove.y - Rect.top);
  6540.     }
  6541.  
  6542.     return(pRetval);
  6543. }
  6544.  
  6545. static void
  6546. free_this_callback(MWContext * context, LO_Element * lo_element, int32 event,
  6547.                   void * pObj, ETEventStatus status)
  6548. {
  6549.     XP_FREE(pObj);
  6550. }
  6551.  
  6552. //  Fire mouse out events for cached element types.
  6553. void CWinCX::FireMouseOutEvent(BOOL bClearElement, BOOL bClearAnchor, int32 xVal,
  6554.                    int32 yVal, CL_Layer *layer)
  6555. {
  6556.     // JS needs screen coords for click events.
  6557.     CPoint cpScreenPoint(xVal, yVal);
  6558.     ClientToScreen(GetPane(), &cpScreenPoint);
  6559.  
  6560.     //  Determine if we're sending an anchor out or an element out.
  6561.     if(m_pLastOverAnchorData)
  6562.     {
  6563.         //  Anchor data.
  6564.         //  Create a fake holder element here since we didn't save enough
  6565.         //    information and Win16 won't let us pass stack variables
  6566.         LO_Element * element = XP_NEW_ZAP(LO_Element);
  6567.         element->lo_text.type = LO_TEXT;
  6568.         element->lo_text.anchor_href = m_pLastOverAnchorData;
  6569.  
  6570.         // We use the text of the element to determine if it is still
  6571.         // valid later so give the dummy text struct's text a value.
  6572.         if (element->lo_text.anchor_href->anchor)
  6573.             element->lo_text.text = element->lo_text.anchor_href->anchor;
  6574.  
  6575.         JSEvent *event;
  6576.         event = XP_NEW_ZAP(JSEvent);
  6577.         event->type = EVENT_MOUSEOUT;
  6578.         event->x = xVal;
  6579.         event->y = yVal;
  6580.         event->docx = xVal + CL_GetLayerXOrigin(layer);
  6581.         event->docy = yVal + CL_GetLayerYOrigin(layer);
  6582.         event->screenx = cpScreenPoint.x;
  6583.         event->screeny = cpScreenPoint.y;
  6584.  
  6585.         event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  6586.             
  6587.         ET_SendEvent(GetContext(), element, event,
  6588.                      free_this_callback, element);
  6589.     }
  6590.     else if(m_pLastOverElement && (m_pLastOverElement->type == LO_IMAGE
  6591.             || m_pLastOverElement->type == LO_FORM_ELE ||        
  6592.             (m_pLastOverElement->type == LO_TEXT && 
  6593.             m_pLastOverElement->lo_text.anchor_href) 
  6594. #ifdef DOM
  6595.             || LO_IsWithinSpan(m_pLastOverElement)
  6596. #endif
  6597.             ))
  6598.     {
  6599.         //  Element.
  6600.         JSEvent *event;
  6601.         event = XP_NEW_ZAP(JSEvent);
  6602.         event->type = EVENT_MOUSEOUT;
  6603.         event->x = xVal;
  6604.         event->y = yVal;
  6605.         event->docx = xVal + CL_GetLayerXOrigin(layer);
  6606.         event->docy = yVal + CL_GetLayerYOrigin(layer);
  6607.         event->screenx = cpScreenPoint.x;
  6608.         event->screeny = cpScreenPoint.y;
  6609.  
  6610.         event->layer_id = LO_GetIdFromLayer(GetContext(), layer);
  6611.      
  6612.         ET_SendEvent(GetContext(), m_pLastOverElement, event,
  6613.                      NULL, this);
  6614.     }
  6615.  
  6616.     //
  6617.     // Mocha may have trashed the docuemnt, but it will still be safe
  6618.     //   to set the following elements to NULL.  Mocha can't have
  6619.     //   destroyed our context yet
  6620.     //
  6621.  
  6622.     if(bClearElement)   {
  6623.         m_pLastOverElement = NULL;
  6624.     }
  6625.     if(bClearAnchor)    {
  6626.         m_pLastOverAnchorData = NULL;
  6627.     }
  6628.  
  6629.     //  Clean up, these can now be empty.
  6630.     m_bLastOverTextSet = FALSE;
  6631. }
  6632.  
  6633. CFrameGlue *CWinCX::GetFrame() const
  6634. {
  6635.     //    If we're a grid cell, return the
  6636.     //        parent's frame (one in the same)
  6637.     //    This allows those scary times when we're
  6638.     //        a grid in an OLE server to work better
  6639.     //        when the frame's switch.
  6640.     MWContext *pParent = GetParentContext();
  6641.     if(IsGridCell() && pParent)    {
  6642.         if(ABSTRACTCX(pParent)->IsFrameContext())    {
  6643.             return(WINCX(pParent)->GetFrame());
  6644.         }
  6645.     }
  6646.  
  6647.     //    Make sure our frame isn't NULL.
  6648.     //    If so, go with the NULL frame.
  6649.     //    Could happen if the frame is destroyed, but the
  6650.     //        context lives.
  6651.     if(m_pFrame == NULL)    {
  6652.         return(m_pNullFrame);
  6653.     }
  6654.     return m_pFrame;
  6655. }
  6656.  
  6657. void CWinCX::ClearView()
  6658. {
  6659.     //    Tell the view and frame that we're no more.
  6660.     if(m_pGenView != NULL)    {
  6661.         //    Also, if we're selecting text, clear our capture of the mouse.
  6662.         if(m_bLBDown == TRUE)    {
  6663.             ::ReleaseCapture();
  6664.         }
  6665.         m_pGenView->ClearContext();
  6666.         m_pGenView = NULL;
  6667.     }
  6668. }
  6669.  
  6670. BOOL CWinCX::IsClickingEnabled() const
  6671. {
  6672. #ifdef EDITOR
  6673.     return(GetContext()->waitingMode == FALSE && GetContext()->edit_saving_url == FALSE);
  6674. #else
  6675.     return(GetContext()->waitingMode == FALSE);
  6676. #endif
  6677. }
  6678.  
  6679. //#ifndef NO_TAB_NAVIGATION 
  6680. LO_TabFocusData * CWinCX::getLastTabFocusData()
  6681. {
  6682.     return( &m_lastTabFocus );
  6683. }
  6684.  
  6685. LO_Element * CWinCX::getLastTabFocusElement()
  6686. {
  6687.     return( m_lastTabFocus.pElement );
  6688. }
  6689.  
  6690. int32 CWinCX::getLastFocusAreaIndex()
  6691. {
  6692.     return( m_lastTabFocus.mapAreaIndex );     // 0 means no focus, start with index 1.
  6693. }
  6694.  
  6695. LO_AnchorData    *CWinCX::getLastFocusAnchorPointer()
  6696. {
  6697.     return( m_lastTabFocus.pAnchor );
  6698. }
  6699.  
  6700. char *CWinCX::getLastFocusAnchorStr()
  6701. {
  6702.     if( m_lastTabFocus.pAnchor == NULL)
  6703.         return( NULL );
  6704.  
  6705.     return( (char *)m_lastTabFocus.pAnchor->anchor );
  6706. }
  6707.  
  6708. // When an element gets or losts Tab Focus, we need to invalidate it and hence to redraw it.
  6709. // check if(GetPane() && CanBlockDisplay() ) before calling invalidateElement().
  6710. void CWinCX::invalidateElement( LO_Element *pElement )
  6711. {
  6712.     if( pElement == NULL )
  6713.         return;
  6714.  
  6715.     // find out which element needs refresh.
  6716.     LTRB            Rect;
  6717.     BOOL            rectEmpty;
  6718.     LO_ImageStruct    *pImage;
  6719.     LO_Any            *pp = (LO_Any *)pElement;
  6720.     
  6721.     rectEmpty    = TRUE;
  6722.     
  6723.     switch( pElement->lo_any.type ) {
  6724.     case LO_FORM_ELE :
  6725.         if( LO_isFormElementNeedTextTabFocus( (LO_FormElementStruct *)pElement) ) {
  6726.             // for Form element type FORM_TYPE_RADIO and FORM_TYPE_CHECKBOX,
  6727.             // it is the next Text element, with dotted box, needs refresh.
  6728.             pp = (LO_Any *)pElement->lo_any.next;    
  6729.         }
  6730.         // for other Form element type( button, text input...), the widget handles the focus.
  6731.         ResolveElement(Rect, pp->x, pp->y, pp->x_offset,pp->y_offset, pp->width, pp->height);
  6732.         rectEmpty = FALSE;
  6733.         break;
  6734.     case LO_TEXT :
  6735.         // for a text(link), the element itself has a dotted box as focus.
  6736.         ResolveElement(Rect, pp->x, pp->y, pp->x_offset,pp->y_offset, pp->width, pp->height);
  6737.         rectEmpty = FALSE;
  6738.         break;
  6739.     case LO_IMAGE :
  6740.         // TODO only invalidate the area, not the whole map image.
  6741.         pImage = &pElement->lo_image;
  6742.         ResolveElement(Rect, IL_GetImagePixmap(pImage->image_req), 
  6743.                        pImage->x_offset + pImage->border_width,
  6744.                        pImage->y_offset + pImage->border_width, 
  6745.                        pImage->x, pImage->y, pImage->width, pImage->height);
  6746.  
  6747.         rectEmpty = FALSE;
  6748.         break;
  6749.     default :
  6750.         rectEmpty = TRUE;
  6751.         break;
  6752.     }
  6753.  
  6754.     if( rectEmpty )
  6755.         return;
  6756.  
  6757.     // no background erase
  6758.     ::InvalidateRect(GetPane(), CRect(CASTINT(Rect.left), CASTINT(Rect.top), CASTINT(Rect.right), CASTINT(Rect.bottom)), FALSE);
  6759.  
  6760. }
  6761.  
  6762. void CWinCX::SetActiveWindow()
  6763. {
  6764.     // Set my view to be the active view, so I will get keyboard input.
  6765.     // SetFocus cannot get keyboard, and it would grab focus from
  6766.     // Form elements. They need focus to process SpaceBar etc.
  6767.     CFrameGlue * pFrame = GetFrame();
  6768.     if( pFrame ) {
  6769.         CFrameWnd * pFrameWindow = pFrame->GetFrameWnd();
  6770.         if( pFrameWindow && pFrameWindow->IsKindOf(RUNTIME_CLASS(CGenericFrame)))    {
  6771.             CGenericView *pView = GetView();
  6772.             if( pView )     
  6773.                 pFrameWindow->SetActiveView( (CView *)pView );
  6774.         }
  6775.     } // else something wrong.
  6776.  
  6777. }
  6778.  
  6779. // this function is trigered by clicking in a form element, or link,
  6780. // the form element has set focus to itself. we need to clear old focus only.
  6781. // for clicking on link, we don't need to call Windows' setFocus().
  6782. void CWinCX::setFormElementTabFocus( LO_Element * pFormElement )
  6783. {
  6784.     LO_TabFocusData    newTabFocus;    
  6785.  
  6786.     if(pFormElement == getLastTabFocusElement() )  // clicking on the focused element.
  6787.         return;                                      
  6788.  
  6789.     newTabFocus.pElement        = pFormElement;
  6790.     MWContext *pContext = GetContext();
  6791.  
  6792.     // for clicking area.
  6793.     newTabFocus.mapAreaIndex    = 0;        // 0 means no area.
  6794.     newTabFocus.pAnchor            = NULL;
  6795.     
  6796.     // double check tab-able, and fill in pAnchor
  6797.     if( LO_isTabableElement(pContext, &newTabFocus ) ) {
  6798.         setLastTabFocusElement( &newTabFocus, 0 );  // clicked, 0 means don't needSetFocus
  6799.         SetMainFrmTabFocusFlag(CMainFrame::TAB_FOCUS_IN_GRID);  // I have tab focus.
  6800.     }
  6801.  
  6802. }
  6803.  
  6804. // text element may be fragmented in multiple lines, for Tab_focus, they
  6805. // need to be treated as one tab stop.
  6806. int CWinCX::invalidateSegmentedTextElement(LO_TabFocusData *pNextTabFocus, int forward )
  6807. {
  6808.     int        count = 0;
  6809.     LO_Element *pElement;
  6810.     pElement = pNextTabFocus->pElement;
  6811.     while(    pElement && 
  6812.             (pElement->lo_any.type == LO_TEXT || pElement->lo_any.type == LO_LINEFEED) ) {
  6813.                                                         // skip LO_LINEFEED
  6814.         if( pElement->lo_any.type == LO_TEXT ) {
  6815.             if( pElement->lo_text.anchor_href 
  6816.                 && pElement->lo_text.anchor_href == pNextTabFocus->pAnchor ) {
  6817.                 FEU_MakeElementVisible(  GetContext(), (LO_Any *) pElement );  
  6818.                 count++;
  6819.                 invalidateElement( pElement );
  6820.                 if( ! forward )
  6821.                     pNextTabFocus->pElement = pElement;  // move the current focus pointer to the first segment.
  6822.             } else {
  6823.                 break;            // stop searching ;
  6824.             }
  6825.         }    // if( pElement->lo_any.type == LO_TEXT ) 
  6826.  
  6827.         if( forward)
  6828.             pElement = pElement->lo_any.next;
  6829.         else
  6830.             pElement = pElement->lo_any.prev;
  6831.  
  6832.     }    // while(    pElement && 
  6833.     return count;
  6834. }
  6835.  
  6836. // this function is trigered by TAB key
  6837. // or called from setFormElementTabFocus() with byClickFormElement = 0, in such case
  6838. // the form element is visible and has the fucos already.
  6839. void CWinCX::setLastTabFocusElement( LO_TabFocusData *pNextTabFocus, int needSetFocus ) 
  6840. {
  6841.     LO_Element *pElement;
  6842.  
  6843.     // both old and new element can be NULL.
  6844.  
  6845.     // avoid setting focus on the same element.
  6846.     // For image map, the element may be the same, but the mapAreaIndex 
  6847.     // increase for each Tab.
  6848.     
  6849.     if( pNextTabFocus
  6850.         && m_lastTabFocus.pElement == pNextTabFocus->pElement
  6851.         && m_lastTabFocus.mapAreaIndex    == pNextTabFocus->mapAreaIndex    )
  6852.         return;                                      
  6853.  
  6854.     if( m_isReEntry_setLastTabFocusElement ) 
  6855.         return;
  6856.     m_isReEntry_setLastTabFocusElement = 1;
  6857.  
  6858.     // need to redraw those 2 elements for visual feedback.
  6859.     if(GetPane() && CanBlockDisplay() )    {
  6860.         // the new element gets the focus.
  6861.         pElement = pNextTabFocus->pElement;
  6862.         if( NULL != pElement)  {
  6863.             if( needSetFocus ) {
  6864.                 SetActiveWindow();
  6865.                 // FEU_MakeElementVisible must happen before invalidate
  6866.                 FEU_MakeElementVisible(  GetContext(), (LO_Any *) pElement );  
  6867.                 invalidateElement( pElement );
  6868.             
  6869.                 if( pElement->lo_any.type == LO_FORM_ELE) {        
  6870.                     // Form elements need focus to get keyboard input.
  6871.                     // this will loop back to setFormElementTabFocus(), That
  6872.                     // is why we need the re-entry protection.
  6873.                     FE_FocusInputElement(GetContext(), pElement ); 
  6874.                 } else {
  6875.                     CGenericFrame * pFrame = (CGenericFrame * )FEU_GetLastActiveFrame();
  6876.                     if( pFrame )
  6877.                         pFrame->SetFocus();        // set focus to the window.
  6878.                 }
  6879.             }
  6880.                 
  6881.             if( pElement->lo_any.type == LO_TEXT            // defined_as 1
  6882.                 || pElement->lo_any.type == LO_FORM_ELE        // defined_as 6
  6883.                     && LO_isFormElementNeedTextTabFocus( (LO_FormElementStruct *)pElement) ) {
  6884.                 
  6885.                 // first trace back for the first segmented text.
  6886.                 // need to do this when: tab backward, and click on not-first segment.
  6887.                 invalidateSegmentedTextElement(pNextTabFocus, 1);    // forward
  6888.                 
  6889.                 // trace down the fragmented text for a link.
  6890.                 invalidateSegmentedTextElement(pNextTabFocus, 0);    // backward, set to first
  6891.             }
  6892.         }    // if( NULL != pElement) , the new element
  6893.  
  6894.         // the old element losts the focus
  6895.         pElement = getLastTabFocusElement();
  6896.         if( NULL !=  pElement)  {
  6897.             
  6898.             invalidateElement( pElement );
  6899.  
  6900.             if( pElement->lo_any.type == LO_FORM_ELE) {
  6901.                 FE_BlurInputElement(GetContext(), pElement );
  6902.             } 
  6903.             
  6904.             if( pElement->lo_any.type == LO_TEXT 
  6905.                 || pElement->lo_any.type == LO_FORM_ELE 
  6906.                     && LO_isFormElementNeedTextTabFocus( (LO_FormElementStruct *)pElement) ) {
  6907.                 // remove focus box for all continnuios text fragments.
  6908.                 // because it is always pointing to the first segment, no need to go backward.
  6909.                 invalidateSegmentedTextElement(getLastTabFocusData(), 1);    // forward
  6910.             }
  6911.  
  6912.         }    // if( NULL !=  pElement), the old element
  6913.         
  6914.     }    // if(GetPane() && CanBlockDisplay() )    
  6915.  
  6916.     m_lastTabFocus.pElement        = pNextTabFocus->pElement;
  6917.     m_lastTabFocus.mapAreaIndex    = pNextTabFocus->mapAreaIndex;        // 0 means no focus, start with index 1.
  6918.     m_lastTabFocus.pAnchor        = pNextTabFocus->pAnchor    ;
  6919.  
  6920.     // update the status bar.
  6921.     // For all LO_ types which update status bar, see CWinCX::OnMouseMoveForLayerCX(UINT uFlags, CPoint& cpPoint,
  6922.  
  6923.     if( getLastFocusAnchorStr() != NULL )
  6924.         wfe_Progress(GetContext(), getLastFocusAnchorStr() );
  6925.     else
  6926.         wfe_Progress(GetContext(), "");
  6927.     
  6928.     m_isReEntry_setLastTabFocusElement = 0;
  6929.     return;
  6930. }    // CWinCX::setLastTabFocusElement()
  6931.  
  6932. // try to set Tab Focus in this CWinCX only.
  6933. BOOL CWinCX::setNextTabFocusInWin( int forward )
  6934. {
  6935.     BOOL            found;
  6936.     LO_TabFocusData    newTabFocus;    
  6937.  
  6938.     newTabFocus.pElement        = m_lastTabFocus.pElement;
  6939.     newTabFocus.mapAreaIndex    = m_lastTabFocus.mapAreaIndex;        // 0 means no area
  6940.     newTabFocus.pAnchor            = m_lastTabFocus.pAnchor    ;
  6941.  
  6942.     found = LO_getNextTabableElement( GetContext(), &newTabFocus, forward );
  6943.  
  6944.     // even  new element is NULL, need to clear the old focus
  6945.     setLastTabFocusElement( &newTabFocus, 1 );    // key, not click, needSetFocus
  6946.  
  6947.     return( found );
  6948. }    // BOOL CWinCX::setNextTabFocusInWin( int forward )
  6949.  
  6950. // this function searchs for sibling CWinCX, and set Tab focus.
  6951. // See MWContext * XP_FindNamedContextInList(MWContext * context, char *name)
  6952. // in ns\lib\xp\xp_cntxt.c for navigating grid_parent - grid_children tree.
  6953. BOOL CWinCX::setTabFocusNext( int forward )
  6954. {
  6955.     BOOL        ret;
  6956.  
  6957.     // First try myself and my children.
  6958.     ret = setTabFocusNextChild( NULL, forward ) ;  // no exclusive child
  6959.     if( ret )                
  6960.         return( TRUE );                // all done
  6961.  
  6962.     // TODO loop to search up all parents
  6963.     // now try to set focus to siblings
  6964.  
  6965.     // if I am on the top, I cannot have sibling.
  6966.     if( IsGridCell() != TRUE ) 
  6967.         return( FALSE );
  6968.     
  6969.     MWContext *pParent = GetParentContext();    
  6970.     if(  pParent == NULL)    
  6971.         return( FALSE );
  6972.  
  6973.     if( ! ABSTRACTCX(pParent)->IsWindowContext() )
  6974.         return( FALSE );
  6975.     
  6976.     ret = WINCX(pParent)->setTabFocusNextChild( GetContext(), forward ) ;
  6977.     if ( ret )
  6978.         return( TRUE );
  6979.     
  6980.     return( FALSE );
  6981. }
  6982.  
  6983. BOOL CWinCX::setTabFocusNextChild( MWContext *currentChildContext, int forward ) 
  6984. {
  6985.     BOOL        ret;
  6986.     XP_List        *gridListHead, *gridList;
  6987.     MWContext    *pChild;
  6988.     // MWContext    *pCurrent = ( MWContext *) currentChild;
  6989.  
  6990.     // try myself first
  6991.     ret = setNextTabFocusInWin( forward ) ;
  6992.     if( ret ) {
  6993.         return( TRUE );
  6994.     }
  6995.  
  6996.     //    If not a parent, return. over kill?
  6997.     if( IsGridParent() == FALSE)
  6998.         return( FALSE );
  6999.  
  7000.     // see ns\lib\xp\xp_list.c for navigating the list.
  7001.     gridListHead    = GetContext()->grid_children;
  7002.     if( currentChildContext )
  7003.         gridList    = XP_ListFindObject( gridListHead, currentChildContext );
  7004.     else 
  7005.         gridList  = gridListHead;        // , start from head, The head node is always empty(no data).
  7006.  
  7007.     if( gridList != NULL )            // revers order??
  7008.         gridList = forward ? gridList->prev : gridList->next ;        // the list is in revers order
  7009.     
  7010.     while( gridList != NULL ) {
  7011.         pChild = (MWContext *) gridList->object ;
  7012.         if( ABSTRACTCX(pChild)->IsWindowContext() ) {
  7013.             TRACE0("recursive setTabFocusNextChild()\n");
  7014.             ret = WINCX(pChild)->setTabFocusNextChild( NULL, forward ) ;  // no exlusive child.
  7015.             if( ret )
  7016.                 return( ret );
  7017.         }
  7018.         gridList = forward ? gridList->prev : gridList->next ;        // the list is in revers order
  7019.     }
  7020.  
  7021.     return( FALSE );
  7022. }
  7023.     
  7024. BOOL CWinCX::fireTabFocusElement( UINT nChar)        
  7025. {
  7026.     int32            mapAreaIndex, xx, yy;
  7027.     lo_MapAreaRec    *theArea;
  7028.  
  7029.     LO_Element *pFocusElement    = getLastTabFocusElement();
  7030.     if( pFocusElement == NULL )
  7031.         return( FALSE );
  7032.     
  7033.     // SpaceBar Return are handled by Form itself for 
  7034.     // all Form elements, including checkbox and radio.
  7035.     // Here we only take care of the links
  7036.  
  7037.     if( pFocusElement->lo_any.type == LO_IMAGE )    { 
  7038.         mapAreaIndex = getLastFocusAreaIndex();
  7039.         if( mapAreaIndex > 0 ) {
  7040.             // the focus is in a map area
  7041.             theArea = LO_getTabableMapArea( GetContext(), (LO_ImageStruct *)pFocusElement, mapAreaIndex );
  7042.             if( theArea && LO_findApointInArea( theArea, &xx, &yy ) ) {
  7043.                 // Area coordinates are relative to the image, add the left-top of the image.
  7044.                 xx += pFocusElement->lo_any.x;    
  7045.                 yy += pFocusElement->lo_any.y;
  7046.                 if ( FE_ClickAnyElement( GetContext(), pFocusElement, 1, xx, yy ) )    // click the center
  7047.                     return( TRUE );
  7048.             }
  7049.             return( FALSE );
  7050.         }    
  7051.         // else mapAreaIndex not > 0, it is a link for the whole image, fall through.
  7052.     }
  7053.  
  7054.     if(        pFocusElement->lo_any.type == LO_TEXT 
  7055.         ||    pFocusElement->lo_any.type == LO_IMAGE )    { 
  7056.         // it is a link
  7057.         if ( FE_ClickAnyElement( GetContext(), pFocusElement, 0, 0, 0 ) )    // click the center
  7058.             return( TRUE );
  7059.     }
  7060.  
  7061.     return( FALSE );
  7062. }
  7063.  
  7064. int CWinCX::getImageDrawFlag( MWContext *pContext, LO_ImageStruct *pImage, lo_MapAreaRec **ppArea, uint32 *pFlag )
  7065. {
  7066.     LO_Element        *pFocusElement;
  7067.     int32            lastAreaIndex;
  7068.     lo_MapAreaRec    *theArea;
  7069.  
  7070.     // clear the flag first
  7071.     *pFlag &= ~FE_DRAW_TAB_FOCUS ;
  7072.  
  7073.     
  7074.     if( pImage == NULL )
  7075.         return( 0 );
  7076.  
  7077.     pFocusElement    = getLastTabFocusElement();
  7078.     if( pFocusElement == NULL)
  7079.         return( 0 );
  7080.  
  7081.     if( pFocusElement != (LO_Element *) pImage )
  7082.         return( 0 );
  7083.  
  7084.     lastAreaIndex = getLastFocusAreaIndex();
  7085.     if( lastAreaIndex < 0 )                    // error
  7086.         return(0);
  7087.  
  7088.     if( lastAreaIndex == 0 ) {        // no area, the whole image is focused.
  7089.         LO_AnchorData *pLastAnchor = getLastFocusAnchorPointer();
  7090.         if (pLastAnchor && !(pLastAnchor->flags & ANCHOR_SUPPRESS_FEEDBACK)) {
  7091.             *pFlag |= FE_DRAW_TAB_FOCUS;
  7092.             return(1);
  7093.         }
  7094.     }
  7095.     
  7096.     theArea = LO_getTabableMapArea( pContext, pImage, lastAreaIndex );
  7097.  
  7098.     // Don't draw selection rectangle if it's been disabled
  7099.     if(theArea && !(theArea->anchor && (theArea->anchor->flags & ANCHOR_SUPPRESS_FEEDBACK))) {
  7100.         *pFlag |= FE_DRAW_TAB_FOCUS ;
  7101.         *ppArea = theArea;            // only the area is focused.
  7102.         return( 1 );
  7103.     }
  7104.     
  7105.     return( 0 );
  7106.  
  7107. }
  7108.  
  7109. int CWinCX::setTextTabFocusDrawFlag( LO_TextStruct *pText, uint32 *pFlag )
  7110. {
  7111.     // Visual feedback for Tab Focus is a dotted box around text or image.
  7112.     // For 2 Form elements, check box and radio button, the box is on
  7113.     // the text following the button.
  7114.     //
  7115.     // The text may have been fragmented into multiple lines because the line folding.
  7116.     // When line width changes, fragments can be generated, or merged. It can happen 
  7117.     // anytime when the width of Navigator is changed. So, it cannot be handled
  7118.     // when Tab key is pressed.
  7119.     // 
  7120.     // When searching for next Tabable element, focus is moved to next different anchor.
  7121.     // Continuious text fragments are skipped.
  7122.     // See LO_getNextTabableElement() in lib\layout\laysel.c file.
  7123.     //
  7124.     // To find all focus text fragments, the Anchor data is checked. Every fragment has
  7125.     // its own copy of duplicated Anchor pointer. If it is the same as the Focused element,
  7126.     // the text will be drawn as focused.
  7127.     //
  7128.     // When an element losts Tab focus, all dotted fragments need redraw to erase the focus.
  7129.     //
  7130.  
  7131.     // assuming no focus and clear the flag first.
  7132.     *pFlag &= ~FE_DRAW_TAB_FOCUS ;
  7133.  
  7134.     if( pText == NULL )
  7135.         return(0);
  7136.  
  7137.     LO_Element *pCurrentElement, *pPreviousElement, *pFocusElement;
  7138.  
  7139.     pFocusElement    = getLastTabFocusElement();
  7140.     if( pFocusElement == NULL)
  7141.         return(0);
  7142.  
  7143.     // Don't draw selection rectangle if it's been disabled
  7144.     if ( pText->anchor_href 
  7145.          && pText->anchor_href->flags & ANCHOR_SUPPRESS_FEEDBACK)
  7146.         return(0);
  7147.  
  7148.     pCurrentElement = (LO_Element *) pText;
  7149.  
  7150.     // return focus if it is a link and it has Tab focus
  7151.     if( pFocusElement == pCurrentElement ) {
  7152.         *pFlag |= FE_DRAW_TAB_FOCUS;
  7153.         return( 1 );
  7154.     }
  7155.  
  7156.     // test fragmented text for a link.
  7157.     // is one fragmented element.
  7158.     if( pFocusElement->lo_any.type == LO_TEXT          // fix for bug #45111
  7159.         && pText->anchor_href 
  7160.         && pText->anchor_href == getLastFocusAnchorPointer() ) {
  7161.         *pFlag |= FE_DRAW_TAB_FOCUS ;
  7162.         return( 1 );
  7163.     }
  7164.  
  7165.     // Test if it is a text element following a Form element checkBox(or radio button),
  7166.     // which has focus. If it is, the text(not the button) needs to draw the focus box.
  7167.     //todo in html, two separated element may have the same link. need to make sure it
  7168.     pPreviousElement = pCurrentElement->lo_any.prev;
  7169.     if( pPreviousElement != NULL  && pPreviousElement == pFocusElement ) {
  7170.         if( LO_isFormElementNeedTextTabFocus( (LO_FormElementStruct *)pPreviousElement ) ) {
  7171.             *pFlag |= FE_DRAW_TAB_FOCUS ;
  7172.             return(1);
  7173.         }
  7174.     }
  7175.  
  7176.     return(0);
  7177.     
  7178. }    // isTabFocusText()
  7179. //#endif    /* NO_TAB_NAVIGATION */
  7180.  
  7181. void CWinCX::CancelSizing()
  7182. {
  7183. #ifdef EDITOR
  7184.     ASSERT(EDT_IS_EDITOR(GetContext()));
  7185.     // Remove last sizing feedback
  7186.     DisplaySelectionFeedback(LO_ELE_SELECTED, m_rectSizing);
  7187.     EDT_CancelSizing(GetContext());
  7188. #endif // EDITOR
  7189. }
  7190.  
  7191.  
  7192.