home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / fmtext.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  17.4 KB  |  520 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 "fmtext.h"
  22. #include "odctrl.h"
  23. #include "intl_csi.h"
  24. //    This file is dedicated to form type select one elements
  25. //        otherwise known as list boxes on windows and
  26. //        their implementation as requried by the XP layout
  27. //        library.
  28.  
  29. //    Construction simply clears all members.
  30. CFormText::CFormText()
  31. {
  32.     //    No widget yet.
  33.     m_pWidget = NULL;
  34. }
  35.  
  36. //    Destruction cleans out all members.
  37. CFormText::~CFormText()
  38. {
  39. }
  40.  
  41. //    How to set the LO form element.
  42. //    This may change during the lifetime of an instance, so use this
  43. //        to update all referencing values.
  44. void CFormText::SetElement(LO_FormElementStruct *pFormElement)
  45. {
  46.     //    Call the base.
  47.     CFormElement::SetElement(pFormElement);
  48.  
  49.     //    Let the widget know the element.
  50.     if(m_pWidget)    {
  51.         m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement());
  52.     }
  53. }
  54.  
  55. //    Set the owning context.
  56. //    Use this to determine what context we live in and how we should
  57. //        represent ourself (DC or window).
  58. void CFormText::SetContext(CAbstractCX *pCX)
  59. {
  60.     //    Call the base.
  61.     CFormElement::SetContext(pCX);
  62.  
  63.     //    Let the widget know the context.
  64.     if(m_pWidget)    {
  65.         m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement());
  66.     }
  67. }
  68.  
  69. //    Display the form element given the particular context we are in.
  70. //    Possibly only use a DC for representation, or have the
  71. //        window move.
  72. void CFormText::DisplayFormElement(LTRB& Rect)
  73. {
  74.     //    Display only has meaning if our context is a device context.
  75.     if(GetContext() && GetContext()->IsDCContext())    {
  76.         //    Further, need to detect how we're going to be drawing ourselves.
  77.         if(GetContext()->IsPureDCContext())    {
  78.             //    Only works from a DC, needs a GDI drawing representation.
  79.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  80.             LTRB r(Rect.left, Rect.top, Rect.right, Rect.bottom);
  81.  
  82.             //  Adjust for what we bastardized earlier in fill size info.
  83.             r.Inflate(0, -1 * pDCCX->Pix2TwipsY(EDIT_SPACE) / 2);
  84.  
  85.             //  Do something simple.
  86.             pDCCX->Display3DBox(r, pDCCX->ResolveLightLineColor(), pDCCX->ResolveDarkLineColor(), pDCCX->Pix2TwipsY(2));
  87.  
  88.             //  Final adjustment for below...
  89.             r.Inflate(-1 * pDCCX->Twips2PixX(2), -1 * pDCCX->Twips2PixY(2));
  90.  
  91.             //  Is there text to output.
  92.             if(GetElementTextData() && GetElementTextData()->current_text)  {
  93.                 char *pText = (char *)GetElementTextData()->current_text;
  94.  
  95.                 //  Obtain the font for the text to be drawn.
  96.                     //  Get the DC.
  97.                     HDC pDC = pDCCX->GetContextDC();
  98.                     if(pDC) {
  99.                         CyaFont    *pMyFont;
  100.                         
  101.                         pDCCX->SelectNetscapeFont( pDC, GetTextAttr(), pMyFont );
  102.                         if (pMyFont) {
  103.                             SetWidgetFont(pDC, m_pWidget->m_hWnd);
  104.                             int32 lTextLength = XP_STRLEN(pText);
  105.                             char *pTextBuf = new char[lTextLength + 1];
  106.                             if(pTextBuf)    {
  107.                                 //  Clear it.
  108.                                 memset(pTextBuf, 0, CASTSIZE_T(lTextLength + 1));
  109.  
  110.                                 //  Decide if a password.
  111.                                 if(GetElementMinimalData()->type == FORM_TYPE_PASSWORD)  {
  112.                                     memset(pTextBuf, '*', CASTSIZE_T(lTextLength));
  113.                                 }
  114.                                 else    {
  115.                                     strcpy(pTextBuf, pText);
  116.                                 }
  117.  
  118.                                 //  Text mode must go transparent (some printers block out drawing around text).
  119.                                 int iOldBk = ::SetBkMode(pDC, TRANSPARENT);
  120.  
  121.                                 //  Decide the destination for the text rect.
  122.                                 //  We need to move the text to the right and left some, and on the Y.
  123.                                 RECT crDest;
  124.                                 ::SetRect(&crDest, CASTINT(r.left), CASTINT(r.top), CASTINT(r.right), CASTINT(r.bottom));
  125.                                 crDest.left  += pMyFont->GetMeanWidth();
  126.                                 crDest.top += ((crDest.bottom - crDest.top) - (pMyFont->GetHeight())) / 2;
  127.                                 //  Finally draw the text.
  128.                                 //  The clipping rect is not the destination rect.
  129.                                 CIntlWin::ExtTextOut(
  130.                                     (GetContext()->GetContext() ?
  131.                                          INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())) :0),
  132.                                     pDC, crDest.left,
  133.                                     crDest.top, ETO_CLIPPED, CRect(CASTINT(r.left),
  134.                                     CASTINT(r.top), CASTINT(r.right),
  135.                                     CASTINT(r.bottom)), pTextBuf, CASTINT(lTextLength), NULL);
  136.  
  137.                                 //  Restore Bk mode.
  138.                                 ::SetBkMode(pDC, iOldBk);
  139.  
  140.                                 //  Get rid of the buffer.
  141.                                 delete[] pTextBuf;
  142. //                            }
  143.  
  144.                             pDCCX->ReleaseNetscapeFont( pDC, pMyFont );
  145.                         }
  146.                         else {
  147.                             m_pWidget->ReleaseDC(CDC::FromHandle(pDC));
  148.                             DestroyWidget();
  149.                         }
  150.                         pDCCX->ReleaseContextDC(pDC);
  151.                     }
  152.                 }
  153.             }
  154.         }
  155.         else if(GetContext()->IsWindowContext())    {
  156.             MoveWindow(m_pWidget->m_hWnd, Rect.left, Rect.top + EDIT_SPACE / 2);
  157.         }
  158.         else    {
  159.             //    Is undefined....
  160.             ASSERT(0);
  161.         }
  162.     }
  163.  
  164.     //    Call the base.
  165.     CFormElement::DisplayFormElement(Rect);
  166. }
  167.  
  168. //    Destroy the widget (window) implemenation of the form.
  169. void CFormText::DestroyWidget()
  170. {
  171.     //    Get rid of the widget if around.
  172.     if(m_pWidget)    {
  173.         m_pWidget->DestroyWindow();
  174.         delete m_pWidget;
  175.         m_pWidget = NULL;
  176.     }
  177. }
  178.  
  179. //    Create the widget (window) implementation of the form
  180. //        but DO NOT DISPLAY.
  181. void CFormText::CreateWidget()
  182. {
  183.     if(GetContext() && GetElement())    {
  184.         if(GetContext()->IsWindowContext() && VOID2CX(GetContext(), CPaneCX)->GetPane())    {
  185.             //    Need a widget representation.
  186.             ASSERT(m_pWidget == NULL);
  187.             m_pWidget = new CODNetscapeEdit;
  188.     
  189.             if(m_pWidget == NULL)    {
  190.                 return;
  191.             }
  192.  
  193.             //    Inform widget of context and element.
  194.             m_pWidget->SetContext(GetContext()->GetContext(), GetElement());
  195.  
  196. #ifdef XP_WIN16
  197.             //    On 16 bits, we need to set the segment of the widget before creation.
  198.             HINSTANCE hSegment = GetSegment();
  199.             if(hSegment)    {
  200.                 m_pWidget->SetInstance(hSegment);
  201.             }
  202.             else    {
  203.                 delete m_pWidget;
  204.                 m_pWidget = NULL;
  205.                 return;
  206.             }
  207. #endif
  208.  
  209.             //    The style of the widget to be created.
  210.             DWORD dwStyle = WS_CHILD | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP;
  211.             if(GetElementMinimalData())    {
  212.                 switch(GetElementMinimalData()->type)    {
  213.                     case FORM_TYPE_PASSWORD:
  214.                         dwStyle |= ES_PASSWORD;
  215.                         break;
  216.                     default:
  217.                         break;
  218.                 }
  219.             }
  220.             else    {
  221.                 //    Must set styles.
  222.                 delete m_pWidget;
  223.                 m_pWidget = NULL;
  224.                 return;
  225.             }
  226.  
  227.             //    Create the widget, hidden, and with a bad size.
  228.             BOOL bCreate =
  229. #ifdef XP_WIN32
  230.                 m_pWidget->CreateEx(WS_EX_CLIENTEDGE, 
  231.                      _T("EDIT"),
  232.                      NULL,
  233.                      dwStyle, 
  234.                      1, 1, 0, 0,
  235.                      VOID2CX(GetContext(), CPaneCX)->GetPane(), 
  236.                      (HMENU)GetDynamicControlID(),
  237.                      NULL);    
  238.  
  239. #else
  240.                 m_pWidget->Create(dwStyle, CRect(1, 1, 0, 0), 
  241.                     CWnd::FromHandle(VOID2CX(GetContext(), CPaneCX)->GetPane()), 
  242.                     GetDynamicControlID());
  243. #endif
  244.  
  245.             if(!bCreate)    {
  246.                 delete m_pWidget;
  247.                 m_pWidget = NULL;
  248.                 return;
  249.             }
  250.  
  251.             //    Next, need to size the widget.
  252.             //    Obtain a font.
  253.             //    Measure some text.
  254.             CDC *pDC = m_pWidget->GetDC();
  255.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  256.             if(pDC)    {
  257.                 //    Default length is 20
  258.                 int32 lLength = 20;
  259.                 CyaFont    *pMyFont;
  260.                     
  261.                 pDCCX->SelectNetscapeFont( pDC->GetSafeHdc(), GetTextAttr(), pMyFont );
  262.                 if (pMyFont) {
  263.                     SetWidgetFont(pDC->GetSafeHdc(), m_pWidget->m_hWnd);
  264.                     GetElement()->text_attr->FE_Data = pMyFont;
  265.                     //    Now figure up the width and height we would like.
  266.                     int32 lWidgetWidth = pMyFont->GetMaxWidth();
  267.                     int32 lWidgetHeight = pMyFont->GetHeight() + (pMyFont->GetHeight() / 2);
  268.  
  269.                     //    See if we can measure the default text, and/or
  270.                     //        set up the size and size limits.
  271.                     if(GetElementTextData())    {
  272.                         if(GetElementTextData()->size > 0)    {
  273.                             //    Use provided size.
  274.                             lLength = GetElementTextData()->size;
  275.  
  276.                             //    Use average width.
  277.                             lWidgetWidth += lLength * pMyFont->GetMeanWidth();
  278.                         }
  279.                         else if(GetElementTextData()->default_text)    {
  280.                             //    Use length of text, exactly.
  281.                             char *pDefault = (char *)GetElementTextData()->default_text;
  282.  
  283.                             lLength = XP_STRLEN(pDefault);
  284.                             SIZE csz;
  285.                             CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  286.                                     INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  287.                                     pDC->GetSafeHdc(), pDefault, CASTINT(lLength), &csz);
  288.                             //    Use this width.
  289.                             lWidgetWidth += csz.cx;
  290.                         }
  291.  
  292.                         //    Hold to the maximum size limit, and set it.
  293.                         if(GetElementTextData()->max_size >= 0)    {
  294.                             m_pWidget->LimitText(CASTINT(GetElementTextData()->max_size));
  295.                         }
  296.                     }
  297.  
  298.                     //    Restore old font selection.
  299.                     pDCCX->ReleaseNetscapeFont( pDC->GetSafeHdc(), pMyFont );
  300.                     m_pWidget->MoveWindow(1, 1, CASTINT(lWidgetWidth), CASTINT(lWidgetHeight), FALSE);
  301.                     m_pWidget->ReleaseDC(pDC);
  302.                 }
  303.                 else {
  304.                     m_pWidget->ReleaseDC(pDC);
  305.                     DestroyWidget();
  306.                     return;
  307.                 }
  308.             }
  309.             else    {
  310.                 //    No DC, no widget.
  311.                 DestroyWidget();
  312.                 return;
  313.             }
  314.         }
  315.         else if(GetContext()->IsPureDCContext())    {
  316.             //    Need a drawn representation.
  317.         }
  318.     }
  319. }
  320.  
  321. //    Copy the current data out of the layout struct into the form
  322. //        widget, or mark that you should represent using the current data.
  323. void CFormText::UseCurrentData()
  324. {
  325.     //    Detect context type and do the right thing.
  326.     if(GetContext())    {
  327.         if(GetContext()->IsWindowContext())    {
  328.             //    Need a widget.
  329.             if(m_pWidget)    {
  330.                 //    Determine the current text to set.
  331.                 char *pCurrent = "";
  332.                 if(GetElementTextData() && GetElementTextData()->current_text)    {
  333.                     pCurrent = (char *)GetElementTextData()->current_text;
  334.                 }
  335.                 // We have to SetContext to the widget before we SetWindowText
  336.                 // Otherwise, the widget don't know what csid the text is.
  337.                 m_pWidget->SetContext(GetContext()->GetContext(), GetElement());
  338.  
  339.                 m_pWidget->SetWindowText(pCurrent);
  340.             }
  341.         }
  342.         else if(GetContext()->IsPureDCContext())    {
  343.             //    Printing/metafile
  344.             //  Whatever is in current data is current....
  345.         }
  346.     }
  347. }
  348.  
  349. //    Copy the default data out of the layout struct into the form
  350. //        widget, or mark that you should represent using the default data.
  351. void CFormText::UseDefaultData()
  352. {
  353.     //    Detect context type and do the right thing.
  354.     if(GetContext())    {
  355.         if(GetContext()->IsWindowContext())    {
  356.             //    Need a widget.
  357.             if(m_pWidget)    {
  358.                 //    Determine the default text to set.
  359.                 char *pDefault = "";
  360.                 if(GetElementTextData() && GetElementTextData()->default_text)    {
  361.                     pDefault = (char *)GetElementTextData()->default_text;
  362.                 }
  363.                 // We have to SetContext to the widget before we SetWindowText
  364.                 // Otherwise, the widget don't know what csid the text is.
  365.                 m_pWidget->SetContext(GetContext()->GetContext(), GetElement());
  366.                 m_pWidget->SetWindowText(pDefault);
  367.             }
  368.         }
  369.         else if(GetContext()->IsPureDCContext())    {
  370.             //    Printing/metafile
  371.             //  Delete any current data, attempt to use the default data if present.
  372.             if(GetElementTextData())    {
  373.                 if(GetElementTextData()->current_text)  {
  374.                     XP_FREE(GetElementTextData()->current_text);
  375.                     GetElementTextData()->current_text = NULL;
  376.                 }
  377.  
  378.                 if(GetElementTextData()->default_text) {
  379.                     char *pText = (char *)GetElementTextData()->default_text;
  380.                     int32 lSize = XP_STRLEN(pText) + 1;
  381.                     GetElementTextData()->current_text = (XP_Block)XP_ALLOC(lSize);
  382.                     memcpy(GetElementTextData()->current_text, pText, CASTSIZE_T(lSize));
  383.                 }
  384.             }
  385.         }
  386.     }
  387. }
  388.  
  389. //    Fill in the layout size information in the layout struct regarding
  390. //        the dimensions of the widget.
  391. void CFormText::FillSizeInfo()
  392. {
  393.     //    Detect context type and do the right thing.
  394.     if(GetContext() && GetElement())    {
  395.         if(GetContext()->IsWindowContext())    {
  396.             //    Need a widget.
  397.             if(m_pWidget)    {
  398.                 //    Determine our window position.
  399.                 CRect crRect;
  400.                 m_pWidget->GetWindowRect(crRect);
  401.  
  402.                 //    Munge the coordinate a little for layout.
  403.                 //    We'll have to know how to decode this information
  404.                 //        in the display routine (by half).
  405.                 GetElement()->width = crRect.Width();
  406.                 GetElement()->height = crRect.Height() + EDIT_SPACE;
  407.                 GetElement()->border_vert_space = EDIT_SPACE/2;
  408.                 GetElement()->baseline = GetElement()->height - GetElement()->height / 4;
  409.             }
  410.             else    {
  411.                 //    No widget, tell layout nothing.
  412.                 GetElement()->width = 0;
  413.                 GetElement()->height = 0;
  414.                 GetElement()->baseline = 0;
  415.             }
  416.         }
  417.         else if(GetContext()->IsPureDCContext())    {
  418.             int32 lWidth = 0;
  419.             int32 lHeight = 0;
  420.             int32 lBaseline = 0;
  421.  
  422.             //  Need to figure the size of the widget.
  423.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  424.                 HDC pDC = pDCCX->GetAttribDC();
  425.                 if(pDC) {
  426.                     CyaFont    *pMyFont;
  427.                     int32 lLength = 20;
  428.                     
  429.                     pDCCX->SelectNetscapeFont( pDC, GetTextAttr(), pMyFont );
  430.                     if (pMyFont) {
  431.                         SetWidgetFont(pDC, m_pWidget->m_hWnd);
  432.                         lWidth = pMyFont->GetMaxWidth();
  433.                         lHeight = pMyFont->GetHeight() + pMyFont->GetHeight() / 2 + pDCCX->Twips2PixY(EDIT_SPACE);
  434.  
  435.                         //  Attempt to measure text.
  436.                         if(GetElementTextData())    {
  437.                             if(GetElementTextData()->size > 0)  {
  438.                                 //  Use provided size.
  439.                                 lLength = GetElementTextData()->size;
  440.  
  441.                                 //  Figure width using average char width.
  442.                                 lWidth += lLength * pMyFont->GetMeanWidth();
  443.                             }
  444.                             else if(GetElementTextData()->default_text) {
  445.                                 //  Use length of text instead.
  446.                                 char *pText = (char *)GetElementTextData()->default_text;
  447.                                 lLength = XP_STRLEN(pText);
  448.  
  449.                                 //  Use exact size information.
  450.                                 SIZE csz;
  451.                                 CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  452.                                     INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  453.                                     pDC, pText, CASTINT(lLength), &csz);
  454.                                 lWidth += csz.cx;
  455.                             }
  456.                         }
  457.  
  458.                         //  Figure baseline.
  459.                         lBaseline = lHeight - (pMyFont->GetHeight() / 2 + pMyFont->GetDescent()) / 2;
  460.                             pDCCX->ReleaseNetscapeFont( pDC, pMyFont );
  461.                     }
  462.                     else {
  463.                         m_pWidget->ReleaseDC(CDC::FromHandle(pDC));
  464.                         DestroyWidget();
  465.                     }
  466.                     pDCCX->ReleaseContextDC(pDC);
  467.             }
  468.  
  469.             //  Inform layout what we now know.
  470.             GetElement()->width = lWidth;
  471.             GetElement()->height = lHeight;
  472.             GetElement()->baseline = lBaseline;
  473.         }
  474.     }
  475. }
  476.  
  477. //    Copy the current data out of the form element back into the
  478. //        layout struct.
  479. void CFormText::UpdateCurrentData()
  480. {
  481.     if(GetContext())    {
  482.         if(GetContext()->IsWindowContext())    {
  483.             if(m_pWidget && ::IsWindow(m_pWidget->GetSafeHwnd()) && GetElementTextData())    {
  484.                 //    Free off any current text.
  485.                 if(GetElementTextData()->current_text)    {
  486.                     XP_FREE(GetElementTextData()->current_text);
  487.                     GetElementTextData()->current_text = NULL;
  488.                 }
  489.                 //    See if we've got anything.
  490.                 int32 lLength = m_pWidget->GetWindowTextLength();
  491.                 if(lLength > 0)    {
  492.                     GetElementTextData()->current_text = (XP_Block)XP_ALLOC(lLength + 1);
  493.                     if(GetElementTextData()->current_text)    {
  494.                         m_pWidget->GetWindowText((char *)GetElementTextData()->current_text, CASTINT(lLength + 1));
  495.                     }
  496.                 }
  497.             }
  498.         }
  499.         else if(GetContext()->IsPureDCContext())    {
  500.             //    Printing/metafile
  501.             //  If there is no current data, attempt to use the default data if present.
  502.             if(GetElementTextData())    {
  503.                 if(GetElementTextData()->default_text) {
  504.                     char *pText = (char *)GetElementTextData()->default_text;
  505.                     if(GetElementTextData()->current_text == NULL)  {
  506.                         int32 lSize = XP_STRLEN(pText) + 1;
  507.                         GetElementTextData()->current_text = (XP_Block)XP_ALLOC(lSize);
  508.                         memcpy(GetElementTextData()->current_text, pText, CASTSIZE_T(lSize));
  509.                     }
  510.                 }
  511.             }
  512.         }
  513.     }
  514. }
  515.  
  516. HWND CFormText::GetRaw()
  517. {
  518.     return(m_pWidget ? m_pWidget->m_hWnd : NULL);
  519. }
  520.