/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "stdafx.h" #include "fmtext.h" #include "odctrl.h" #include "intl_csi.h" // This file is dedicated to form type select one elements // otherwise known as list boxes on windows and // their implementation as requried by the XP layout // library. // Construction simply clears all members. CFormText::CFormText() { // No widget yet. m_pWidget = NULL; } // Destruction cleans out all members. CFormText::~CFormText() { } // How to set the LO form element. // This may change during the lifetime of an instance, so use this // to update all referencing values. void CFormText::SetElement(LO_FormElementStruct *pFormElement) { // Call the base. CFormElement::SetElement(pFormElement); // Let the widget know the element. if(m_pWidget) { m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement()); } } // Set the owning context. // Use this to determine what context we live in and how we should // represent ourself (DC or window). void CFormText::SetContext(CAbstractCX *pCX) { // Call the base. CFormElement::SetContext(pCX); // Let the widget know the context. if(m_pWidget) { m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement()); } } // Display the form element given the particular context we are in. // Possibly only use a DC for representation, or have the // window move. void CFormText::DisplayFormElement(LTRB& Rect) { // Display only has meaning if our context is a device context. if(GetContext() && GetContext()->IsDCContext()) { // Further, need to detect how we're going to be drawing ourselves. if(GetContext()->IsPureDCContext()) { // Only works from a DC, needs a GDI drawing representation. CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX); LTRB r(Rect.left, Rect.top, Rect.right, Rect.bottom); // Adjust for what we bastardized earlier in fill size info. r.Inflate(0, -1 * pDCCX->Pix2TwipsY(EDIT_SPACE) / 2); // Do something simple. pDCCX->Display3DBox(r, pDCCX->ResolveLightLineColor(), pDCCX->ResolveDarkLineColor(), pDCCX->Pix2TwipsY(2)); // Final adjustment for below... r.Inflate(-1 * pDCCX->Twips2PixX(2), -1 * pDCCX->Twips2PixY(2)); // Is there text to output. if(GetElementTextData() && GetElementTextData()->current_text) { char *pText = (char *)GetElementTextData()->current_text; // Obtain the font for the text to be drawn. // Get the DC. HDC pDC = pDCCX->GetContextDC(); if(pDC) { CyaFont *pMyFont; pDCCX->SelectNetscapeFont( pDC, GetTextAttr(), pMyFont ); if (pMyFont) { SetWidgetFont(pDC, m_pWidget->m_hWnd); int32 lTextLength = XP_STRLEN(pText); char *pTextBuf = new char[lTextLength + 1]; if(pTextBuf) { // Clear it. memset(pTextBuf, 0, CASTSIZE_T(lTextLength + 1)); // Decide if a password. if(GetElementMinimalData()->type == FORM_TYPE_PASSWORD) { memset(pTextBuf, '*', CASTSIZE_T(lTextLength)); } else { strcpy(pTextBuf, pText); } // Text mode must go transparent (some printers block out drawing around text). int iOldBk = ::SetBkMode(pDC, TRANSPARENT); // Decide the destination for the text rect. // We need to move the text to the right and left some, and on the Y. RECT crDest; ::SetRect(&crDest, CASTINT(r.left), CASTINT(r.top), CASTINT(r.right), CASTINT(r.bottom)); crDest.left += pMyFont->GetMeanWidth(); crDest.top += ((crDest.bottom - crDest.top) - (pMyFont->GetHeight())) / 2; // Finally draw the text. // The clipping rect is not the destination rect. CIntlWin::ExtTextOut( (GetContext()->GetContext() ? INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())) :0), pDC, crDest.left, crDest.top, ETO_CLIPPED, CRect(CASTINT(r.left), CASTINT(r.top), CASTINT(r.right), CASTINT(r.bottom)), pTextBuf, CASTINT(lTextLength), NULL); // Restore Bk mode. ::SetBkMode(pDC, iOldBk); // Get rid of the buffer. delete[] pTextBuf; // } pDCCX->ReleaseNetscapeFont( pDC, pMyFont ); } else { m_pWidget->ReleaseDC(CDC::FromHandle(pDC)); DestroyWidget(); } pDCCX->ReleaseContextDC(pDC); } } } } else if(GetContext()->IsWindowContext()) { MoveWindow(m_pWidget->m_hWnd, Rect.left, Rect.top + EDIT_SPACE / 2); } else { // Is undefined.... ASSERT(0); } } // Call the base. CFormElement::DisplayFormElement(Rect); } // Destroy the widget (window) implemenation of the form. void CFormText::DestroyWidget() { // Get rid of the widget if around. if(m_pWidget) { m_pWidget->DestroyWindow(); delete m_pWidget; m_pWidget = NULL; } } // Create the widget (window) implementation of the form // but DO NOT DISPLAY. void CFormText::CreateWidget() { if(GetContext() && GetElement()) { if(GetContext()->IsWindowContext() && VOID2CX(GetContext(), CPaneCX)->GetPane()) { // Need a widget representation. ASSERT(m_pWidget == NULL); m_pWidget = new CODNetscapeEdit; if(m_pWidget == NULL) { return; } // Inform widget of context and element. m_pWidget->SetContext(GetContext()->GetContext(), GetElement()); #ifdef XP_WIN16 // On 16 bits, we need to set the segment of the widget before creation. HINSTANCE hSegment = GetSegment(); if(hSegment) { m_pWidget->SetInstance(hSegment); } else { delete m_pWidget; m_pWidget = NULL; return; } #endif // The style of the widget to be created. DWORD dwStyle = WS_CHILD | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP; if(GetElementMinimalData()) { switch(GetElementMinimalData()->type) { case FORM_TYPE_PASSWORD: dwStyle |= ES_PASSWORD; break; default: break; } } else { // Must set styles. delete m_pWidget; m_pWidget = NULL; return; } // Create the widget, hidden, and with a bad size. BOOL bCreate = #ifdef XP_WIN32 m_pWidget->CreateEx(WS_EX_CLIENTEDGE, _T("EDIT"), NULL, dwStyle, 1, 1, 0, 0, VOID2CX(GetContext(), CPaneCX)->GetPane(), (HMENU)GetDynamicControlID(), NULL); #else m_pWidget->Create(dwStyle, CRect(1, 1, 0, 0), CWnd::FromHandle(VOID2CX(GetContext(), CPaneCX)->GetPane()), GetDynamicControlID()); #endif if(!bCreate) { delete m_pWidget; m_pWidget = NULL; return; } // Next, need to size the widget. // Obtain a font. // Measure some text. CDC *pDC = m_pWidget->GetDC(); CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX); if(pDC) { // Default length is 20 int32 lLength = 20; CyaFont *pMyFont; pDCCX->SelectNetscapeFont( pDC->GetSafeHdc(), GetTextAttr(), pMyFont ); if (pMyFont) { SetWidgetFont(pDC->GetSafeHdc(), m_pWidget->m_hWnd); GetElement()->text_attr->FE_Data = pMyFont; // Now figure up the width and height we would like. int32 lWidgetWidth = pMyFont->GetMaxWidth(); int32 lWidgetHeight = pMyFont->GetHeight() + (pMyFont->GetHeight() / 2); // See if we can measure the default text, and/or // set up the size and size limits. if(GetElementTextData()) { if(GetElementTextData()->size > 0) { // Use provided size. lLength = GetElementTextData()->size; // Use average width. lWidgetWidth += lLength * pMyFont->GetMeanWidth(); } else if(GetElementTextData()->default_text) { // Use length of text, exactly. char *pDefault = (char *)GetElementTextData()->default_text; lLength = XP_STRLEN(pDefault); SIZE csz; CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())), pDC->GetSafeHdc(), pDefault, CASTINT(lLength), &csz); // Use this width. lWidgetWidth += csz.cx; } // Hold to the maximum size limit, and set it. if(GetElementTextData()->max_size >= 0) { m_pWidget->LimitText(CASTINT(GetElementTextData()->max_size)); } } // Restore old font selection. pDCCX->ReleaseNetscapeFont( pDC->GetSafeHdc(), pMyFont ); m_pWidget->MoveWindow(1, 1, CASTINT(lWidgetWidth), CASTINT(lWidgetHeight), FALSE); m_pWidget->ReleaseDC(pDC); } else { m_pWidget->ReleaseDC(pDC); DestroyWidget(); return; } } else { // No DC, no widget. DestroyWidget(); return; } } else if(GetContext()->IsPureDCContext()) { // Need a drawn representation. } } } // Copy the current data out of the layout struct into the form // widget, or mark that you should represent using the current data. void CFormText::UseCurrentData() { // Detect context type and do the right thing. if(GetContext()) { if(GetContext()->IsWindowContext()) { // Need a widget. if(m_pWidget) { // Determine the current text to set. char *pCurrent = ""; if(GetElementTextData() && GetElementTextData()->current_text) { pCurrent = (char *)GetElementTextData()->current_text; } // We have to SetContext to the widget before we SetWindowText // Otherwise, the widget don't know what csid the text is. m_pWidget->SetContext(GetContext()->GetContext(), GetElement()); m_pWidget->SetWindowText(pCurrent); } } else if(GetContext()->IsPureDCContext()) { // Printing/metafile // Whatever is in current data is current.... } } } // Copy the default data out of the layout struct into the form // widget, or mark that you should represent using the default data. void CFormText::UseDefaultData() { // Detect context type and do the right thing. if(GetContext()) { if(GetContext()->IsWindowContext()) { // Need a widget. if(m_pWidget) { // Determine the default text to set. char *pDefault = ""; if(GetElementTextData() && GetElementTextData()->default_text) { pDefault = (char *)GetElementTextData()->default_text; } // We have to SetContext to the widget before we SetWindowText // Otherwise, the widget don't know what csid the text is. m_pWidget->SetContext(GetContext()->GetContext(), GetElement()); m_pWidget->SetWindowText(pDefault); } } else if(GetContext()->IsPureDCContext()) { // Printing/metafile // Delete any current data, attempt to use the default data if present. if(GetElementTextData()) { if(GetElementTextData()->current_text) { XP_FREE(GetElementTextData()->current_text); GetElementTextData()->current_text = NULL; } if(GetElementTextData()->default_text) { char *pText = (char *)GetElementTextData()->default_text; int32 lSize = XP_STRLEN(pText) + 1; GetElementTextData()->current_text = (XP_Block)XP_ALLOC(lSize); memcpy(GetElementTextData()->current_text, pText, CASTSIZE_T(lSize)); } } } } } // Fill in the layout size information in the layout struct regarding // the dimensions of the widget. void CFormText::FillSizeInfo() { // Detect context type and do the right thing. if(GetContext() && GetElement()) { if(GetContext()->IsWindowContext()) { // Need a widget. if(m_pWidget) { // Determine our window position. CRect crRect; m_pWidget->GetWindowRect(crRect); // Munge the coordinate a little for layout. // We'll have to know how to decode this information // in the display routine (by half). GetElement()->width = crRect.Width(); GetElement()->height = crRect.Height() + EDIT_SPACE; GetElement()->border_vert_space = EDIT_SPACE/2; GetElement()->baseline = GetElement()->height - GetElement()->height / 4; } else { // No widget, tell layout nothing. GetElement()->width = 0; GetElement()->height = 0; GetElement()->baseline = 0; } } else if(GetContext()->IsPureDCContext()) { int32 lWidth = 0; int32 lHeight = 0; int32 lBaseline = 0; // Need to figure the size of the widget. CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX); HDC pDC = pDCCX->GetAttribDC(); if(pDC) { CyaFont *pMyFont; int32 lLength = 20; pDCCX->SelectNetscapeFont( pDC, GetTextAttr(), pMyFont ); if (pMyFont) { SetWidgetFont(pDC, m_pWidget->m_hWnd); lWidth = pMyFont->GetMaxWidth(); lHeight = pMyFont->GetHeight() + pMyFont->GetHeight() / 2 + pDCCX->Twips2PixY(EDIT_SPACE); // Attempt to measure text. if(GetElementTextData()) { if(GetElementTextData()->size > 0) { // Use provided size. lLength = GetElementTextData()->size; // Figure width using average char width. lWidth += lLength * pMyFont->GetMeanWidth(); } else if(GetElementTextData()->default_text) { // Use length of text instead. char *pText = (char *)GetElementTextData()->default_text; lLength = XP_STRLEN(pText); // Use exact size information. SIZE csz; CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())), pDC, pText, CASTINT(lLength), &csz); lWidth += csz.cx; } } // Figure baseline. lBaseline = lHeight - (pMyFont->GetHeight() / 2 + pMyFont->GetDescent()) / 2; pDCCX->ReleaseNetscapeFont( pDC, pMyFont ); } else { m_pWidget->ReleaseDC(CDC::FromHandle(pDC)); DestroyWidget(); } pDCCX->ReleaseContextDC(pDC); } // Inform layout what we now know. GetElement()->width = lWidth; GetElement()->height = lHeight; GetElement()->baseline = lBaseline; } } } // Copy the current data out of the form element back into the // layout struct. void CFormText::UpdateCurrentData() { if(GetContext()) { if(GetContext()->IsWindowContext()) { if(m_pWidget && ::IsWindow(m_pWidget->GetSafeHwnd()) && GetElementTextData()) { // Free off any current text. if(GetElementTextData()->current_text) { XP_FREE(GetElementTextData()->current_text); GetElementTextData()->current_text = NULL; } // See if we've got anything. int32 lLength = m_pWidget->GetWindowTextLength(); if(lLength > 0) { GetElementTextData()->current_text = (XP_Block)XP_ALLOC(lLength + 1); if(GetElementTextData()->current_text) { m_pWidget->GetWindowText((char *)GetElementTextData()->current_text, CASTINT(lLength + 1)); } } } } else if(GetContext()->IsPureDCContext()) { // Printing/metafile // If there is no current data, attempt to use the default data if present. if(GetElementTextData()) { if(GetElementTextData()->default_text) { char *pText = (char *)GetElementTextData()->default_text; if(GetElementTextData()->current_text == NULL) { int32 lSize = XP_STRLEN(pText) + 1; GetElementTextData()->current_text = (XP_Block)XP_ALLOC(lSize); memcpy(GetElementTextData()->current_text, pText, CASTSIZE_T(lSize)); } } } } } } HWND CFormText::GetRaw() { return(m_pWidget ? m_pWidget->m_hWnd : NULL); }