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

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  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. // button.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "fmabstra.h"
  22.  
  23. #include "button.h"
  24.  
  25. #include "libevent.h"
  26. #include <windowsx.h>
  27.  
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char BASED_CODE THIS_FILE[] = __FILE__;
  31. #endif
  32.  
  33. #ifndef _AFXDLL
  34. #define new DEBUG_NEW  // MSVC Debugging new...goes to regular new in release mode
  35. #endif
  36.  
  37. #ifndef _WIN32
  38. #define GET_WM_COMMAND_CMD(wp, lp)    ((UINT)HIWORD(lp))
  39. #endif
  40.  
  41. /////////////////////////////////////////////////////////////////////////////
  42. /////////////////////////////////////////////////////////////////////////////
  43. /////////////////////////////////////////////////////////////////////////////
  44. // CNetscapeButton dialog
  45.  
  46. IMPLEMENT_DYNAMIC(CNetscapeButton, CButton)                                     
  47.  
  48. CNetscapeButton::CNetscapeButton(MWContext * context, LO_FormElementStruct * form, CWnd* pParent)
  49. {
  50.     m_Context = context;
  51.     m_Form = form;
  52.     m_bDepressed = FALSE;
  53.     m_pwndEdit = NULL;
  54.     m_pPaneCX = PANECX(m_Context);
  55.     m_callBase = FALSE;
  56. }
  57.  
  58. BEGIN_MESSAGE_MAP(CNetscapeButton, CButton)
  59.     ON_WM_CHAR()
  60.     ON_WM_SETFOCUS()
  61.     ON_WM_KILLFOCUS()
  62.     ON_WM_LBUTTONDBLCLK()
  63.     ON_WM_LBUTTONDOWN()
  64.     ON_WM_LBUTTONUP()
  65.     ON_WM_RBUTTONDBLCLK()
  66.     ON_WM_RBUTTONDOWN()
  67.     ON_WM_RBUTTONUP()
  68. END_MESSAGE_MAP()
  69.  
  70. /////////////////////////////////////////////////////////////////////////////
  71. // CNetscapeButton message handlers
  72. /////////////////////////////////////////////////////////////////////////////
  73.  
  74. //
  75. // Called when the 'submit' event has been processed
  76. //
  77. static void
  78. button_submit_closure(MWContext * pContext, LO_Element * pEle, int32 event,
  79.                      void * pObj, ETEventStatus status)
  80. {
  81.     if(status != EVENT_OK || !pEle || !pContext)
  82.         return;
  83.     FE_SubmitInputElement(pContext, pEle);
  84. }
  85.  
  86. //
  87. // Called when the 'click' event has been processed
  88. //
  89. static void
  90. button_click_closure(MWContext * pContext, LO_Element * pEle, int32 event,
  91.                      void * pObj, ETEventStatus status)
  92. {
  93.  
  94.     // make sure every thing is OK
  95.     if(status == EVENT_PANIC || !pEle || !pContext)
  96.         return;
  97.  
  98.     CNetscapeButton      * pButton = (CNetscapeButton *) pObj;
  99.     LO_FormElementStruct * pForm   = (LO_FormElementStruct *) pEle;
  100.  
  101.     lo_FormElementMinimalData * min_data;
  102.     lo_FormElementToggleData  * tog_data;
  103.     min_data = (lo_FormElementMinimalData *) pForm->element_data;
  104.  
  105.     if(!min_data)
  106.         return;
  107.  
  108.     if(status == EVENT_OK) {
  109.         switch(min_data->type) {
  110.             case FORM_TYPE_SUBMIT:
  111.                 // send the event to libmocha --- do any further processing
  112.                 //   in our closure routine
  113.         JSEvent *event;
  114.         event = XP_NEW_ZAP(JSEvent);
  115.         event->type = EVENT_SUBMIT;
  116.         event->layer_id = pForm->layer_id;
  117.                 
  118.         ET_SendEvent(pContext, pEle, event, 
  119.                              button_submit_closure, pObj);
  120.                 break;
  121.  
  122.             case FORM_TYPE_RESET:
  123.                 // libmocha has said it was OK to allow the reset to happen
  124.                 //   tell layout to go forward with the operation
  125.                 // the world may not be safe after this so return
  126.                 LO_ResetForm(pContext, pForm);
  127.                 return;
  128.  
  129.             default:
  130.                 break;
  131.         }
  132.     }
  133.     else    {
  134.         //  Undo state operations.
  135.         switch(min_data->type) {
  136.             case FORM_TYPE_RADIO:
  137.                 if(pButton->m_pLastSelectedRadio)  {
  138.                     tog_data = (lo_FormElementToggleData *)
  139.                         pButton->m_pLastSelectedRadio->element_data;
  140.                     if(!tog_data->toggled)
  141.                         LO_FormRadioSet(ABSTRACTCX(pContext)->GetDocumentContext(), 
  142.                                     pButton->m_pLastSelectedRadio);
  143.  
  144.                     CFormElement *pRadioButton = CFormElement::GetFormElement(ABSTRACTCX(pContext), 
  145.                                                    pButton->m_pLastSelectedRadio);
  146.                     if(pRadioButton)    {
  147.                         pRadioButton->SetFormElementToggle(tog_data->toggled);
  148.                     }
  149.                 }
  150.                 break;
  151.             case FORM_TYPE_CHECKBOX: 
  152.                 tog_data = (lo_FormElementToggleData *) pForm->element_data;
  153.                 if(tog_data->toggled)
  154.                     tog_data->toggled = FALSE;
  155.                 else 
  156.                     tog_data->toggled = TRUE;
  157.  
  158.                 if((pButton->GetCheck() ? TRUE : FALSE) != tog_data->toggled)
  159.                     pButton->SetCheck(tog_data->toggled);
  160.  
  161.                 break;
  162.             default:
  163.                 break;
  164.         }
  165.     }
  166.  
  167. }
  168.  
  169.  
  170. //  NFlags as per OnLButtonUp
  171. //
  172. //  
  173. //  for FORM_TYPE_CHECKBOX, there are 3 places in this file call Click().
  174. //  1. OnChar           for space-key
  175. //  2. OnButtonEvent,   initiated by java script?
  176. //  3. OnChildNotify    maybe not necesary to handle this msg.
  177. // 
  178. //  We taggled state for 1 and 2.We do NOT taggle for 3. It always comes 
  179. //  with 1 or 2. It is not clear whether item 3 is redundent, so it is 
  180. //  not removed.
  181. //
  182. //  Click() function is still called for all 3 cases. 
  183. //  
  184. //  Messages interfare with debug, Trace statements are left for debuging.
  185. //
  186. //  When change this code, please make sure radio-button and check-box 
  187. //  work for both Tab-Space keys and mouse click(with out debug).
  188. //  
  189. //  Arthur 3/12/97, fix for #49682
  190. // 
  191. void CNetscapeButton::Click(UINT nFlags, BOOL bNotify, BOOL &bReturnImmediately)  
  192. {
  193.     if(!m_Form || !m_Context)
  194.         return;
  195.  
  196.     lo_FormElementMinimalData * min_data;
  197.     lo_FormElementToggleData  * tog_data;
  198.     min_data = (lo_FormElementMinimalData *) m_Form->element_data;
  199.     char * pFileName;
  200.     if(!min_data)
  201.         return;
  202.  
  203.     m_pLastSelectedRadio = NULL;
  204.     switch(min_data->type) {
  205.  
  206.     case FORM_TYPE_RADIO:
  207.         tog_data = (lo_FormElementToggleData *) m_Form->element_data;
  208.         if(!tog_data->toggled) {
  209.             m_pLastSelectedRadio = LO_FormRadioSet(ABSTRACTCX(m_Context)->GetDocumentContext(), m_Form);  // Turn off everyone else
  210.         }
  211.         if(GetCheck() != tog_data->toggled)   {
  212.             SetCheck(tog_data->toggled);
  213. #ifdef DEBUG_aliu
  214.             TRACE0("Set\n");
  215. #endif  // DEBUG_aliu
  216.         }
  217.         break;
  218.  
  219.     case FORM_TYPE_CHECKBOX: 
  220.         //  Make sure we don't already reflect that state, and don't do this
  221.         //      if via OnChar, as MFC/Windows will do it for us.
  222.         if(bNotify == FALSE)    {
  223.             tog_data = (lo_FormElementToggleData *) m_Form->element_data;
  224.             if(tog_data->toggled) {
  225. #ifdef DEBUG_aliu
  226.                 TRACE0("Off ");
  227. #endif  // DEBUG_aliu
  228.                 tog_data->toggled = FALSE;
  229.             } else {
  230.                 tog_data->toggled = TRUE;
  231. #ifdef DEBUG_aliu
  232.                 TRACE0("On ");
  233. #endif  // DEBUG_aliu
  234.             }
  235.  
  236.              if((GetCheck() ? TRUE : FALSE) != tog_data->toggled)  {
  237. #ifdef DEBUG_aliu
  238.                 TRACE0("Set\n");
  239. #endif  // DEBUG_aliu
  240.                 SetCheck(tog_data->toggled);
  241.              }
  242.         }
  243.         break;
  244.  
  245.     case FORM_TYPE_BUTTON:
  246.         break;
  247.  
  248.     case FORM_TYPE_RESET: 
  249.     case FORM_TYPE_SUBMIT:
  250.         // don't do anything yet --- send the OnClick to libmocha first
  251.     // Sigh don't make double submits
  252.     if (bNotify == TRUE) return;
  253.         break; 
  254.  
  255.     case FORM_TYPE_FILE:
  256.         pFileName = wfe_GetExistingFileName(m_hWnd, 
  257.                         szLoadString(IDS_FILE_UPLOAD), 
  258.                         HTM, 
  259.                         TRUE);
  260.  
  261.         /* update both the widget display and the lo-datastructure */
  262.     if(pFileName && m_pwndEdit) {
  263.             m_pwndEdit->SetWindowText(pFileName);
  264.  
  265.         if (m_Form->element_data->ele_text.current_text)
  266.         XP_FREE(m_Form->element_data->ele_text.current_text);
  267.  
  268.         m_Form->element_data->ele_text.current_text = (PA_Block) pFileName;
  269.     }
  270.  
  271.         break;
  272.  
  273.     default:
  274.         break;
  275.  
  276.     }
  277.  
  278.     // send the event to libmocha --- do any further processing
  279.     //   in our closure routine
  280.     JSEvent *event;
  281.     event = XP_NEW_ZAP(JSEvent);
  282.     event->type = EVENT_CLICK;
  283.     event->layer_id = m_Form->layer_id;
  284.     event->which = 1;
  285.     event->modifiers = (nFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  286.             | (nFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  287.             | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  288.  
  289.     ET_SendEvent(m_Context, (LO_Element *)m_Form, event, 
  290.                  button_click_closure, this);
  291.  
  292. }
  293.  
  294. void CNetscapeButton::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
  295. {
  296.     // CButton::OnChar( nChar,  nRepCnt, nFlags);
  297.     if(( nChar == VK_SPACE  || nChar == VK_RETURN) && !(nFlags>>14 & 1))  {
  298.         //  buttons need a push.
  299.         BOOL bReturnImmediately = FALSE;
  300. #ifdef DEBUG_aliu
  301.         TRACE0("onCharClick ");
  302. #endif  // DEBUG_aliu
  303.         Click(0, FALSE, bReturnImmediately);   //#49682 TRUE
  304.         if(bReturnImmediately)  {
  305.             return;
  306.         }
  307.     }
  308. }
  309.  
  310. void CNetscapeButton::OnSetFocus(CWnd * pWnd)
  311. {
  312.     CButton::OnSetFocus(pWnd);        //must have this for fixing #51086, ref. #49682 
  313.     if(m_Context && m_Form) {
  314.         // set tab focus to this element
  315.         CWinCX *pWinCX = WINCX(m_Context);
  316. //    if ((LO_Element *)m_Form == pWinCX->getLastTabFocusElement())
  317. //        return;
  318.  
  319.         pWinCX->setFormElementTabFocus( (LO_Element *)m_Form );
  320.  
  321.         // send the event to libmocha --- do any further processing
  322.         //   in our closure routine
  323.     JSEvent *event;
  324.     event = XP_NEW_ZAP(JSEvent);
  325.     event->type = EVENT_FOCUS;
  326.     event->layer_id = m_Form->layer_id;
  327.         
  328.     ET_SendEvent(m_Context, (LO_Element *)m_Form, event, 
  329.             NULL, this);
  330.     }
  331. }
  332.  
  333.  
  334. void CNetscapeButton::OnKillFocus(CWnd * pWnd)
  335. {
  336.     CButton::OnKillFocus(pWnd);
  337.     if(m_Context && m_Form) {
  338.         // send the event to libmocha --- do any further processing
  339.         //   in our closure routine
  340.     JSEvent *event;
  341.     event = XP_NEW_ZAP(JSEvent);
  342.     event->type = EVENT_BLUR;
  343.     event->layer_id = m_Form->layer_id;
  344.         
  345.     ET_SendEvent(m_Context, (LO_Element *)m_Form, event, NULL, this);
  346.     }
  347. }
  348.  
  349. void CNetscapeButton::OnLButtonDblClk(UINT uFlags, CPoint cpPoint)    {
  350.  
  351.     if (m_callBase) {
  352.     CButton::OnLButtonDblClk(uFlags, cpPoint);
  353.     return;
  354.     }
  355.  
  356.     //    Don't continue if this context is destroyed.
  357.     if(!m_Context || ABSTRACTCX(m_Context)->IsDestroyed())    {
  358.         return;
  359.     }
  360.  
  361.     MapWindowPoints(GetParent(), &cpPoint, 1);     
  362.  
  363.     //    Convert the point to something we understand.
  364.     XY Point;
  365.     m_pPaneCX->ResolvePoint(Point, cpPoint);
  366.  
  367.     if (m_Context->compositor) {
  368.         CL_Event event;
  369.         fe_EventStruct fe_event;
  370.         
  371.         fe_event.uFlags = uFlags;
  372.         fe_event.x = cpPoint.x;
  373.         fe_event.y = cpPoint.y;
  374.         
  375.         event.type = CL_EVENT_MOUSE_BUTTON_MULTI_CLICK;
  376.         event.fe_event = (void *)&fe_event;
  377.         event.fe_event_size = sizeof(fe_EventStruct);
  378.         event.x = Point.x;
  379.         event.y = Point.y;
  380.         event.which = 1;
  381.         event.data = 2;
  382.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  383.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  384.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  385.     
  386.         CL_DispatchEvent(m_Context->compositor,
  387.                  &event);
  388.     }
  389.     else 
  390.         CButton::OnLButtonDblClk(uFlags, cpPoint);
  391.  
  392.     return;
  393. }
  394.  
  395. void CNetscapeButton::OnLButtonDown(UINT uFlags, CPoint cpPoint)    {
  396.  
  397.     if (m_callBase) {
  398.         CButton::OnLButtonDown(uFlags, cpPoint);
  399.     return;
  400.     }
  401.  
  402.     //    Don't continue if this context is destroyed.
  403.     if(!m_Context)    {
  404.         return;
  405.     }
  406.  
  407.     //    Start capturing all mouse events.
  408.     if(m_hWnd)    {
  409.     ::SetCapture(m_hWnd);
  410.     }
  411.  
  412.     MapWindowPoints(GetParent(), &cpPoint, 1);     
  413.  
  414.     XY Point;
  415.     m_pPaneCX->ResolvePoint(Point, cpPoint);
  416.  
  417.     if (m_Context->compositor) {
  418.         CL_Event event;
  419.         fe_EventStruct fe_event;
  420.         
  421.         fe_event.uFlags = uFlags;
  422.         fe_event.x = cpPoint.x;
  423.         fe_event.y = cpPoint.y;
  424.  
  425.         event.type = CL_EVENT_MOUSE_BUTTON_DOWN;
  426.         event.fe_event = (void *)&fe_event;
  427.         event.fe_event_size = sizeof(fe_EventStruct);
  428.         event.x = Point.x;
  429.         event.y = Point.y;
  430.         event.which = 1;
  431.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  432.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  433.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  434.     
  435.         CL_DispatchEvent(m_Context->compositor,
  436.                  &event);
  437.     }
  438.     else 
  439.  
  440.         CButton::OnLButtonDown(uFlags, cpPoint);
  441.  
  442.     return;
  443.  
  444. }
  445. void CNetscapeButton::OnLButtonUp(UINT uFlags, CPoint cpPoint)    {
  446.  
  447.     if (m_callBase) {
  448.     CButton::OnLButtonUp(uFlags, cpPoint);
  449.         return;
  450.     }
  451.  
  452.     //    Don't continue if this context is destroyed.
  453.     if(!m_Context)    {
  454.         return;
  455.     }
  456.  
  457.     //    Start capturing all mouse events.
  458.     if(m_hWnd)    {
  459.         ::ReleaseCapture();
  460.     }
  461.  
  462.     // translate mouse position to screen
  463.     CPoint cpScreenPoint(cpPoint);
  464.     ClientToScreen(&cpScreenPoint);
  465.  
  466.     //  Don't send the event on to JS if we're out of the button area.
  467.     if (::WindowFromPoint(cpScreenPoint) != m_hWnd) {
  468.     CButton::OnLButtonUp(uFlags, cpPoint);
  469.     m_bDepressed = FALSE;
  470.     return;
  471.     }
  472.     
  473.     MapWindowPoints(GetParent(), &cpPoint, 1);     
  474.  
  475.     XY Point;
  476.     m_pPaneCX->ResolvePoint(Point, cpPoint);
  477.  
  478.     if (m_Context->compositor) {
  479.         CL_Event event;
  480.         fe_EventStruct fe_event;
  481.         
  482.         fe_event.uFlags = uFlags;
  483.         fe_event.x = cpPoint.x;
  484.         fe_event.y = cpPoint.y;
  485.  
  486.         event.type = CL_EVENT_MOUSE_BUTTON_UP;
  487.         event.fe_event = (void *)&fe_event;
  488.         event.fe_event_size = sizeof(fe_EventStruct);
  489.         event.x = Point.x;
  490.         event.y = Point.y;
  491.         event.which = 1;
  492.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  493.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  494.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  495.     
  496.         CL_DispatchEvent(m_Context->compositor,
  497.                  &event);
  498.     }
  499.     else 
  500.         CButton::OnLButtonUp(uFlags, cpPoint);
  501.  
  502.     return;
  503.  
  504. }
  505.  
  506. void CNetscapeButton::OnRButtonDblClk(UINT uFlags, CPoint cpPoint)    {
  507.  
  508.     if (m_callBase) {
  509.         CButton::OnRButtonDblClk(uFlags, cpPoint);
  510.     return;
  511.     }
  512.  
  513.     //    Don't continue if this context is destroyed.
  514.     if(!m_Context)    {
  515.         return;
  516.     }
  517.  
  518.     MapWindowPoints(GetParent(), &cpPoint, 1);     
  519.  
  520.     XY Point;
  521.     m_pPaneCX->ResolvePoint(Point, cpPoint);
  522.  
  523.     if (m_Context->compositor) {
  524.         CL_Event event;
  525.         fe_EventStruct fe_event;
  526.         
  527.         fe_event.uFlags = uFlags;
  528.         fe_event.x = cpPoint.x;
  529.         fe_event.y = cpPoint.y;
  530.         
  531.         event.type = CL_EVENT_MOUSE_BUTTON_MULTI_CLICK;
  532.         event.fe_event = (void *)&fe_event;
  533.         event.fe_event_size = sizeof(fe_EventStruct);
  534.         event.x = Point.x;
  535.         event.y = Point.y;
  536.         event.which = 3;
  537.         event.data = 2;
  538.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  539.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  540.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  541.     
  542.         CL_DispatchEvent(m_Context->compositor,
  543.                  &event);
  544.     }
  545.     else 
  546.         CButton::OnRButtonDblClk(uFlags, cpPoint);
  547.  
  548.     return;
  549. }
  550.  
  551. void CNetscapeButton::OnRButtonDown(UINT uFlags, CPoint cpPoint)    {
  552.  
  553.     if (m_callBase) {
  554.     CButton::OnRButtonDown(uFlags, cpPoint);
  555.     return;
  556.     }
  557.  
  558.     //    Don't continue if this context is destroyed.
  559.     if(!m_Context)    {
  560.         return;
  561.     }
  562.  
  563.     //    Start capturing all mouse events.
  564.     if(m_hWnd)    {
  565.     ::SetCapture(m_hWnd);
  566.     }
  567.  
  568.     MapWindowPoints(GetParent(), &cpPoint, 1);     
  569.  
  570.     XY Point;
  571.     m_pPaneCX->ResolvePoint(Point, cpPoint);
  572.  
  573.     if (m_Context->compositor) {
  574.         CL_Event event;
  575.         fe_EventStruct fe_event;
  576.         
  577.         fe_event.uFlags = uFlags;
  578.         fe_event.x = cpPoint.x;
  579.         fe_event.y = cpPoint.y;
  580.  
  581.         event.type = CL_EVENT_MOUSE_BUTTON_DOWN;
  582.         event.fe_event = (void *)&fe_event;
  583.         event.fe_event_size = sizeof(fe_EventStruct);
  584.         event.x = Point.x;
  585.         event.y = Point.y;
  586.         event.which = 3;
  587.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  588.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  589.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  590.     
  591.         CL_DispatchEvent(m_Context->compositor,
  592.                  &event);
  593.     }
  594.     else
  595.         CButton::OnRButtonDown(uFlags, cpPoint);
  596.  
  597.     return;
  598. }
  599. void CNetscapeButton::OnRButtonUp(UINT uFlags, CPoint cpPoint)    {
  600.  
  601.     if (m_callBase) {
  602.     CButton::OnRButtonUp(uFlags, cpPoint);
  603.     return;
  604.     }
  605.  
  606.     //    Don't continue if this context is destroyed.
  607.     if(!m_Context)    {
  608.         return;
  609.     }
  610.  
  611.     //    Start capturing all mouse events.
  612.     if(m_hWnd)    {
  613.         ::ReleaseCapture();
  614.     }
  615.  
  616.     MapWindowPoints(GetParent(), &cpPoint, 1);     
  617.  
  618.     XY Point;
  619.     m_pPaneCX->ResolvePoint(Point, cpPoint);
  620.  
  621.     if (m_Context->compositor) {
  622.         CL_Event event;
  623.         fe_EventStruct fe_event;
  624.         
  625.         fe_event.uFlags = uFlags;
  626.         fe_event.x = cpPoint.x;
  627.         fe_event.y = cpPoint.y;
  628.         
  629.         event.type = CL_EVENT_MOUSE_BUTTON_UP;
  630.         event.fe_event = (void *)&fe_event;
  631.         event.fe_event_size = sizeof(fe_EventStruct);
  632.         event.x = Point.x;
  633.         event.y = Point.y;
  634.         event.which = 3;
  635.         event.modifiers = (uFlags & MK_SHIFT ? EVENT_SHIFT_MASK : 0) 
  636.                 | (uFlags & MK_CONTROL ? EVENT_CONTROL_MASK : 0) 
  637.                 | (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0); 
  638.     
  639.         CL_DispatchEvent(m_Context->compositor,
  640.                  &event);
  641.     }
  642.     else 
  643.         CButton::OnRButtonUp(uFlags, cpPoint);
  644.  
  645.     return;
  646. }
  647.  
  648. void
  649. CNetscapeButton::OnButtonEvent(CL_EventType type, UINT nFlags, CPoint point) {
  650.     BOOL bReturnImmediately;
  651.     m_callBase = TRUE;
  652.  
  653.     switch (type) {
  654.     case CL_EVENT_MOUSE_BUTTON_DOWN:
  655.     SendMessage(WM_LBUTTONDOWN, nFlags, MAKELONG(point.x, point.y));
  656.     // Hack since Windows stubbornly refuses to accept current state.
  657.     SetState(FALSE);
  658.     SetState(TRUE);
  659.     m_bDepressed = TRUE;
  660.     break;
  661.     case CL_EVENT_MOUSE_BUTTON_UP:
  662.     // Only send click event if button is already down.
  663.         if (m_bDepressed) {
  664.             SendMessage(WM_LBUTTONUP, nFlags, MAKELONG(point.x, point.y));
  665. #ifdef DEBUG_aliu
  666.         TRACE0("ButtonEventClick ");
  667. #endif  // DEBUG_aliu
  668.         Click(nFlags, FALSE, bReturnImmediately);
  669.         m_bDepressed = FALSE;
  670.     }
  671.     break;
  672.     case CL_EVENT_MOUSE_BUTTON_MULTI_CLICK:
  673.     SendMessage(WM_LBUTTONDBLCLK, nFlags, MAKELONG(point.x, point.y));
  674.     break;
  675.     }
  676.     m_callBase = FALSE;
  677. }
  678.  
  679.  
  680.  
  681.