home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / fmabstra.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  27.0 KB  |  868 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.  
  19. #include "stdafx.h"
  20.  
  21. #include "fmabstra.h"
  22. #include "fmbutton.h"
  23. #include "fmfile.h"
  24. #include "fmradio.h"
  25. #include "fmselmul.h"
  26. #include "fmselone.h"
  27. #include "fmtext.h"
  28. #include "fmtxarea.h"
  29. #include "fmrdonly.h"
  30.  
  31. #include "windowsx.h"
  32.  
  33. //    Class to define common base functionality of all form elements
  34. //        in the front end in an object oriented manner.
  35.  
  36. //    Static control ID unique for each instance of this class.
  37. UINT CFormElement::m_uNextControlID = 0;
  38.  
  39. //    Function to create and/or retrieve a CFormElement from
  40. //        a layout form struct.
  41. CFormElement *CFormElement::GetFormElement(CAbstractCX *pCX, LO_FormElementStruct *pFormElement)
  42. {
  43.     CFormElement *pRetval = NULL;
  44.  
  45.     //    Ensure we have enough information with which to continue.
  46.     if(pCX == NULL)    {
  47.         return(pRetval);
  48.     }
  49.     else if(pFormElement == NULL)    {
  50.         return(pRetval);
  51.     }
  52.  
  53.     pRetval = GetFormElement(pCX, pFormElement->element_data);
  54.  
  55.     //    Look at the form element structure to see if one already exists.
  56.     if(pRetval == NULL && pFormElement->element_data != NULL)    {
  57.         //    We need to create a new form class.
  58.         TRY    {
  59.             switch(pFormElement->element_data->type)    {
  60.                 case FORM_TYPE_TEXT:
  61.                 case FORM_TYPE_PASSWORD:
  62.                     pRetval = (CFormElement *)new CFormText();
  63.                     break;
  64.                 case FORM_TYPE_CHECKBOX:
  65.                 case FORM_TYPE_RADIO:
  66.                     pRetval = (CFormElement *)new CFormRadio();
  67.                     break;
  68.                 case FORM_TYPE_BUTTON:
  69.                 case FORM_TYPE_RESET:
  70.                 case FORM_TYPE_SUBMIT:
  71.                     pRetval = (CFormElement *)new CFormButton();
  72.                     break;
  73.                 case FORM_TYPE_SELECT_ONE:
  74.                     pRetval = (CFormElement *)new CFormSelectOne();
  75.                     break;
  76.                 case FORM_TYPE_SELECT_MULT:
  77.                     pRetval = (CFormElement *)new CFormSelectMult();
  78.                     break;
  79.                 case FORM_TYPE_TEXTAREA:
  80.                     pRetval = (CFormElement *)new CFormTextarea();
  81.                     break;
  82.                 case FORM_TYPE_FILE:
  83.                     pRetval = (CFormElement *)new CFormFile();
  84.                     break;
  85.                 case FORM_TYPE_READONLY:
  86.                     pRetval = (CFormElement *)new CFormReadOnly();
  87.                     break;
  88.                 default:
  89.                     //    What exactly are we doing here?
  90.                     TRACE("Unimplemented form type (%d) requested.\n", (int)pFormElement->element_data->type);
  91.                     pRetval = NULL;
  92.                     break;
  93.             }
  94.         }
  95.         CATCH(CException, e)    {
  96.             pRetval = NULL;
  97.         }
  98.         END_CATCH
  99.     }
  100.  
  101.     //    Set up and/or update the relevant information in the class.
  102.     if(pRetval != NULL)    {
  103.         pRetval->SetContext(pCX);
  104.         pRetval->SetElement(pFormElement);
  105.     }
  106.  
  107.     return(pRetval);
  108. }
  109.  
  110. //    Only retrieve the form element class, do not create.
  111. CFormElement *CFormElement::GetFormElement(CAbstractCX *pCX, LO_FormElementData *pFormData)
  112. {
  113.     CFormElement *pRetval = NULL;
  114.  
  115.     //    Ensure we have enough information with which to continue.
  116.     if(pFormData == NULL) {
  117.         return(pRetval);
  118.     }
  119.     else if(pFormData->type == FORM_TYPE_KEYGEN)    {
  120.         //  Doesn't have minimal data.
  121.         return(pRetval);
  122.     }
  123.  
  124.     //    Look at the form element structure to see if one already exists.
  125.     if(pFormData->ele_minimal.FE_Data != NULL)    {
  126.         //    Already there, return it.
  127.         pRetval = (CFormElement *)pFormData->ele_minimal.FE_Data;
  128.     }
  129.  
  130.     //    Set up and/or update the relevant information in the class.
  131.     if(pRetval != NULL)    {
  132.         pRetval->SetContext(pCX);
  133.     }
  134.  
  135.     return(pRetval);
  136. }
  137.  
  138.  
  139. //    Construction simply clears all members.
  140. CFormElement::CFormElement()
  141. {
  142.     //    No LO form element.
  143.     SetElement(NULL);
  144.  
  145.     //    No context.
  146.     SetContext(NULL);
  147.  
  148.     //    By default, we have no widget allocated, and we are using default data.
  149.     m_bUseCurrentData = FALSE;
  150.     m_bWidgetPresent = FALSE;
  151. }
  152.  
  153. //    Destruction cleans out all members.
  154. CFormElement::~CFormElement()
  155. {
  156.     //    No LO form anymore.
  157.     //    FreeFormElement must be used to delete the class.
  158.     //    This assert knows that FreeFormElement calls SetElement(NULL).
  159.     ASSERT(GetElement() == NULL);
  160.  
  161.     //    No context anymore.
  162.     SetContext(NULL);
  163. }
  164.  
  165. //    How to set the LO form element.
  166. //    This may change during the lifetime of an instance, so use this to update all referencing values.
  167. void CFormElement::SetElement(LO_FormElementStruct *pFormElement)
  168. {
  169.     //    Simply copy.
  170.     m_pFormElement = pFormElement;
  171.     
  172.     //    Ensure its FE_Data points to us.
  173.     if(GetElementMinimalData())    {
  174.         GetElementMinimalData()->FE_Data = (void *)this;
  175.     }
  176. }
  177.  
  178. //    Return the owning LO element.
  179. LO_FormElementStruct *CFormElement::GetElement() const
  180. {
  181.     return(m_pFormElement);
  182. }
  183.  
  184. LO_FormElementData *CFormElement::GetElementData() const
  185. {
  186.     LO_FormElementData *pRetval = NULL;
  187.     if(GetElement())    {
  188.         pRetval = GetElement()->element_data;
  189.     }
  190.  
  191.     return(pRetval);
  192. }
  193.  
  194. //    Careful when using, may return incorrect structure if not correct
  195. //        form type.
  196. lo_FormElementTextData *CFormElement::GetElementTextData() const
  197. {
  198.     lo_FormElementTextData *pRetval = NULL;
  199.     if(GetElementData())    {
  200.         ASSERT(
  201.             GetElementData()->type == FORM_TYPE_TEXT ||
  202.             GetElementData()->type == FORM_TYPE_PASSWORD ||
  203.             GetElementData()->type == FORM_TYPE_FILE
  204.             );
  205.         pRetval = &(GetElementData()->ele_text);
  206.     }
  207.  
  208.     return(pRetval);
  209. }
  210.  
  211. //    Careful when using, may return incorrect structure if not correct
  212. //        form type.
  213. lo_FormElementTextareaData *CFormElement::GetElementTextareaData() const
  214. {
  215.     lo_FormElementTextareaData *pRetval = NULL;
  216.     if(GetElementData())    {
  217.         ASSERT(
  218.             GetElementData()->type == FORM_TYPE_TEXTAREA
  219.             );
  220.         pRetval = &(GetElementData()->ele_textarea);
  221.     }
  222.  
  223.     return(pRetval);
  224. }
  225.  
  226.  
  227. //    Always safe to use.
  228. lo_FormElementMinimalData *CFormElement::GetElementMinimalData() const
  229. {
  230.     lo_FormElementMinimalData *pRetval = NULL;
  231.     if(GetElementData())    {
  232.         pRetval = &(GetElementData()->ele_minimal);
  233.     }
  234.  
  235.     return(pRetval);
  236. }
  237.  
  238. //    Careful when using, may return incorrect structure if not correct
  239. //        form type.
  240. lo_FormElementToggleData *CFormElement::GetElementToggleData() const
  241. {
  242.     lo_FormElementToggleData *pRetval = NULL;
  243.     if(GetElementData())    {
  244.         ASSERT(
  245.             GetElementData()->type == FORM_TYPE_RADIO ||
  246.             GetElementData()->type == FORM_TYPE_CHECKBOX
  247.             );
  248.         pRetval = &(GetElementData()->ele_toggle);
  249.     }
  250.  
  251.     return(pRetval);
  252. }
  253.  
  254. //    Careful when using, may return incorrect structure if not correct
  255. //        form type.
  256. lo_FormElementSelectData *CFormElement::GetElementSelectData() const
  257. {
  258.     lo_FormElementSelectData *pRetval = NULL;
  259.     if(GetElementData())    {
  260.         ASSERT(
  261.             GetElementData()->type == FORM_TYPE_SELECT_ONE ||
  262.             GetElementData()->type == FORM_TYPE_SELECT_MULT
  263.             );
  264.         pRetval = &(GetElementData()->ele_select);
  265.     }
  266.  
  267.     return(pRetval);
  268. }
  269.  
  270. void *CFormElement::GetElementFEData() const
  271. {
  272.     void *pRetval = NULL;
  273.     if(GetElementMinimalData())    {
  274.         pRetval = GetElementMinimalData()->FE_Data;
  275.     }
  276.  
  277.     return(pRetval);
  278. }
  279.  
  280. //    Set the owning context.
  281. void CFormElement::SetContext(CAbstractCX *pCX)
  282. {
  283.     //    Simply copy.
  284.     m_pCX = pCX;
  285.  
  286.     //  If we're printing, we know (or assume), that
  287.     //      any form data has been set to the last context's current
  288.     //      state, so we don't want to just throw it all away by
  289.     //      calling UseDefaultData in GetFormElementInfo.
  290.     //  This does not apply to metafiles until they serialize the form data also.
  291.     if(GetContext() && GetContext()->IsPrintContext())  {
  292.         m_bUseCurrentData = TRUE;
  293.     }
  294. }
  295.  
  296. //    Return the owning context.
  297. CAbstractCX *CFormElement::GetContext() const
  298. {
  299.     return(m_pCX);
  300. }
  301.  
  302. //    Update the coordinates of display from the layout
  303. //        element and display if need be.
  304. void CFormElement::DisplayFormElement(LTRB& Rect)
  305. {
  306.     //    Class which need to handle this should know how in the derivation.
  307.     //    Call the base class after your implementation.
  308.     
  309.     //    In any event, make sure that the widget is visible.
  310.     //    Again, call the base class after your implementation.
  311.     HWND hRaw = GetRaw();
  312.     if(hRaw)    {
  313.         BOOL bVisible = ::IsWindowVisible(hRaw);
  314.         
  315.         /* If window is visible, but should be invisible, then make it disappear */
  316.         if (m_pFormElement->ele_attrmask & LO_ELE_INVISIBLE) {
  317.             if (bVisible) {
  318.                 ::ShowWindow(hRaw, SW_HIDE);
  319.             }
  320.         }
  321.         /* If window is invisible, but should be visible, then draw it */
  322.         else {
  323.             if (!bVisible) {
  324.                 ::ShowWindow(hRaw, SW_SHOWNA);
  325.             }
  326.         }
  327.     }
  328. }
  329.  
  330. //    This is called by LAYOUT when a form element should interpret a newline as
  331. //        hitting the submit button in a form.  This is done mainly on single line
  332. //        edit fields.
  333. void CFormElement::FormTextIsSubmit()
  334. {
  335.     HWND hRaw = GetRaw();
  336.     if(hRaw) {
  337.         CNetscapeEdit *pEdit = (CNetscapeEdit *)CEdit::FromHandlePermanent(hRaw);
  338.         pEdit->SetSubmit(TRUE);
  339.     }
  340. }
  341.  
  342. //    Free the form element.
  343. //    The form data is passed in, because layout has already
  344. //        disassociated it with the form struct.
  345. //    No need to override really....
  346. void CFormElement::FreeFormElement(LO_FormElementData *pFormData)
  347. {
  348.     //    Cause all widgets to be deallocated if not already.
  349.     DestroyWidget();
  350.  
  351.     //    NOTE:    m_pFormElement at this point can not be guaranteed to be valid.
  352.     //            Do not use it or members which access it.
  353.     SetElement(NULL);
  354.  
  355.     //    We're done.
  356.     //  Set the FE data to be null, since we're deleting it.
  357.     if(pFormData)    {
  358.         pFormData->ele_minimal.FE_Data = NULL;
  359.     }
  360.     delete this;
  361. }
  362.  
  363. //    Layout calls this to determine the size of a form element.
  364. void CFormElement::GetFormElementInfo()
  365. {
  366.     //    Avoid creating lots of widgets, see if we already have one.
  367.     if(IsWidgetPresent() == FALSE)    {
  368.         //    Not present, we have to create it on our own.
  369.         //    Be sure to check ShouldUseCurrentData to see if you should use the
  370.         //        current or default data from the Layout struct when
  371.         //        filling in the information (however, the actual size
  372.         //        calculation of the widget should be done with default
  373.         //        data always).
  374.         CreateWidget();
  375.  
  376.         if(ShouldUseCurrentData())    {
  377.             UseCurrentData();
  378.         }
  379.         else    {
  380.             UseDefaultData();
  381.  
  382.             //    First time creations should by default fill in the
  383.             //        current data with the default data, so that
  384.             //        MOCHA has some data to play with.
  385.             UpdateCurrentData();
  386.         }
  387.     }
  388.  
  389.     //    A widget should be present, so that we can check cached
  390.     //        size values in the future.
  391.     m_bWidgetPresent = TRUE;
  392.  
  393.     //    Get widget information into the layout structure.
  394.     FillSizeInfo();
  395. }
  396.  
  397. //    Retrieve the data from the form element, and possibly
  398. //        delete the form element widget.
  399. void CFormElement::GetFormElementValue(BOOL bTurnOff)
  400. {
  401.     //    Collect data from the widgets.
  402.     UpdateCurrentData();
  403.  
  404.     if(bTurnOff)    {
  405.         //    If we have to turn off, then mark that we should use current data in the future
  406.         //        when we have to recreate ourselves, and mark that our widget is gone.
  407.         m_bUseCurrentData = TRUE;
  408.         m_bWidgetPresent = FALSE;
  409.  
  410.         //    Get rid of the widgets.
  411.         DestroyWidget();
  412.     }
  413. }
  414.  
  415. //    Reset the form element to its default value.
  416. void CFormElement::ResetFormElement()
  417. {
  418.     //    Just use the default data in the LAYOUT struct.
  419.     UseDefaultData();
  420.  
  421.     //    Update (write over) any modified current (now old) data.
  422.     UpdateCurrentData();
  423. }
  424.  
  425. //    Toggle the form element's state.
  426. void CFormElement::SetFormElementToggle(BOOL bState)
  427. {
  428.     HWND hRaw = GetRaw();
  429.     if(hRaw) {
  430.         //  Set state if not already reflected.
  431.         if(Button_GetCheck(hRaw) != bState) {
  432.             Button_SetCheck(hRaw, bState);
  433.         }
  434.         UpdateCurrentData();
  435.     }
  436. }
  437.  
  438. //    Give focus to the form element.
  439. void CFormElement::FocusInputElement()
  440. {
  441.     HWND hRaw = GetRaw();
  442.     if(hRaw && GetContext() && GetElement()) {
  443.         FEU_MakeElementVisible(GetContext()->GetContext(), (LO_Any *)GetElement());
  444.         ::SetFocus(hRaw);
  445.     }
  446. }
  447.  
  448. //    Do not give focus to the form element.
  449. void CFormElement::BlurInputElement()
  450. {
  451.     HWND hRaw = GetRaw();
  452.     if(hRaw) {
  453.         // Only blur focus if we already have it and we can give it to our parent.
  454.         if(hRaw == ::GetFocus() && ::GetParent(hRaw)) {
  455.             ::SetFocus(::GetParent(hRaw));
  456.         }
  457.     }
  458. }
  459.  
  460. //    Select the form element's data.
  461. void CFormElement::SelectInputElement()
  462. {
  463.     HWND hRaw = GetRaw();
  464.     if(hRaw) {
  465.         Edit_SetSel(hRaw, 0, -1);
  466.     }
  467. }
  468.  
  469. //    Change the value of the form element.
  470. void CFormElement::ChangeInputElement()
  471. {
  472.     //    All we really need to do is update ourselves so that we reflect the
  473.     //        current data.
  474.     UseCurrentData();
  475.  
  476.     if(GetElementMinimalData())    {
  477.         if(GetElementMinimalData()->type == FORM_TYPE_RADIO)    {
  478.             if(GetContext() && GetContext()->GetContext())    {
  479.                 lo_FormElementToggleData * tog_data;
  480.                 tog_data = (lo_FormElementToggleData *) GetElement()->element_data;
  481.                 if(tog_data->toggled) {
  482.                     // If we are supposed to be on, turn off everyone else
  483.                     LO_FormRadioSet(GetContext()->GetDocumentContext(), GetElement());  
  484.                 }
  485.             }
  486.         }
  487.     }
  488. }
  489.  
  490. //  Enable the form element (Editable to the user).
  491. void CFormElement::EnableInputElement()
  492. {
  493.     HWND hRaw = GetRaw();
  494.     if(hRaw) {
  495.         ::EnableWindow(hRaw, TRUE);
  496.     }
  497. }
  498.  
  499. //  Disable the form element (Read only to the user).
  500. void CFormElement::DisableInputElement()
  501. {
  502.     HWND hRaw = GetRaw();
  503.     if(hRaw) {
  504.         ::EnableWindow(hRaw, FALSE);
  505.     }
  506. }
  507.  
  508. //    Return a unique control ID each time called.
  509. UINT CFormElement::GetDynamicControlID()
  510. {
  511.     //    Handle wrap.
  512.     if(m_uNextControlID == 0)    {
  513.         m_uNextControlID = DYNAMIC_RESOURCE;
  514.     }
  515.  
  516.     return(m_uNextControlID++);
  517. }
  518.  
  519. #ifdef XP_WIN16
  520. //    Call this to get the segment for edit fields under 16 bit windows.
  521. //    This is so they are taken out of the precious DGROUP.
  522. HINSTANCE CFormElement::GetSegment()
  523. {
  524.     HINSTANCE hRetval = NULL;
  525.  
  526.     //    Only if we have a context, and it has widgets.
  527.     if(GetContext() && GetContext()->IsWindowContext())    {
  528.         CPaneCX *pPaneCX = VOID2CX(GetContext(), CPaneCX);
  529.         hRetval = pPaneCX->GetSegment();
  530.     }
  531.  
  532.     return(hRetval);
  533. }
  534. #endif
  535.  
  536. extern "C" void FE_RaiseWindow(MWContext *pContext)    {
  537.     //  Make sure this is possible.
  538.     if(pContext && ABSTRACTCX(pContext) && !ABSTRACTCX(pContext)->IsDestroyed()
  539.         && ABSTRACTCX(pContext)->IsFrameContext() && PANECX(pContext)->GetPane()
  540.         && WINCX(pContext)->GetFrame() && WINCX(pContext)->GetFrame()->GetFrameWnd()) {
  541.         CWinCX *pWinCX = WINCX(pContext);
  542.         CFrameWnd *pFrameWnd = pWinCX->GetFrame()->GetFrameWnd();
  543.  
  544.         //  Bring the frame to the top first.
  545.         if(pFrameWnd->IsIconic())    {
  546.             pFrameWnd->ShowWindow(SW_RESTORE);
  547.         }
  548.         ::SetWindowPos(pFrameWnd->GetSafeHwnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  549. #ifdef XP_WIN32
  550.         pFrameWnd->SetForegroundWindow();
  551. #endif
  552.  
  553.         //  Now, set focus to the view being raised,
  554.         //      possibly a frame cell.
  555.         pWinCX->
  556.             GetFrame()->
  557.             GetFrameWnd()->
  558.             SetActiveView(pWinCX->GetView(), TRUE);
  559.     }
  560. }
  561.  
  562. extern "C" void FE_LowerWindow(MWContext *pContext)    {
  563.     //  Make sure this is possible.
  564.     if(pContext && ABSTRACTCX(pContext) && !ABSTRACTCX(pContext)->IsDestroyed()
  565.         && ABSTRACTCX(pContext)->IsFrameContext() && PANECX(pContext)->GetPane()
  566.         && WINCX(pContext)->GetFrame() && WINCX(pContext)->GetFrame()->GetFrameWnd()) {
  567.         CWinCX *pWinCX = WINCX(pContext);
  568.         CFrameWnd *pFrameWnd = pWinCX->GetFrame()->GetFrameWnd();
  569.  
  570.     MWContext *pTravContext = NULL;
  571.     CWinCX *pTravWinCX = NULL;
  572.     CFrameWnd *pTravFrameWnd = NULL;
  573.     HWND pTopBottommostHwnd = NULL;
  574.     HWND pTravHwnd;
  575.     XP_Bool LowerWindow;
  576.  
  577.     // We don't have a good way to do this.  Look through the global
  578.     // context list for always lowered windows.
  579.     XP_List *pTraverse = XP_GetGlobalContextList();
  580.     while (pTravContext = (MWContext *)XP_ListNextObject(pTraverse)) {
  581.         if(pTravContext && ABSTRACTCX(pTravContext) && 
  582.             !ABSTRACTCX(pTravContext)->IsDestroyed() &&
  583.             ABSTRACTCX(pTravContext)->IsFrameContext() &&
  584.             WINCX(pTravContext)->GetFrame() && 
  585.             WINCX(pTravContext)->GetFrame()->GetFrameWnd())    {
  586.  
  587.         // Find each always lowered window.
  588.         pTravWinCX = WINCX(pTravContext);
  589.         pTravFrameWnd = pTravWinCX->GetFrame()->GetFrameWnd();
  590.         if (((CGenericFrame*)pTravFrameWnd)->IsBottommost()) {
  591.             if (!pTopBottommostHwnd)
  592.             pTopBottommostHwnd = pTravFrameWnd->GetSafeHwnd();
  593.             else {
  594.             //Ugly!  See if any of the other bottommost windows are above
  595.             //this one.  If so, use them.
  596.             LowerWindow = FALSE;
  597.             pTravHwnd = pTopBottommostHwnd;
  598.             while (pTravHwnd = GetNextWindow(pTravHwnd, GW_HWNDPREV)) {
  599.                 if (pTravHwnd == pTravFrameWnd->GetSafeHwnd())
  600.                 LowerWindow = TRUE;
  601.             }
  602.             if (LowerWindow)
  603.                 pTopBottommostHwnd = pTravFrameWnd->GetSafeHwnd();
  604.             }
  605.         }
  606.         }
  607.     }
  608.     
  609.     if (pTopBottommostHwnd)
  610.         //  Place the frame above the top bottommost window..
  611.         ::SetWindowPos(pFrameWnd->GetSafeHwnd(), GetNextWindow(pTopBottommostHwnd, GW_HWNDPREV), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  612.     else
  613.         //  Push the frame to the bottom.
  614.         ::SetWindowPos(pFrameWnd->GetSafeHwnd(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  615.  
  616.         //  Remove focus.
  617.         ::SetFocus(NULL);
  618.     }
  619. }
  620.  
  621. //
  622. // Mocha-betties demand attention --- give them the focus
  623. //
  624. extern "C" void FE_FocusInputElement(MWContext * pContext, LO_Element * pElement)
  625. {
  626.     //  They may intend the actual context.
  627.     if(pElement == NULL)    {
  628.         TRACE("Focusing context\n");
  629.         FE_RaiseWindow(pContext);
  630.         return;
  631.     }
  632.     else if(pElement->type == LO_FORM_ELE)    {
  633.         CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  634.         if(pFormClass != NULL)    {
  635.             pFormClass->FocusInputElement();
  636.         }
  637.     }
  638. }
  639.  
  640. //
  641. // Mocha-betties are sulking and don't want anyone looking at them --- just give
  642. //    focus to our parent (if we have the focus to begin with)
  643. //
  644. extern "C" void FE_BlurInputElement(MWContext * pContext, LO_Element * pElement)
  645. {
  646.     //  They may intend the actual context.
  647.     if(pElement == NULL)    {
  648.         TRACE("Blurring context\n");
  649.         FE_LowerWindow(pContext);
  650.         return;
  651.     }
  652.     else if(pElement->type == LO_FORM_ELE)    {
  653.         CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  654.         if(pFormClass != NULL)    {
  655.             pFormClass->BlurInputElement();
  656.         }
  657.     }
  658. }
  659.  
  660. //
  661. // Mocha-betties want to be the ones that are selected
  662. //
  663. extern "C" void FE_SelectInputElement(MWContext * pContext, LO_Element * pElement)
  664. {
  665.     //    Get our front end form element, and have it do its thang.
  666.     ASSERT(pElement && pElement->type == LO_FORM_ELE);
  667.     if(pElement && pElement->type == LO_FORM_ELE)    {
  668.         CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  669.         if(pFormClass != NULL)    {
  670.             pFormClass->SelectInputElement();
  671.         }
  672.     }
  673. }
  674.  
  675. // Mocha-betties have decided to change the value of a form element
  676. //   deal with it
  677. extern "C" void FE_ChangeInputElement(MWContext * pContext, LO_Element * pElement)
  678. {
  679.     //    Get our front end form element, and have it do its thang.
  680.     ASSERT(pElement && pElement->type == LO_FORM_ELE);
  681.     if(pElement && pElement->type == LO_FORM_ELE)    {
  682.         CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  683.         if(pFormClass != NULL)    {
  684.             pFormClass->ChangeInputElement();
  685.         }
  686.     }
  687. }
  688.  
  689. // FE_ClickAnyElement() is based on FE_ClickInputElement(), and should replace the latter.
  690. // If haveXY != 0, the xx, yy will be used for click. otherwise click the center of element.
  691. //
  692. // xx, yy are element coordinates, This function take care of :
  693. // lo_any.x_offset, pWinCX->GetOriginX(), ClientToScreen(), and  ScreenToClient()
  694. extern "C" int FE_ClickAnyElement(MWContext * pContext,  LO_Element * pElement, int haveXY, int32 xx, int32 yy )
  695. {
  696.     if(pElement && ABSTRACTCX(pContext) && ABSTRACTCX(pContext)->IsWindowContext())    {
  697.         HWND hRaw = NULL;
  698.         CPaneCX *pPaneCX = PANECX(pContext);
  699.         //    Get our front end form element, and have it do its thang.
  700.         //  This differs only in that they are child windows and therefore, the destination window
  701.         //      for the events differ.
  702.         if(pElement->type == LO_FORM_ELE)    {
  703.             CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  704.             if(pFormClass != NULL)    {
  705.                 hRaw = pFormClass->GetRaw();
  706.             }
  707.         }
  708.         else    {
  709.             //  The destination for the click is the view.
  710.             hRaw = pPaneCX->GetPane();
  711.         }
  712.  
  713.         if(hRaw) {
  714.  
  715.             if( ! haveXY ) {
  716.                 //  Emulate a mouse click in the center of the element.
  717.                 xx  = pElement->lo_any.x + pElement->lo_any.width / 2;
  718.                 yy  = pElement->lo_any.y + pElement->lo_any.height / 2;
  719.             }
  720.             
  721.             //  Mouse coordinates are relative to the widget, not absolute to the screen.
  722.             //  We may have some problems if the destination is not viewable.
  723.             
  724.             //  Figure the coordinates of the element according to context (view).
  725.             xx += pElement->lo_any.x_offset - pPaneCX->GetOriginX();
  726.             yy += pElement->lo_any.y_offset - pPaneCX->GetOriginY();
  727.  
  728.             //  Adjust for coords to the widget.
  729.             CPoint pCoords(CASTINT(xx), CASTINT(yy));
  730.             ::ClientToScreen(pPaneCX->GetPane(), &pCoords);
  731.             ::ScreenToClient(hRaw, &pCoords);
  732.             //  Fire.
  733.             ::SendMessage(hRaw, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pCoords.x, pCoords.y));
  734.             ::SendMessage(hRaw, WM_LBUTTONUP, 0, MAKELPARAM(pCoords.x, pCoords.y));
  735.             return( 1 );
  736.         }
  737.     }    // if(pElement && ABSTRACTCX(pCon
  738.     return( 0 );
  739. }    // FE_ClickAnyElement()
  740.  
  741. extern "C" void FE_ClickInputElement(MWContext * pContext, LO_Element * pElement)
  742. {
  743.     if(pElement && ABSTRACTCX(pContext) && ABSTRACTCX(pContext)->IsWindowContext())    {
  744.         HWND hRaw = NULL;
  745.         CPaneCX *pPaneCX = PANECX(pContext);
  746.         //    Get our front end form element, and have it do its thang.
  747.         //  This differs only in that they are child windows and therefore, the destination window
  748.         //      for the events differ.
  749.         if(pElement->type == LO_FORM_ELE)    {
  750.             CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  751.             if(pFormClass != NULL)    {
  752.                 hRaw = pFormClass->GetRaw();
  753.             }
  754.         }
  755.         else    {
  756.             //  The destination for the click is the view.
  757.             hRaw = pPaneCX->GetPane();
  758.         }
  759.  
  760.         if(hRaw) {
  761.             //  Emulate a mouse click in the center of the element.
  762.             //  Mouse coordinates are relative to the widget, not absolute to the screen.
  763.             //  We may have some problems if the destination is not viewable.
  764.             
  765.             //  Figure the coordinates of the element according to context (view).
  766.             LTRB Rect;
  767.             Rect.left = pElement->lo_any.x + pElement->lo_any.x_offset - pPaneCX->GetOriginX();
  768.             Rect.top = pElement->lo_any.y + pElement->lo_any.y_offset - pPaneCX->GetOriginY();
  769.             Rect.right = Rect.left + pElement->lo_any.width;
  770.             Rect.bottom = Rect.top + pElement->lo_any.height;
  771.             //  Adjust for coords to the widget.
  772.             CPoint pCoords(CASTINT(Rect.left), CASTINT(Rect.top));
  773.             ::ClientToScreen(pPaneCX->GetPane(), &pCoords);
  774.             ::ScreenToClient(hRaw, &pCoords);
  775.             //  Center target.
  776.             pCoords.x += CASTINT(Rect.Width() / 2);
  777.             pCoords.y += CASTINT(Rect.Height() / 2);
  778.             //  Fire.
  779.             ::SendMessage(hRaw, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pCoords.x, pCoords.y));
  780.             ::SendMessage(hRaw, WM_LBUTTONUP, 0, MAKELPARAM(pCoords.x, pCoords.y));
  781.         }
  782.     }
  783. }
  784.  
  785. extern "C" void FE_EnableInputElement(MWContext *pContext, LO_Element *pElement)
  786. {
  787.     //    Get our front end form element, and have it do its thang.
  788.     ASSERT(pElement && pElement->type == LO_FORM_ELE);
  789.     if(pElement && pElement->type == LO_FORM_ELE)    {
  790.         CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  791.         if(pFormClass != NULL)    {
  792.             pFormClass->EnableInputElement();
  793.         }
  794.     }
  795. }
  796.  
  797. extern "C" void FE_DisableInputElement(MWContext *pContext, LO_Element *pElement)
  798. {
  799.     //    Get our front end form element, and have it do its thang.
  800.     ASSERT(pElement && pElement->type == LO_FORM_ELE);
  801.     if(pElement && pElement->type == LO_FORM_ELE)    {
  802.         CFormElement *pFormClass = CFormElement::GetFormElement(ABSTRACTCX(pContext), &(pElement->lo_form));
  803.         if(pFormClass != NULL)    {
  804.             pFormClass->DisableInputElement();
  805.         }
  806.     }
  807. }
  808.  
  809. void CFormElement::MoveWindow(HWND hWnd, int32 lX, int32 lY)
  810. {
  811.     if(hWnd && ::GetParent(hWnd))    {
  812.         //    Is a window, needs a widget/window representation.
  813.         //    All we need to do is to make sure that the widget is
  814.         //        at the correct location as requested by layout.
  815.         //    Figure the XY layout wants.
  816.  
  817.         //    Determine widget offset into the client window.
  818.         RECT crWidget;
  819.         ::GetWindowRect(hWnd, &crWidget);
  820.         
  821.         POINT ptLT;
  822.         ptLT.x = crWidget.left;
  823.         ptLT.y = crWidget.top;
  824.         ::ScreenToClient(::GetParent(hWnd), &ptLT);
  825.  
  826.         //  Only move the widget if not already there.
  827.         //  No need to cause the widget to redraw.
  828.         if(ptLT.x != lX || ptLT.y != lY) {
  829.             ::MoveWindow(hWnd, CASTINT(lX), CASTINT(lY),
  830.                 crWidget.right - crWidget.left,
  831.                 crWidget.bottom - crWidget.top,
  832.                 TRUE);
  833.         }
  834.     }
  835. }
  836.  
  837.  
  838. void CFormElement::SetWidgetFont(HDC hdc, HWND hWidget)
  839. {
  840.     // this is just a trick to get the HFONT from the dc.
  841.     if (hWidget) {
  842.         HFONT hFont = (HFONT)::SelectObject(hdc, 
  843.                         (HFONT)    GetStockObject(SYSTEM_FONT));
  844.         // now select the correct font into the DC.        
  845.         ::SelectObject(hdc, hFont);
  846.         
  847. #ifdef XP_WIN32
  848.         //  Win95 systems need to keep their previous margins, or things get changed (margins)
  849.         //      upon switching fonts.
  850.         //  MS Knowledge Base article ID: Q138419
  851.         DWORD dwMargins = 0;
  852.         if(sysInfo.IsWin4_32()) {
  853.             dwMargins = ::SendMessage(hWidget, EM_GETMARGINS, 0L, 0L);
  854.         }
  855. #endif
  856.         ::SendMessage(hWidget, WM_SETFONT, (WPARAM)hFont, TRUE);
  857. #ifdef XP_WIN32
  858.         if(sysInfo.IsWin4_32()) {
  859.             ::SendMessage(
  860.                 hWidget,
  861.                 EM_SETMARGINS,
  862.                 EC_LEFTMARGIN | EC_RIGHTMARGIN,
  863.                 MAKELPARAM(LOWORD(dwMargins), HIWORD(dwMargins)));
  864.         }
  865. #endif
  866.     }
  867. }
  868.