gecko-dev/cmd/winfe/odctrl.cpp
1998-03-28 02:44:41 +00:00

626 lines
16 KiB
C++
Executable File

/* -*- 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.
*/
//
// This file contains the implementation of
// CODNetscapeButton
// CODMochaListBox
// CODMochaComboBox
//
// Why we need the ownerdrawn version ?
// 1. So we could display UTF8 widget
// 2. So we coudl use Unicode Font on US Win95 to display non-Latin
// characters.
// Requried include file
#include "stdafx.h"
#include "odctrl.h"
#include "intlwin.h"
#include "intl_csi.h"
//////////////////////////////////////////////////////////////////////////
//
// CODNetscapeButton
//
//////////////////////////////////////////////////////////////////////////
CODNetscapeButton::CODNetscapeButton(MWContext * context, LO_FormElementStruct * form, CWnd* pParent) :
CNetscapeButton(context, form, pParent)
{
}
void CODNetscapeButton::Draw3DBox(CDC *pDC, CRect& r, BOOL selected)
{
// fill out the rectangle wiht background brush
CBrush* pBrush = new CBrush ( ::GetSysColor (COLOR_BTNFACE));
pDC->FillRect (r, pBrush);
delete pBrush;
// decide which color we should use to draw the four edges
COLORREF color1, color2, color3, color4;
#ifdef XP_WIN32
if(selected)
{
color1 = ::GetSysColor(COLOR_3DHILIGHT);
color2 = ::GetSysColor(COLOR_3DLIGHT);
color3 = ::GetSysColor(COLOR_3DDKSHADOW);
color4 = ::GetSysColor(COLOR_3DSHADOW);
}
else
{
color1 = ::GetSysColor(COLOR_3DDKSHADOW);
color2 = ::GetSysColor(COLOR_3DSHADOW);
color3 = ::GetSysColor(COLOR_3DHILIGHT);
color4 = ::GetSysColor(COLOR_3DLIGHT);
}
#else
if(selected)
{
color1 = ::GetSysColor(COLOR_BTNHIGHLIGHT);
color2 = ::GetSysColor(COLOR_BTNHIGHLIGHT);
color3 = ::GetSysColor(COLOR_BTNSHADOW);
color4 = ::GetSysColor(COLOR_BTNSHADOW);
}
else
{
color1 = ::GetSysColor(COLOR_BTNSHADOW);
color2 = ::GetSysColor(COLOR_BTNSHADOW);
color3 = ::GetSysColor(COLOR_BTNHIGHLIGHT);
color4 = ::GetSysColor(COLOR_BTNHIGHLIGHT);
}
#endif
// 3. create pen and draw them
CPen* pPen1 = new CPen( PS_SOLID, 0, color1);
CPen* pOldpen = pDC->SelectObject(pPen1);
POINT seg1[3];
seg1[0].x = r.left;
seg1[0].y = r.bottom-1;
seg1[1].x = r.right-1;
seg1[1].y = r.bottom-1;
seg1[2].x = r.right-1;
seg1[2].y = r.top;
pDC->Polyline(seg1, 3);
CPen* pPen2 = new CPen( PS_SOLID, 0, color2);
pDC->SelectObject(pPen2);
delete pPen1;
POINT seg2[3];
seg2[0].x = r.left+1;
seg2[0].y = r.bottom-2;
seg2[1].x = r.right-2;
seg2[1].y = r.bottom-2;
seg2[2].x = r.right-2;
seg2[2].y = r.top;
pDC->Polyline(seg2, 3);
CPen* pPen3 = new CPen( PS_SOLID, 0, color3);
pDC->SelectObject(pPen3);
delete pPen2;
POINT seg3[3];
seg3[0].x = r.left;
seg3[0].y = r.bottom-2;
seg3[1].x = r.left;
seg3[1].y = r.top;
seg3[2].x = r.right-1;
seg3[2].y = r.top;
pDC->Polyline(seg3, 3);
CPen* pPen4 = new CPen( PS_SOLID, 0, color4);
pDC->SelectObject(pPen4);
delete pPen3;
POINT seg4[3];
seg4[0].x = r.left+1;
seg4[0].y = r.bottom-3;
seg4[1].x = r.left+1;
seg4[1].y = r.top+1;
seg4[2].x = r.right-2;
seg4[2].y = r.top+1;
pDC->Polyline(seg4, 3);
pDC->SelectObject(pOldpen);
delete pPen4;
}
void CODNetscapeButton::DrawCenterText(CDC *pDC, LPCSTR text, CRect& r)
{
CSize size;
int16 wincsid = INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(m_Context));
LO_TextAttr *text_attr = m_Form->text_attr;
// Measure what the size of the button should be.
CyaFont *pMyFont;
CXDC(m_Context)->SelectNetscapeFont( pDC->GetSafeHdc(), text_attr, pMyFont );
// pMyFont->PrepareDrawText(pDC->GetSafeHdc());
CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, wincsid,
pDC->GetSafeHdc(), text, XP_STRLEN(text), &size);
CIntlWin::TextOutWithCyaFont(pMyFont, wincsid, pDC->GetSafeHdc(),
(r.right + r.left - size.cx) / 2 ,
(r.top + r.bottom - size.cy) / 2 ,
text, XP_STRLEN(text));
// pMyFont->EndDrawText( pDC->GetSafeHdc( ));
CXDC(m_Context)->ReleaseNetscapeFont( pDC->GetSafeHdc(), pMyFont );
}
void CODNetscapeButton::DrawContent(CDC *pDC, LPDRAWITEMSTRUCT lpdis)
{
CString text;
int16 win_csid = INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(m_Context));
if (CS_UTF8 == win_csid)
{
// UTF8 text is broken inside MFC or WINAPI.
// We need to use original data in form.
// We should maybe only use this part (not call MFC get a window text).
// This should be reviewed again for Gromit.
LO_FormElementStruct* elm = GetElement();
lo_FormElementMinimalData ele_minimal = elm->element_data->ele_minimal;
char *cp = (char *) (ele_minimal.value);
text = CString(cp);
}
else
{
GetWindowText(text);
}
// set the mode to TRANSPARENT
pDC->SetBkMode(TRANSPARENT);
// If it is disabled, draw a ghost one first.
if(lpdis->itemState & ODS_DISABLED)
{
#ifdef XP_WIN32
pDC->SetTextColor(::GetSysColor(COLOR_3DLIGHT));
#else
// *** Fix me ftang
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
#endif
CRect ghostRect = lpdis->rcItem;
ghostRect.OffsetRect(1,1);
this->DrawCenterText(pDC, (LPCSTR)text, ghostRect);
pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
}
else
{
pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
}
// Find teh rect that we should draw the text
CRect textrect = lpdis->rcItem;
if(lpdis->itemState & ODS_SELECTED)
textrect.OffsetRect(1,1);
// Draw the text
this->DrawCenterText(pDC, (LPCSTR)text, textrect);
// Draw focus box
if( (lpdis->itemState & ODS_FOCUS) &&
!(lpdis->itemState & ODS_DISABLED))
{
CRect rect = lpdis->rcItem;
rect.InflateRect(-3, -3);
pDC->DrawFocusRect(rect);
}
}
void CODNetscapeButton::DrawItem(LPDRAWITEMSTRUCT lpdis)
{
CDC dc;
dc.Attach (lpdis->hDC);
CRect rect = lpdis->rcItem;
this->Draw3DBox(&dc, rect, (lpdis->itemState & ODS_SELECTED));
this->DrawContent(&dc, lpdis);
dc.Detach();
}
//////////////////////////////////////////////////////////////////////////
//
// CODMochaListBox
//
//////////////////////////////////////////////////////////////////////////
// Helper routine used shared by list box and combo box code
static void
DrawTheItem(LPDRAWITEMSTRUCT lpdis, int16 wincsid, LO_TextAttr* text_attr, MWContext* m_Context)
{
#ifdef _WIN32
::FillRect(lpdis->hDC, &lpdis->rcItem, lpdis->itemState & ODS_SELECTED ?
(HBRUSH)(COLOR_HIGHLIGHT + 1) : (HBRUSH)(COLOR_WINDOW + 1));
#else
HBRUSH hBrush;
// Paint the item background
hBrush = ::CreateSolidBrush(::GetSysColor(lpdis->itemState & ODS_SELECTED ?
COLOR_HIGHLIGHT : COLOR_WINDOW));
::FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
::DeleteObject(hBrush);
#endif
// Measure what the size of the button should be.
if (lpdis->itemID != (UINT)-1) {
CyaFont *pMyFont;
CXDC(m_Context)->SelectNetscapeFont( lpdis->hDC, text_attr, pMyFont );
//pMyFont->PrepareDrawText(lpdis->hDC);
::SetTextColor(lpdis->hDC, ::GetSysColor(lpdis->itemState & ODS_SELECTED ?
COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
::SetBkColor(lpdis->hDC, ::GetSysColor(lpdis->itemState & ODS_SELECTED ?
COLOR_HIGHLIGHT : COLOR_WINDOW ));
CIntlWin::TextOutWithCyaFont(pMyFont, wincsid, lpdis->hDC,
2 + lpdis->rcItem.left, lpdis->rcItem.top,
(LPCSTR)lpdis->itemData, XP_STRLEN((char*)lpdis->itemData));
//pMyFont->EndDrawText(lpdis->hDC);
CXDC(m_Context)->ReleaseNetscapeFont( lpdis->hDC, pMyFont );
}
if (lpdis->itemState & ODS_FOCUS)
::DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
}
void CODMochaListBox::MeasureItem(LPMEASUREITEMSTRUCT lpmis)
{
CyaFont *pMyFont;
CDC *pDC = GetDC();
HDC hDC = pDC->GetSafeHdc();
CXDC(m_Context)->SelectNetscapeFont( hDC, m_Form->text_attr, pMyFont );
lpmis->itemHeight = pMyFont->GetHeight();
CXDC(m_Context)->ReleaseNetscapeFont( hDC, pMyFont );
ReleaseDC(pDC);
}
void CODMochaListBox::DrawItem(LPDRAWITEMSTRUCT lpdis)
{
LO_LockLayout();
INTL_CharSetInfo csi = LO_GetDocumentCharacterSetInfo(m_Context);
DrawTheItem(lpdis, INTL_GetCSIWinCSID(csi), m_Form->text_attr, m_Context);
LO_UnlockLayout();
}
//////////////////////////////////////////////////////////////////////////
//
// CODMochaComboBox
//
//////////////////////////////////////////////////////////////////////////
void CODMochaComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpmis)
{
CyaFont *pMyFont;
CDC *pDC = GetDC();
CXDC(m_Context)->SelectNetscapeFont( pDC->GetSafeHdc(), m_Form->text_attr, pMyFont );
lpmis->itemHeight = pMyFont->GetHeight();
CXDC(m_Context)->ReleaseNetscapeFont( pDC->GetSafeHdc(), pMyFont );
ReleaseDC(pDC);
}
void CODMochaComboBox::DrawItem(LPDRAWITEMSTRUCT lpdis)
{
LO_LockLayout();
INTL_CharSetInfo csi = LO_GetDocumentCharacterSetInfo(m_Context);
DrawTheItem(lpdis, INTL_GetCSIWinCSID(csi), m_Form->text_attr, m_Context);
LO_UnlockLayout();
}
//////////////////////////////////////////////////////////////////////////
//
// CUTF8NetscapeEdit
//
//////////////////////////////////////////////////////////////////////////
#define ResizeBuffer(b,l,nl) \
if((nl) > (l)) { \
(b) = ((b) == NULL) ? ((unsigned char*) malloc( ((l)=(((nl) < 512) ? 512 : (nl))))) \
: ((unsigned char*) realloc((b), ((l)=(((nl) < 512) ? 512 : (nl))))); \
}
CODNetscapeEdit::CODNetscapeEdit()
{
m_set_text_wincsid = 0;
m_convertedBufSize = m_ucs2BufSize = m_gettextBufSize = 0;
m_ucs2Buf = m_convertedBuf = m_gettextBuf = NULL;
}
CODNetscapeEdit::~CODNetscapeEdit()
{
if(m_convertedBuf != NULL)
{
free(m_convertedBuf);
m_convertedBuf = NULL;
m_convertedBufSize = 0;
}
if(m_ucs2Buf != NULL)
{
free(m_ucs2Buf);
m_ucs2Buf=NULL;
m_ucs2BufSize = 0;
}
if(m_gettextBuf != NULL)
{
free(m_gettextBuf);
m_gettextBuf=NULL;
m_gettextBufSize = 0;
}
}
void
CODNetscapeEdit::GetWindowText(CString& rString)
{
if( (CIntlWin::UseUnicodeFontAPI(GetSetWindowTextCSID())) ||
(sysInfo.m_bWinNT))
{
int nLen = GetWindowTextLength();
GetWindowText (rString.GetBufferSetLength(nLen), nLen+1);
rString.ReleaseBuffer();
}
else
{
CNetscapeEdit::GetWindowText(rString);
}
}
int
CODNetscapeEdit::GetWindowTextLength()
{
if( (CIntlWin::UseUnicodeFontAPI(GetSetWindowTextCSID())) ||
(sysInfo.m_bWinNT))
return GetWindowText(NULL, 0);
else
return CNetscapeEdit::GetWindowTextLength();
}
#ifdef XP_WIN32
void
CODNetscapeEdit::SetWindowTextW(HWND hWnd, LPCWSTR lpString)
{
::SendMessageW(hWnd, WM_SETTEXT, (WPARAM) 0, (LPARAM) lpString);
}
int
CODNetscapeEdit::GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
{
if(nMaxCount > 0)
return ::SendMessageW(hWnd, WM_GETTEXT, (WPARAM) nMaxCount, (LPARAM) lpString);
else
return ::SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0);
}
#endif
void
CODNetscapeEdit::SetWindowText(LPCTSTR lpszString)
{
int16 wincsid = GetWinCSID();
SetSetWindowTextCSID(wincsid);
#ifdef XP_WIN32
if(sysInfo.m_bWinNT)
{
// In case it is NT, we should convert it to Unicode and use
// if appropriate SendMessageW
ASSERT((strlen(lpszString) < 4) ||
(!((lpszString[0]=='?') && (lpszString[1]=='?') && (lpszString[2]=='?') && (lpszString[3]=='?')))
);
Convert(wincsid, CS_UCS2, (unsigned char*)lpszString);
SetWindowTextW(m_hWnd, (unsigned short*)m_convertedBuf);
return;
}
#endif
if(CS_UTF8 == wincsid)
{
int16 csid = CIntlWin::GetSystemLocaleCsid();
Convert(wincsid, csid, (unsigned char*)lpszString);
CNetscapeEdit::SetWindowText((char*)m_convertedBuf);
}
else
{
CNetscapeEdit::SetWindowText(lpszString);
}
}
int
CODNetscapeEdit::GetWindowText(LPTSTR lpszStringBuf, int nMaxCount)
{
#ifdef XP_WIN32
if(sysInfo.m_bWinNT)
{
// In case it is NT, we should convert it to Unicode and use
// if appropriate SendMessageW
int rawLen = (::GetWindowTextLengthW(m_hWnd) + 1) * 2;
ResizeBuffer(m_gettextBuf, m_gettextBufSize, rawLen);
GetWindowTextW(m_hWnd, (unsigned short*)m_gettextBuf, m_gettextBufSize / 2);
Convert(CS_UCS2, GetSetWindowTextCSID(), (unsigned char*)m_gettextBuf);
int convertedLen = strlen((char*)m_convertedBuf);
ASSERT((convertedLen < 4) ||
(! ((m_convertedBuf[0]=='?') && (m_convertedBuf[1]=='?') &&
(m_convertedBuf[2]=='?') && (m_convertedBuf[3]=='?')))
);
if((nMaxCount > 0) && (lpszStringBuf != NULL))
{
if(nMaxCount > convertedLen)
{
strcpy(lpszStringBuf, (char*)m_convertedBuf);
}
else
{
/* We should really make sure it return the whole characters */
strncpy(lpszStringBuf, (char*)m_convertedBuf, nMaxCount-1);
lpszStringBuf[nMaxCount-1] = '\0';
}
}
return convertedLen;
}
#endif
if(CS_UTF8 == GetWinCSID())
{
int rawLen = CNetscapeEdit::GetWindowTextLength();
if(rawLen == 0)
return 0;
ResizeBuffer(m_gettextBuf, m_gettextBufSize, rawLen);
// Currently, I have problem to use GetWindowTextW to get the
// Unicode text. Try to use DDE CF_UNICODETEXT instead
CNetscapeEdit::GetWindowText((char*)m_gettextBuf, m_gettextBufSize);
Convert(CIntlWin::GetSystemLocaleCsid(),GetWinCSID(), m_gettextBuf);
int convertedLen = strlen((char*)m_convertedBuf);
if((nMaxCount > 0) && (lpszStringBuf != NULL))
{
if(nMaxCount > convertedLen)
{
strcpy(lpszStringBuf, (char*)m_convertedBuf);
}
else
{
/* We should really make sure it return the whole characters */
strncpy(lpszStringBuf, (char*)m_convertedBuf, nMaxCount-1);
lpszStringBuf[nMaxCount-1] = '\0';
}
}
return convertedLen;
}
else
{
if(0 == nMaxCount)
return CNetscapeEdit::GetWindowTextLength();
else
return CNetscapeEdit::GetWindowText(lpszStringBuf,nMaxCount);
}
}
void CODNetscapeEdit::Convert(int16 from, int16 to, unsigned char* lpszString)
{
int ucs2bufneeded;
int ucs2len;
int mbbufneeded;
if((lpszString == NULL) || ((lpszString[0] == NULL) && (CS_UCS2 != from)))
{
ResizeBuffer(m_convertedBuf, m_convertedBufSize, 2);
m_convertedBuf[0] = '\0';
m_convertedBuf[1] = '\0'; // in case the to is UCS2
return;
}
if(CS_UCS2 == from)
{
// it the from is UCS2, then we don't need to convert it
// Just make sure the buffer is big enough and copy to it.
ucs2len = CASTINT(INTL_UnicodeLen((INTL_Unicode*)lpszString));
ucs2bufneeded = CASTINT((ucs2len + 1)* 2);
ResizeBuffer(m_ucs2Buf, m_ucs2BufSize, ucs2bufneeded);
memcpy((char*)m_ucs2Buf, (char*)lpszString, ucs2bufneeded);
m_ucs2Buf[ucs2len*2] = '\0'; // NULL terminated UCS2 string
m_ucs2Buf[ucs2len*2+1] = '\0'; // NULL terminated UCS2 string
} else {
ucs2bufneeded = CASTINT(INTL_StrToUnicodeLen(from, lpszString) * 2);
ResizeBuffer(m_ucs2Buf, m_ucs2BufSize, ucs2bufneeded);
ucs2len = CASTINT(INTL_StrToUnicode(from, lpszString, (INTL_Unicode*)m_ucs2Buf, m_ucs2BufSize));
}
if(CS_UCS2 == to)
{
// it the to is UCS2, then we don't need to convert it
// Just make sure the buffer is big enough and copy to it.
mbbufneeded = CASTINT((ucs2len+1)*2);
ResizeBuffer(m_convertedBuf, m_convertedBufSize, mbbufneeded);
memcpy((char*)m_convertedBuf, (char*)m_ucs2Buf, mbbufneeded);
m_convertedBuf[ucs2len*2] = '\0'; // NULL terminated UCS2 string
m_convertedBuf[ucs2len*2+1] = '\0'; // NULL terminated UCS2 string
} else {
mbbufneeded = CASTINT(INTL_UnicodeToStrLen(to, (INTL_Unicode*)m_ucs2Buf, ucs2len));
ResizeBuffer(m_convertedBuf, m_convertedBufSize, mbbufneeded);
INTL_UnicodeToStr(to, (INTL_Unicode*)m_ucs2Buf, ucs2len, m_convertedBuf, m_convertedBufSize);
}
}
int16
CODNetscapeEdit::GetSetWindowTextCSID()
{
// XP_ASSERT(0 != m_set_text_wincsid); // Make sure SetWindowText is called after SetWindowText
if(m_set_text_wincsid != CS_UNKNOWN && m_set_text_wincsid != CS_DEFAULT)
return m_set_text_wincsid;
else
return INTL_DefaultWinCharSetID(0); // temp use CS_LATIN1
}
int16 CODNetscapeEdit::GetWinCSID()
{
XP_ASSERT(m_Context);
if(m_Context)
{
return INTL_GetCSIWinCSID(
LO_GetDocumentCharacterSetInfo(m_Context));
}
else
{
return CS_DEFAULT; // CS_DEFAULT == 0
}
}
#ifdef XP_WIN32
BOOL CODNetscapeEdit::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{
if(sysInfo.m_bWinNT)
{
// Place holder for code deal with Unicode
}
return CEdit::CreateEx(dwExStyle, lpszClassName, lpszWindowName,
dwStyle, x, y, nWidth, nHeight, hWndParent, nIDorHMenu, lpParam);
}
#endif