home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / fmselone.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  20.9 KB  |  597 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 "odctrl.h"
  22. #include "fmselone.h"
  23. #include "intl_csi.h"
  24.  
  25. //    This file is dedicated to form type select one elements
  26. //        otherwise known as combo boxes on windows and
  27. //        their implementation as requried by the XP layout
  28. //        library.
  29.  
  30. //    Construction simply clears all members.
  31. CFormSelectOne::CFormSelectOne()
  32. {
  33.     //    No widget representation yet.
  34.     m_pWidget = NULL;
  35. }
  36.  
  37. //    Destruction cleans out all members.
  38. CFormSelectOne::~CFormSelectOne()
  39. {
  40. }
  41.  
  42. //    How to set the LO form element.
  43. //    This may change during the lifetime of an instance, so use this
  44. //        to update all referencing values.
  45. void CFormSelectOne::SetElement(LO_FormElementStruct *pFormElement)
  46. {
  47.     //    Call the base.
  48.     CFormElement::SetElement(pFormElement);
  49.  
  50.     //    Have our widget update if present.
  51.     if(m_pWidget != NULL)    {
  52.         m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement());
  53.     }
  54. }
  55.  
  56. //    Set the owning context.
  57. //    Use this to determine what context we live in and how we should
  58. //        represent ourself (DC or window).
  59. void CFormSelectOne::SetContext(CAbstractCX *pCX)
  60. {
  61.     //    Call the base.
  62.     CFormElement::SetContext(pCX);
  63.  
  64.     //    Have our widget update if present.
  65.     if(m_pWidget != NULL)    {
  66.         m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement());
  67.     }
  68. }
  69.  
  70. //    Display the form element given the particular context we are in.
  71. //    Possibly only use a DC for representation, or have the
  72. //        window move.
  73. void CFormSelectOne::DisplayFormElement(LTRB& Rect)
  74. {
  75.     //    Display only has meaning if our context is a device context.
  76.     if(GetContext() && GetContext()->IsDCContext())    {
  77.         //    Further, need to detect how we're going to be drawing ourselves.
  78.         if(GetContext()->IsPureDCContext())    {
  79.             //    Only works from a DC, needs a GDI drawing representation.
  80.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  81.             LTRB r(Rect.left, Rect.top, Rect.right, Rect.bottom);
  82.  
  83.             //  Compensate for munging in FillSizeInfo.
  84.             r.Inflate(0, -1 * pDCCX->Pix2TwipsY(EDIT_SPACE));
  85.  
  86.             //  Do something simple.
  87.             pDCCX->Display3DBox(r, pDCCX->ResolveLightLineColor(), pDCCX->ResolveDarkLineColor(), pDCCX->Pix2TwipsY(2));
  88.             r.Inflate(0, -1 * pDCCX->Pix2TwipsY(2));
  89.  
  90.             HDC pDC = pDCCX->GetContextDC();
  91.             if(pDC) {
  92.                 //  Draw the down arrow on the right.
  93.                 r.right -= pDCCX->Pix2TwipsX(sysInfo.m_iScrollWidth);
  94.                 LTRB BButton(r.right, r.top - pDCCX->Pix2TwipsY(2), r.right + pDCCX->Pix2TwipsX(sysInfo.m_iScrollWidth), r.bottom + pDCCX->Pix2TwipsY(2));
  95.                 pDCCX->Display3DBox(BButton, RGB(0, 0, 0), pDCCX->ResolveDarkLineColor(), pDCCX->Pix2TwipsY(2));
  96.                 BButton.Inflate(-1 * pDCCX->Pix2TwipsX(2), -1 * pDCCX->Pix2TwipsY(2));
  97.  
  98.                 //  Arrow.
  99.                 POINT aPoints[3];
  100.                 aPoints[0].x = CASTINT(BButton.left + BButton.Width() / 4);
  101.                 aPoints[0].y = CASTINT(BButton.top + BButton.Height() / 3);
  102.                 aPoints[1].x = CASTINT(BButton.left + BButton.Width() / 2);
  103.                 aPoints[1].y = CASTINT(BButton.top + 2 * BButton.Height() / 3);
  104.                 aPoints[2].x = CASTINT(BButton.left + 3 * BButton.Width() / 4);
  105.                 aPoints[2].y = CASTINT(BButton.top + BButton.Height() / 3);
  106.                 TRY {
  107.                     HPEN cpBlack = ::CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
  108.                     HBRUSH cbBlack;
  109.                     HBRUSH pOldBrush = NULL;
  110.                     if(cbBlack = CreateSolidBrush(RGB(0, 0, 0)))  {
  111.                         pOldBrush = (HBRUSH)::SelectObject(pDC, cbBlack);
  112.                     }
  113.                     HPEN pOldPen = (HPEN)::SelectObject(pDC, cpBlack);
  114.  
  115.                     int iOldMode = ::SetPolyFillMode(pDC, ALTERNATE);
  116.                     ::Polygon(pDC, aPoints, 3);
  117.                     ::SetPolyFillMode(pDC, iOldMode);
  118.  
  119.                     if(pOldPen) {
  120.                         ::SelectObject(pDC, pOldPen);
  121.                     }
  122.                     if(pOldBrush)   {
  123.                         ::SelectObject(pDC, pOldBrush);
  124.                     }
  125.                     VERIFY(::DeleteObject(cpBlack));
  126.                     VERIFY(::DeleteObject(cbBlack));
  127.                 }
  128.                 CATCH(CException, e)    {
  129.                     //  Can't create pen.
  130.                 }
  131.                 END_CATCH
  132.  
  133.                 //  Output visible text.
  134.                 if(GetElementSelectData())  {
  135.                     CyaFont    *pMyFont;
  136.                     VOID2CX(GetContext(), CDCCX)->SelectNetscapeFont( pDC, GetTextAttr(), pMyFont );
  137.                     if (pMyFont) {
  138.                         SetWidgetFont(pDC, m_pWidget->m_hWnd);
  139.                         lo_FormElementOptionData *pOptionData = (lo_FormElementOptionData *)GetElementSelectData()->options;
  140.                         if(pOptionData) {
  141.                             char *pText = NULL;
  142.                             int32 lCounter = 0;
  143.  
  144.                             //  As a default for the text, use the first entry.
  145.                             //  Sometimes nothing is selected, and then we don't output anything....
  146.                             //  This will get retset by the loop below if something actually
  147.                             //      does exist.
  148.                             if(GetElementSelectData()->option_cnt > 0)  {
  149.                                 pText = (char *)pOptionData[0].text_value;
  150.                             }
  151.  
  152.                             while(lCounter < GetElementSelectData()->option_cnt)    {
  153.                                 if(pOptionData[lCounter].selected)  {
  154.                                     //  Show this one.
  155.                                     pText = (char *)pOptionData[lCounter].text_value;
  156.                                     break;
  157.                                 }
  158.                                 lCounter++;
  159.                             }
  160.  
  161.                             //  Do we have anything to show?
  162.                             if(pText)   {
  163.                                 //  Need to modify the coordinates a little bit.
  164.                                 r.left += pMyFont->GetMeanWidth();
  165.                                 int32 lCenterY = (r.Height() - pMyFont->GetHeight()) / 2;
  166.  
  167.                                 //  Transparent please.
  168.                                 int iOldBk = ::SetBkMode(pDC, TRANSPARENT);
  169.  
  170.                                 CIntlWin::ExtTextOut(
  171.                                     ((GetContext()->GetContext()) ?   
  172.                                         INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext()))
  173.                                      : 0) ,
  174.                                     pDC,
  175.                                     CASTINT(r.left),
  176.                                     CASTINT(r.top + lCenterY),
  177.                                     ETO_CLIPPED,
  178.                                     CRect(CASTINT(r.left), CASTINT(r.top), CASTINT(r.right), CASTINT(r.bottom)),
  179.                                     pText,
  180.                                     XP_STRLEN(pText),
  181.                                     NULL);
  182.  
  183.                                 //  Restore mode.
  184.                                 ::SetBkMode(pDC, iOldBk);
  185.                             }
  186.                         }
  187.                         VOID2CX(GetContext(), CDCCX)->ReleaseNetscapeFont( pDC, pMyFont );
  188.                     }
  189.                     else {
  190.                         m_pWidget->ReleaseDC(CDC::FromHandle(pDC));
  191.                         DestroyWidget();
  192.                     }
  193.                 }
  194.                 //  Done with DC.
  195.                 pDCCX->ReleaseContextDC(pDC);
  196.             }
  197.         }
  198.         else if(GetContext()->IsWindowContext())    {
  199.             MoveWindow(m_pWidget->m_hWnd, Rect.left, Rect.top + EDIT_SPACE);
  200.         }
  201.         else    {
  202.             //    Is undefined....
  203.             ASSERT(0);
  204.         }
  205.     }
  206.  
  207.     //    Call the base.
  208.     CFormElement::DisplayFormElement(Rect);
  209. }
  210.  
  211.  
  212. //    Destroy the widget (window) implemenation of the form.
  213. void CFormSelectOne::DestroyWidget()
  214. {
  215.     //    Get rid of the widget.
  216.     if(m_pWidget != NULL)    {
  217.         m_pWidget->DestroyWindow();
  218.         delete m_pWidget;
  219.         m_pWidget = NULL;
  220.     }
  221. }
  222.  
  223. //    Create the widget (window) implementation of the form
  224. //        but DO NOT DISPLAY.
  225. void CFormSelectOne::CreateWidget()
  226. {
  227.     if(GetContext() && GetElement())    {
  228.         if(GetContext()->IsWindowContext() && VOID2CX(GetContext(), CPaneCX)->GetPane())    {
  229.             //    For a window context, we use a widget representation.
  230.             //    Allocate.
  231.             ASSERT(m_pWidget == NULL);
  232.             m_pWidget = new CODMochaComboBox();
  233.             if(m_pWidget == NULL)    {
  234.                 return;
  235.             }
  236.  
  237.             //    Inform the widget of the context and form element (for mocha).
  238.             m_pWidget->SetContext(GetContext()->GetContext(), GetElement());
  239.  
  240.             //    Create the widget, initially hidden with a bad size
  241.             if(!m_pWidget->Create(WS_CHILD | WS_BORDER | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED,
  242.                     CRect(0, 0, 1, 1),
  243.                     CWnd::FromHandle(VOID2CX(GetContext(), CPaneCX)->GetPane()),
  244.                     GetDynamicControlID()))    {
  245.                 delete m_pWidget;
  246.                 m_pWidget = NULL;
  247.                 return;
  248.             }
  249.  
  250.             //    Prepare to measure text.
  251.             CDC *pDC = m_pWidget->GetDC();
  252.             HDC hdc = pDC->GetSafeHdc();
  253.             if(pDC)    {
  254.                 CyaFont    *pMyFont;
  255.                 
  256.                 VOID2CX(GetContext(), CDCCX)->SelectNetscapeFont( hdc, GetTextAttr(), pMyFont );
  257.                 int32 lWidgetWidth;
  258.                 int32 lWidgetHeight = 0;
  259.                 if (pMyFont) {
  260.                     SetWidgetFont(pDC->GetSafeHdc(), m_pWidget->m_hWnd);
  261.                     GetElement()->text_attr->FE_Data = pMyFont;
  262.                     SIZE csz;
  263.                     CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  264.                         INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  265.                         hdc, "hi", 2, &csz);
  266.                     lWidgetWidth = csz.cx;
  267.                     lWidgetHeight = 0;
  268.  
  269.                     //    Count the maximum width by looping through all entries.
  270.                     if(GetElementSelectData())    {
  271.                         lo_FormElementOptionData *pOptionData = (lo_FormElementOptionData *)GetElementSelectData()->options;
  272.                         if(pOptionData)    {
  273.                             char *pCurrent = NULL;
  274.                             int32 lCounter = 0;
  275.                             while(lCounter < GetElementSelectData()->option_cnt)    {
  276.                                 pCurrent = (char *)pOptionData[lCounter].text_value;
  277.                                 if(pCurrent && *pCurrent)    {
  278.                                     CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  279.                                         INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  280.                                         hdc, pCurrent, XP_STRLEN(pCurrent), &csz);
  281.                                     if(csz.cx > lWidgetWidth)    {
  282.                                         lWidgetWidth = csz.cx;
  283.                                     }
  284.                                 }
  285.  
  286.                                 //    Servicing next in line now.
  287.                                 lCounter++;
  288.                             }
  289.                         }
  290.                         lWidgetHeight = GetElementSelectData()->option_cnt;
  291.                     }
  292.                     lWidgetWidth += 2 * sysInfo.m_iScrollWidth;
  293.  
  294.                     //    Figure the maximum height we'll allow.
  295.                     //    NOTE:    This algorithm could use some work (legacy code).
  296.                     if(lWidgetHeight > 20)    {
  297.                         lWidgetHeight = 20;
  298.                     }
  299.                     lWidgetHeight += 2;
  300.                     lWidgetHeight *= csz.cy;
  301.  
  302.                     //    Done measuring text width.
  303.                     VOID2CX(GetContext(), CDCCX)->ReleaseNetscapeFont( hdc, pMyFont );
  304.                     m_pWidget->ReleaseDC(pDC);
  305.                 }
  306.                 else {
  307.                     m_pWidget->ReleaseDC(pDC);
  308.                     DestroyWidget();
  309.                     return;
  310.                 }
  311.  
  312.                 if (GetElement()->width > lWidgetWidth) {
  313.                     lWidgetWidth = GetElement()->width;
  314.                 }
  315.                 if (GetElement()->height > lWidgetHeight) {
  316.                     lWidgetHeight = GetElement()->height;
  317.                 }
  318.  
  319.                 //    Finally, size the widget to the width and height
  320.                 //        we have figured here.
  321.                 m_pWidget->MoveWindow(1, 1, CASTINT(lWidgetWidth), CASTINT(lWidgetHeight), FALSE);
  322.             }
  323.             else    {
  324.                 //    No DC, no widget.
  325.                 DestroyWidget();
  326.                 return;
  327.             }
  328.         }
  329.         else if(GetContext()->IsPureDCContext())    {
  330.             //    For a print/metafile context we use a drawn representation.
  331.             //    Figure out what size it will be and save the data.            
  332.         }
  333.     }
  334. }
  335.  
  336. //    Copy the current data out of the layout struct into the form
  337. //        widget, or mark that you should represent using the current data.
  338. void CFormSelectOne::UseCurrentData()
  339. {
  340.     //    Detect context type and copy appropriate data
  341.     //        according to representation.
  342.     if(GetContext())    {
  343.         if(GetContext()->IsWindowContext())    {
  344.             //    Only continue if we've got a widget to fill at all.
  345.             if(m_pWidget)    {
  346.                 //    Remove all entries.
  347.                 m_pWidget->ResetContent();
  348.  
  349.                 //    Loop through and copy the data into the widget.
  350.                 LO_LockLayout();
  351.                 lo_FormElementSelectData * selectData = GetElementSelectData();
  352.                 if(selectData)    {
  353.                     lo_FormElementOptionData *pOptionData = (lo_FormElementOptionData *)selectData->options;
  354.                     if(pOptionData)    {
  355.                         char *pCurrent = NULL;
  356.                         int32 lCounter = 0;
  357.                         while(lCounter < selectData->option_cnt)    {
  358.                             pCurrent = (char *)pOptionData[lCounter].text_value;
  359.  
  360.                             //    Add it to the list.
  361.                 m_pWidget->AddString(pCurrent ? pCurrent : "");
  362.  
  363.                             //    Is it selected?
  364.                             if(pOptionData[lCounter].selected)    {
  365.                                 m_pWidget->SetCurSel(CASTINT(lCounter));
  366.                             }
  367.  
  368.                             //    Servicing next in line now.
  369.                             lCounter++;
  370.                         }
  371.                     }
  372.                 }
  373.                 LO_UnlockLayout();
  374.             }
  375.         }
  376.         else if(GetContext()->IsPureDCContext())    {
  377.             //    For a print/metafile context we use a drawn representation.
  378.             //    So obviously we need to do something other than fill in a widget's data.
  379.         }
  380.     }
  381. }
  382.  
  383. //    Copy the default data out of the layout struct into the form
  384. //        widget, or mark that you should represent using the default data.
  385. void CFormSelectOne::UseDefaultData()
  386. {
  387.     //    Detect context type and copy appropriate data
  388.     //        according to representation.
  389.     if(GetContext())    {
  390.         if(GetContext()->IsWindowContext())    {
  391.             //    Only continue if we've got a widget to fill at all.
  392.             if(m_pWidget)    {
  393.                 //    Remove all entries.
  394.                 m_pWidget->ResetContent();
  395.  
  396.                 //    Loop through and copy the data into the widget.
  397.                 LO_LockLayout();
  398.                 lo_FormElementSelectData * selectData = GetElementSelectData();
  399.                 if(selectData)    {
  400.                     lo_FormElementOptionData *pOptionData = (lo_FormElementOptionData *)selectData->options;
  401.                     if(pOptionData)    {
  402.                         char *pCurrent = NULL;
  403.                         int32 lCounter = 0;
  404.                         while(lCounter < selectData->option_cnt)    {
  405.                             pCurrent = (char *)pOptionData[lCounter].text_value;
  406.  
  407.                             //    Add it to the list.
  408.                             m_pWidget->AddString(pCurrent ? pCurrent : "");
  409.  
  410.                             //    Restore default selection.
  411.                             pOptionData[lCounter].selected = pOptionData[lCounter].def_selected;
  412.  
  413.                             //    Is it selected?
  414.                             if(pOptionData[lCounter].selected)    {
  415.                                 m_pWidget->SetCurSel(CASTINT(lCounter));
  416.                             }
  417.  
  418.                             //    Servicing next in line now.
  419.                             lCounter++;
  420.                         }
  421.                     }
  422.                 }
  423.                 LO_UnlockLayout();
  424.             }
  425.         }
  426.         else if(GetContext()->IsPureDCContext())    {
  427.             //  Loop through and set the current data to reflect the default data.
  428.             if(GetElementSelectData())    {
  429.                 lo_FormElementOptionData *pOptionData = (lo_FormElementOptionData *)GetElementSelectData()->options;
  430.                 if(pOptionData)    {
  431.                     int32 lCounter = 0;
  432.                     while(lCounter < GetElementSelectData()->option_cnt)    {
  433.                         //    Restore default selection.
  434.                         pOptionData[lCounter].selected = pOptionData[lCounter].def_selected;
  435.  
  436.                         //    Servicing next in line now.
  437.                         lCounter++;
  438.                     }
  439.                 }
  440.             }
  441.         }
  442.     }
  443. }
  444.  
  445. //    Fill in the layout size information in the layout struct regarding
  446. //        the dimensions of the widget.
  447. void CFormSelectOne::FillSizeInfo()
  448. {
  449.     //    Detect context type and copy appropriate data
  450.     //        according to representation.
  451.     if(GetContext() && GetElement())    {
  452.         if(GetContext()->IsWindowContext())    {
  453.             //    Only continue if we've got a widget to fill at all.
  454.             if(m_pWidget)    {
  455.                 //    Determine our window position.
  456.                 CRect crRect;
  457.                 m_pWidget->GetWindowRect(crRect);
  458.  
  459.                 //    Munge it a little for layout.
  460.                 //    We'll have to know how to decode
  461.                 //        this information in the display
  462.                 //        routine.
  463.                 GetElement()->width = crRect.Width();
  464.                 GetElement()->height = crRect.Height() + 2 * EDIT_SPACE;
  465.                 GetElement()->border_vert_space = EDIT_SPACE;
  466.                 GetElement()->baseline = 3 * GetElement()->height / 4;
  467.             }
  468.             else    {
  469.                 //    Widget not present, give LAYOUT nothing.
  470.                 GetElement()->width = 0;
  471.                 GetElement()->height = 0;
  472.                 GetElement()->baseline = 0;
  473.             }
  474.         }
  475.         else if(GetContext()->IsPureDCContext())    {
  476.             //  Need to figure size of combo box.
  477.             int32 lWidth = 0;
  478.             int32 lHeight = 0;
  479.             int32 lBaseline = 0;
  480.  
  481.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  482.                 HDC pDC = pDCCX->GetAttribDC();
  483.                 if(pDC) {
  484.                     CyaFont    *pMyFont;
  485.                     
  486.                     pDCCX->SelectNetscapeFont( pDC, GetTextAttr(), pMyFont );
  487.                     if (pMyFont) {
  488.                         SetWidgetFont(pDC, m_pWidget->m_hWnd);
  489.                         SIZE csz;
  490.                         csz.cx = csz.cy = 0;
  491.  
  492.                         //  Default if no other text.
  493.                         CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  494.                             INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  495.                             pDC, "hi", 2, &csz);
  496.                         lWidth = csz.cx;
  497.  
  498.                         //  Get max width by looping through and measuring all entries.
  499.                         if(GetElementSelectData())  {
  500.                             lo_FormElementOptionData *pOptionData = (lo_FormElementOptionData *)GetElementSelectData()->options;
  501.                             if(pOptionData) {
  502.                                 char *pCurrent = NULL;
  503.                                 int32 lCounter = 0;
  504.                                 while(lCounter < GetElementSelectData()->option_cnt)    {
  505.                                     pCurrent = (char *)pOptionData[lCounter].text_value;
  506.                                     if(pCurrent && *pCurrent)    {
  507.                                         CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  508.                                                 INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  509.                                                 pDC, pCurrent, XP_STRLEN(pCurrent), &csz);
  510.  
  511.                                         if(csz.cx > lWidth) {
  512.                                             lWidth = csz.cx;
  513.                                         }
  514.                                     }
  515.  
  516.                                     lCounter++;
  517.                                 }
  518.                             }
  519.                         }
  520.  
  521.                         //  Add some size information.
  522.                         lWidth += 2 * pDCCX->Pix2TwipsX(sysInfo.m_iScrollWidth);
  523.                          lWidth += pMyFont->GetMeanWidth();
  524.  
  525.                         lHeight = csz.cy;
  526.                         lHeight += csz.cy / 2;
  527.                         lHeight += 2 * pDCCX->Pix2TwipsY(EDIT_SPACE);
  528.  
  529.                         // Check and see if we should use preset sizes
  530.                         if (GetElement()->width > lWidth) {
  531.                             lWidth = GetElement()->width;
  532.                         }
  533.                         if (GetElement()->height > lHeight) {
  534.                             lHeight = GetElement()->height;
  535.                         }
  536.  
  537.                         lBaseline = 3 * lHeight / 4;
  538.  
  539.                         //  Restore the font.
  540.                         pDCCX->ReleaseNetscapeFont( pDC, pMyFont );
  541.                     }
  542.                     else {
  543.                         m_pWidget->ReleaseDC(CDC::FromHandle(pDC));
  544.                         DestroyWidget();
  545.                     }
  546.                     //  Done with DC.
  547.                     pDCCX->ReleaseContextDC(pDC);
  548.                 }
  549.  
  550.             //  Let layout know what we know.
  551.             GetElement()->width = lWidth;
  552.             GetElement()->height = lHeight;
  553.             GetElement()->baseline = lBaseline;
  554.         }
  555.     }
  556. }
  557.  
  558. //    Copy the current data out of the form element back into the
  559. //        layout struct.
  560. void CFormSelectOne::UpdateCurrentData()
  561. {
  562.     //    Detect context type and copy appropriate data
  563.     //        according to representation.
  564.     if(GetContext())    {
  565.         if(GetContext()->IsWindowContext())    {
  566.             //    Only continue if we've got a widget and data space to fill at all.
  567.             if(m_pWidget && ::IsWindow(m_pWidget->GetSafeHwnd()) && GetElementSelectData())    {
  568.                 int32 lSelected = m_pWidget->GetCurSel();
  569.                 lo_FormElementOptionData *pOptionData = (lo_FormElementOptionData *)GetElementSelectData()->options;
  570.  
  571.                 if(pOptionData)    {
  572.                     //    Clear out all old selections.
  573.                     int32 lCounter = 0;
  574.                     while(lCounter < GetElementSelectData()->option_cnt)    {
  575.                         pOptionData[lCounter].selected = FALSE;
  576.                         lCounter++;
  577.                     }
  578.  
  579.                     //    Save this into the layout struct.
  580.                     if(lSelected != CB_ERR)    {
  581.                         pOptionData[lSelected].selected = TRUE;
  582.                     }
  583.                 }
  584.             }
  585.         }
  586.         else if(GetContext()->IsPureDCContext())    {
  587.             //    For a print/metafile context we use a drawn representation.
  588.             //    So obviously we need to do something other than fill in a widget's data.
  589.         }
  590.     }
  591. }
  592.  
  593. HWND CFormSelectOne::GetRaw()
  594. {
  595.     return(m_pWidget ? m_pWidget->m_hWnd : NULL);
  596. }
  597.