gecko-dev/cmd/winfe/edprops.cpp

7782 lines
245 KiB
C++

/* -*- 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.
*/
// edprops.cpp : implementation file
//
#include "stdafx.h"
#ifdef EDITOR
#include "edres2.h"
#include "property.h"
#include "edprops.h"
#include "edttypes.h"
#include "edt.h"
#include "pa_tags.h"
#include "netsvw.h"
#include "edview.h"
#include "styles.h" // For WFE_DrawSwatch()
#ifndef XP_WIN32
#include "tooltip.h"
#endif
#include "nethelp.h"
#include "xp_help.h"
#include "prefapi.h"
#include "prefinfo.h"
// the dialog box & string resources are in edtrcdll DLL
#include "edtrcdll\src\resource.h"
// For XP Strings
extern "C" {
#include "xpgetstr.h"
#define WANT_ENUM_STRING_IDS
#include "allxpstr.h"
#undef WANT_ENUM_STRING_IDS
}
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
// Font shared by all comboboxes in dialogs and toolbars
// Should be 1-pixel, 8pt MS Sans Serif or default GUI or font on foreign systems
CFont * wfe_pFont = 0;
// BOLD version of above font
CFont * wfe_pBoldFont = 0;
int wfe_iFontHeight = 15; // Full Height of the this font
// Modification of wfe_iFontHeight for list boxes;
int wfe_iListItemHeight = 15;
extern void wfe_Progress(MWContext *pMWContext, const char *pMessage);
extern BOOL FE_ResolveLinkURL( MWContext* pMWContext,
CString& csURL, BOOL bAutoAdjustLinks );
BOOL bSaveDefaultHRule = TRUE;
int32 wfe_iFontSizeMode = ED_FONTSIZE_POINTS;
// Convert CString into non-const char*
#define CHAR_STR(csString) (char*)LPCSTR(csString)
#define MAX_AUTO_SAVE_MINUTES 600
#define COLORREF_SIZE sizeof(COLORREF)
// Array of colors to show in common color dialog
COLORREF wfe_CustomPalette[16];
// Colors saved in prefs - the last-picked text and background
COLORREF wfe_crLastColorPicked;
COLORREF wfe_crLastBkgrndColorPicked;
int wfe_iTrueTypeFontBase = 0;
int wfe_iTrueTypeFontCount = 0;
// Temporaritly set this to 0 to ignore the limit
// when using EnumTrueTypeFonts() callback
// to get a list of ALL fonts
int wfe_iTrueTypeFontLimit = MAX_TRUETYPE_FONTS;
// Global array of True-Type fonts
// Neccesitates restarting program after new fonts installed
char **wfe_ppTrueTypeFonts = NULL;
// Global index within wfe_ppTrueTypeFonts if "Other..." was needed (too many fonts)
int wfe_iFontFaceOtherIndex = 0;
// Limit count is now a variable -- if its 0, we are retrieving all fonts
// and directly filling a listbox or combobox with font names
int CALLBACK EXPORT
EnumTrueTypeFonts(LPLOGFONT lpnlf, LPTEXTMETRIC lpntm, int nFontType, LPARAM lParam)
{
if (lpntm->tmPitchAndFamily & (/*TMPF_VECTOR|TMPF_DEVICE|*/TMPF_TRUETYPE)){
if( wfe_iTrueTypeFontLimit == 0 )
{
// For this usage, lParam = handle to a CComboBox or CListBox we are filling
// (This is same as ListBox_AddString macro in WINDOWSX.H)
SendMessage((HWND)lParam, LB_ADDSTRING, 0L, (LPARAM)(LPCTSTR)(lpnlf->lfFaceName));
}
else if( wfe_iTrueTypeFontCount < wfe_iTrueTypeFontLimit )
{
// We are filling the cached global list of font faces
wfe_ppTrueTypeFonts[wfe_iTrueTypeFontCount] = XP_STRDUP(lpnlf->lfFaceName);
wfe_iTrueTypeFontCount++;
} else {
// Too many fonts -- add "Other..." to use common dialog
*((BOOL*)lParam) = TRUE;
// Stop looking for more fonts
return FALSE;
}
}
return TRUE;
}
int CompareStrings( const void *arg1, const void *arg2 )
{
// Compare all of both strings:
// TODO: DO WIDE/MULTIBYTE VERSION
return _stricmp( * ( char** ) arg1, * ( char** ) arg2 );
}
static BOOL bTooManyFonts = FALSE;
BOOL wfe_InitTrueTypeArray(CDC *pDC)
{
ASSERT(pDC);
HDC hdc = pDC->GetSafeHdc();
if( wfe_ppTrueTypeFonts ){
return bTooManyFonts;
}
wfe_iTrueTypeFontCount = 0;
wfe_iFontFaceOtherIndex = 0;
bTooManyFonts = FALSE;
wfe_ppTrueTypeFonts = (char**)XP_ALLOC(MAX_TRUETYPE_FONTS*sizeof(char*));
if( !wfe_ppTrueTypeFonts ){
ASSERT(wfe_ppTrueTypeFonts);
bTooManyFonts = TRUE;
return TRUE;
}
memset((void*)wfe_ppTrueTypeFonts, 0, MAX_TRUETYPE_FONTS*sizeof(char*));
EnumFontFamilies(hdc, NULL, (FONTENUMPROC)EnumTrueTypeFonts, (LPARAM)&bTooManyFonts);
if( wfe_iTrueTypeFontCount ){
// Sort font names using Quicksort algorithm:
qsort( (void *)wfe_ppTrueTypeFonts, (size_t)wfe_iTrueTypeFontCount, sizeof( char * ), CompareStrings );
}
return bTooManyFonts;
}
void wfe_FreeTrueTypeArray()
{
int i;
if( wfe_ppTrueTypeFonts ){
for( i = 0; i < MAX_TRUETYPE_FONTS; i++ ){
XP_FREEIF(wfe_ppTrueTypeFonts[i]);
}
XP_FREE(wfe_ppTrueTypeFonts);
wfe_ppTrueTypeFonts = 0;
}
wfe_iTrueTypeFontCount = 0;
}
static char pSepFont1[128] = "_";
int wfe_FillFontComboBox(CComboBox * pCombo, int * pMaxWidth)
{
char * pFontFaces = EDT_GetFontFaces();
CDC * pDC = pCombo->GetDC();
if( !pDC ) return 0;
HDC hdc = 0;
if( pMaxWidth ){
// We need this only if returning iMaxWidth
hdc = pDC->GetSafeHdc();
}
CSize cSize;
int iMaxWidth = 0;
int i = 0;
if( pFontFaces ){
char * pFont = pFontFaces;
int iLen;
for ( i = 0; i < 2; i++){
iLen = XP_STRLEN(pFont);
if( iLen ){
// add to the end of the list
// LIST MUST BE NOT SORTED for EDT_GetFontFaceIndex to work
if( i == 1 ){
// Add signal to draw separator under this string
strcpy(pSepFont1+1,pFont);
pCombo->AddString(pSepFont1);
} else {
pCombo->AddString(pFont);
}
if ( hdc ){
cSize = CIntlWin::GetTextExtent(0, hdc, pFont, strlen(pFont));
pDC->LPtoDP(&cSize);
if ( cSize.cx > iMaxWidth ){
iMaxWidth = cSize.cx;
}
}
pFont += iLen+1;
} else {
break;
}
}
}
// Done with built-in fonts -- next index must be start of True Type
wfe_iTrueTypeFontBase = i;
// Get pointers to array of font names
// (Global list should already be built)
if( wfe_iTrueTypeFontCount && wfe_ppTrueTypeFonts){
// Add sorted string list to combobox
for( int i = 0; i < wfe_iTrueTypeFontCount; i++ ){
char * pFontName = wfe_ppTrueTypeFonts[i];
pCombo->AddString(pFontName);
if ( hdc ){
cSize = CIntlWin::GetTextExtent(0, hdc, pFontName, strlen(pFontName));
pDC->LPtoDP(&cSize);
if ( cSize.cx > iMaxWidth ){
iMaxWidth = cSize.cx;
}
}
}
} else {
bTooManyFonts = TRUE;;
}
if( pMaxWidth ){
// Return max width so dropdown list can be expanded to fit
*pMaxWidth = iMaxWidth;
}
if( bTooManyFonts ){
// Add pointer to globalb "Other..." string
pCombo->AddString(ed_pOther);
// Calculage the index to the "Other..." item,
wfe_iFontFaceOtherIndex = wfe_iTrueTypeFontBase + wfe_iTrueTypeFontCount;
} else {
wfe_iFontFaceOtherIndex = 0;
}
pCombo->ReleaseDC(pDC);
return wfe_iFontFaceOtherIndex;
}
char wfe_pFontSizeString[64];
char wfe_pFontSizeList[MAX_FONT_SIZE+1][64];
int wfe_FillFontSizeCombo(MWContext *pMWContext, CNSComboBox * pCombo, BOOL bFixedWidth)
{
int iFontSize = EDT_GetFontSize(pMWContext);
if( pMWContext ) {
// Clear current data
pCombo->ResetContent();
// Format a string like: "+2" for advanced mode, or convert to
// point size for regular mode
for ( int i = 1; i < MAX_FONT_SIZE; i++ ){
pCombo->AddString(wfe_GetFontSizeString(pMWContext, i, bFixedWidth));
}
if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ){
// "_" will signal combobox to draw a separator under this
pCombo->AddString("_+4");
// This is "8 pts" so we must allow translating string
// (others assume all languages can use ascii numbers)
pCombo->AddString(szLoadString(IDS_8_PTS));
pCombo->AddString("9");
pCombo->AddString("10");
pCombo->AddString("11");
pCombo->AddString("12");
pCombo->AddString("14");
pCombo->AddString("16");
pCombo->AddString("18");
pCombo->AddString("20");
pCombo->AddString("22");
pCombo->AddString("24");
pCombo->AddString("26");
pCombo->AddString("28");
pCombo->AddString("36");
pCombo->AddString("48");
pCombo->AddString("72");
} else {
pCombo->AddString(wfe_GetFontSizeString(pMWContext, MAX_FONT_SIZE, bFixedWidth));
}
}
// Index to current size is 1 less than our relative size (range = 1-7)
// Note that this may be 0 (on startup)
return (iFontSize - 1);
}
// iSize should be 1 to 7
// Returns pointer to static string - DON'T FREE RESULT!
char * wfe_GetFontSizeString(MWContext * pMWContext, int iSize, BOOL bFixedWidth, BOOL bMenu)
{
ASSERT(pMWContext);
int iRelative = iSize - 1 + MIN_FONT_SIZE_RELATIVE;
CString csFormat;
if( wfe_iFontSizeMode != ED_FONTSIZE_POINTS ){
if ( iRelative < 0 ){
// Minus is very narrow - include extra leading space
csFormat = " -";
} else if ( iRelative > 0 ){
csFormat = '+';
} else {
// Use 2 spaces befor "0"; has same width as 1 "-" or "+" char
csFormat = " ";
}
if( bMenu && iSize > 2 ){
// Add underline for "accelerator" only for "0" and above
csFormat += '&';
}
csFormat += "%i";
wsprintf(wfe_pFontSizeList[iSize-1], LPCSTR(csFormat), abs(iRelative));
} else {
// Construct strings for Point sizes
CDCCX *pDC = VOID2CX(pMWContext->fe.cx, CDCCX);
EncodingInfo *pEncoding = theApp.m_pIntlFont->GetEncodingInfo(pMWContext);
int iBaseSize = bFixedWidth ? pEncoding->iFixSize : pEncoding->iPropSize;
double dPoints = pDC->CalcFontPointSize(iSize, iBaseSize);
wsprintf(wfe_pFontSizeList[iSize-1], "%d", (int)dPoints);
}
return wfe_pFontSizeList[iSize-1];
}
////////////////////////////////////////////////////////////////////////
// Local string helper functions
// Strip out quotes and spaces at the ends
void CleanupString(CString& csString)
{
csString.TrimLeft();
csString.TrimRight();
int iQuote;
while ( (iQuote = csString.Find('\"')) != -1 ){
csString = csString.Left(iQuote) + csString.Mid(iQuote+1);
}
}
// Extract separate Name and Value strings
// Return TRUE if Name string was found
BOOL GetNameAndValue(CString& csEntry, CString& csName, CString& csValue)
{
int iEqual = csEntry.Find('=');
if ( iEqual != -1 ) {
csName = csEntry.Left(iEqual);
CleanupString(csName);
csValue = csEntry.Mid(iEqual+1);
CleanupString(csValue);
return ( !csName.IsEmpty() );
}
return FALSE;
}
// Local function used by Image and Document Properties dialogs
//
BOOL wfe_ValidateImage(MWContext * pMWContext, CString& csImageURL, BOOL bCheckIfFileExists)
{
BOOL bRetVal = TRUE;
BOOL bFileExists = FALSE;
CleanupString(csImageURL);
char * pAbsoluteImageURL = NULL;
CString csURL;
// Empty is OK
if ( csImageURL.IsEmpty() ) {
return TRUE;
}
//int iUrlType = NET_URL_Type(csUrl);
// We will trust HTTP: URLs to be absolute and valid
if ( NET_IsHTTP_URL( csImageURL ) ) {
return TRUE;
}
// Convert to URL format -- just copies if already have URL syntax
WFE_ConvertFile2Url( csURL, (char*)LPCSTR(csImageURL) );
// Convert any user-enterred local strings to an absolute URL
History_entry * pEntry = SHIST_GetCurrent(&pMWContext->hist);
if( pEntry && pEntry->address ) {
pAbsoluteImageURL = NET_MakeAbsoluteURL(
pEntry->address, (char *)LPCSTR(csURL) );
}
if(bCheckIfFileExists && pAbsoluteImageURL) {
if ( NET_IsLocalFileURL((char*)LPCSTR(csImageURL)) ) {
// We have a local file URL -- test for existence
char * pLocal = NULL;
bFileExists = XP_ConvertUrlToLocalFile( csImageURL, &pLocal /*NULL*/);
if( pLocal ) XP_FREE(pLocal);
} else {
// Assume we have a local file - find it
XP_StatStruct statinfo;
if ( -1 != XP_Stat((char*)LPCSTR(csImageURL), &statinfo, xpURL) &&
statinfo.st_mode & _S_IFREG ) {
bFileExists = TRUE;
}
}
if ( !bFileExists ) {
CString csMsg;
AfxFormatString1(csMsg, IDS_ERR_SRC_NOT_FOUND, csImageURL);
CWnd *pParent = GetFrame(pMWContext)->GetFrameWnd()->GetLastActivePopup();
::MessageBox( pParent ? pParent->m_hWnd : NULL,
csMsg, szLoadString(IDS_VALIDATE_IMAGE_FILE),
MB_OK | MB_ICONEXCLAMATION);
}
}
if( bCheckIfFileExists ){
bRetVal = bFileExists;
}
if ( pAbsoluteImageURL ) {
if( bRetVal ){
csImageURL = pAbsoluteImageURL;
}
XP_FREE(pAbsoluteImageURL);
}
return bRetVal;
}
// Initialize the strings for percent/pixels combobox
// used with Width and Height input
void wfe_InitPixOrPercentCombos(CWnd* pParent)
{
CComboBox *pCombo =
(CComboBox*)(pParent->GetDlgItem(IDC_HEIGHT_PIX_OR_PERCENT));
if(pCombo){
pCombo->AddString(szLoadString(IDS_PIXELS));
pCombo->AddString(szLoadString(IDS_PERCENT_WINDOW));
}
pCombo = (CComboBox*)(pParent->GetDlgItem(IDC_WIDTH_PIX_OR_PERCENT));
if(pCombo){
pCombo->AddString(szLoadString(IDS_PIXELS));
pCombo->AddString(szLoadString(IDS_PERCENT_WINDOW));
}
}
// Get the "100%" Height and "100%" Width that layout uses:
// this is the current view's dimensions minus margins
void wfe_GetLayoutViewSize(MWContext * pMWContext, int32 * pWidth, int32 * pHeight)
{
if( pMWContext ){
int32 iXOrigin;
int32 iYOrigin;
int32 iHeight;
int32 iWidth;
int32 iMarginWidth;
int32 iMarginHeight;
FE_GetDocAndWindowPosition(pMWContext, &iXOrigin, &iYOrigin, &iWidth, &iHeight);
LO_GetDocumentMargins(pMWContext, &iMarginWidth, &iMarginHeight);
if( pWidth ){
*pWidth = iWidth - (2 * iMarginWidth);
}
if( pHeight ){
*pHeight = iHeight - (2 * iMarginHeight);
}
}
}
char * wfe_ConvertImage(char *p_fileurl,void *p_parentwindow,MWContext *p_pMWContext)
{
if( !wfe_ValidateImage(p_pMWContext, CString(p_fileurl), TRUE) ){
return NULL;
}
CONVERT_IMGCONTEXT imageContext;
CONVERT_IMG_INFO imageInfo;
memset(&imageContext,0,sizeof(CONVERT_IMGCONTEXT));
imageContext.m_stream.m_type=CONVERT_FILE;
char *t_charp;
XP_ConvertUrlToLocalFile(p_fileurl,&t_charp);
if (!t_charp) //failed to localize file
{
// Show same error message as when wfe_ValidateImage fails:
CString csMsg;
AfxFormatString1(csMsg, IDS_ERR_SRC_NOT_FOUND, p_fileurl);
CWnd *pParent = GetFrame(p_pMWContext)->GetFrameWnd()->GetLastActivePopup();
::MessageBox( pParent ? pParent->m_hWnd : NULL,
csMsg, szLoadString(IDS_VALIDATE_IMAGE_FILE),
MB_OK | MB_ICONEXCLAMATION);
return NULL;
}
XP_STRCPY(imageContext.m_filename,t_charp);
XP_FREE(t_charp);
imageContext.m_stream.m_file=XP_FileOpen(imageContext.m_filename,xpTemporary,XP_FILE_READ_BIN);
if (imageContext.m_stream.m_file)
{
imageContext.m_imagetype=conv_bmp;
imageContext.m_callbacks.m_dialogimagecallback=FE_ImageConvertDialog;
imageContext.m_callbacks.m_displaybuffercallback=FE_ImageConvertDisplayBuffer;
imageContext.m_callbacks.m_completecallback=NULL;
imageContext.m_pMWContext=p_pMWContext;
imageContext.m_parentwindow=p_parentwindow;
char *t_outputfilename[1];
t_outputfilename[0]=NULL;
CONVERT_IMAGERESULT t_result=convert_stream2image(imageContext,&imageInfo,1,t_outputfilename); //1 for 1 output
//there is a callback when complete
XP_FileClose(imageContext.m_stream.m_file);
if (t_outputfilename[0])
{
// If using GIF plugin, wait here until finished
// (edit buffer is not writeable during plugin use)
char * pLastDot = strrchr(t_outputfilename[0], '.');
if(pLastDot && 0 == _stricmp(pLastDot, ".gif")){
while(!EDT_IsWritableBuffer(p_pMWContext)) FEU_StayingAlive();
}
return t_outputfilename[0];
}
else
{
if (t_result>CONV_OK)//not cancel or ok
{
((CWnd *)p_parentwindow)->MessageBox(szLoadString(CNetscapeEditView::m_converrmsg[t_result]));
}
return NULL;
}
}
return NULL;
}
CNSComboBox::CNSComboBox() :
m_iSearchPos(0),
m_bAllowSearch(0),
m_dwButtonDownTime(0),
m_bCheckTime(0),
m_pNotInListText(0)
{
}
BOOL CNSComboBox::Create(RECT& rect, CWnd* pParentWnd, UINT nID)
{
if( !CComboBox::Create(CBS_DROPDOWNLIST|CBS_OWNERDRAWFIXED|WS_VISIBLE|WS_TABSTOP|WS_VSCROLL|WS_HSCROLL|CBS_AUTOHSCROLL,
rect, pParentWnd, nID) ){
TRACE0("Failed to create Netscape Combo-box\n");
return FALSE;
}
if( wfe_pFont )
SetFont(wfe_pFont);
return TRUE;
}
BOOL CNSComboBox::Subclass(CWnd* pParentWnd, UINT nID)
{
BOOL bResult = SubclassDlgItem(nID, pParentWnd);
if( bResult ){
if( wfe_pFont )
SetFont(wfe_pFont);
}
return bResult;
}
int CNSComboBox::FindSelectedOrSetText(char * pText, int iStartAt)
{
int iSel = -1;
if( pText ){
// Skip over initial signal for separator
if( *pText == '_' ){
pText++;
}
for( int i = iStartAt; i < GetCount(); i++ ){
char * pItem = (char*)GetItemData(i);
if( *pItem == '_' ){
pItem++;
}
if( 0 == strcmp(pText, pItem) ){
// We found it
iSel = i;
break;
}
}
}
if( iSel == -1 ){
// Text is not in the list
XP_FREEIF(m_pNotInListText);
m_pNotInListText = XP_STRDUP(pText ? pText : " ");
SetWindowText(m_pNotInListText);
}
else {
SetWindowText(pText);
}
// This must be AFTER the SetWindowText()
// so our setting it to -1 triggers display
// of m_pNotInListText in the closed combobox
SetCurSel(iSel);
return iSel;
}
void CNSComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
// all items are of fixed size
lpMIS->itemHeight = wfe_iListItemHeight;
}
//////////////////////////////////////////////////////////////
void CNSComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rectItem = lpDIS->rcItem;
if( lpDIS->itemState & ODS_SELECTED ){
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
} else {
pDC->SetTextColor(RGB(0,0,0));
pDC->SetBkColor(RGB(255,255,255));
}
char *pData;
if( lpDIS->itemData == -1){// When is this -1?
// This is a real neat trick to display text in closed
// dropdown combobox's main window even though
// text is not in list (selected item = -1)
// This text should be set in FindSelectedOrSetText
pData = m_pNotInListText;
} else {
pData = (char*)lpDIS->itemData;
}
if( pData ){
// Draw a gray line separator
CPen pen(PS_SOLID, 1, RGB(128,128,128));
CPen *pOldPen = pDC->SelectObject(&pen);
BOOL bDrawSeparator = FALSE;
if( *pData == '_' ){
// We have a separator - skip over signal character
pData++;
if( GetDroppedState() ) {
bDrawSeparator = TRUE;
}
}
pDC->ExtTextOut(4, rectItem.top+1, ETO_CLIPPED | ETO_OPAQUE, &lpDIS->rcItem,
pData, strlen(pData), NULL);
if( bDrawSeparator ){
// Draw solid line as separator
pDC->MoveTo(rectItem.left, rectItem.bottom-1);
pDC->LineTo(rectItem.right, rectItem.bottom-1);
}
pDC->SelectObject(pOldPen);
}
}
int CNSComboBox::CompareItem(LPCOMPAREITEMSTRUCT lpCIS)
{
// We should never sort!
return 0;
}
// These were initially in CEditFrame:
BEGIN_MESSAGE_MAP(CNSComboBox, CComboBox)
//{{AFX_MSG_MAP(CNSComboBox)
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CNSComboBox::InitSearch()
{
// Don't allow autoselect while typing
// when we have a multibyte system
if( !GetSystemMetrics(SM_DBCSENABLED) ){
m_bAllowSearch = TRUE;
m_iSearchPos = 0;
m_pSearchBuf[m_iSearchPos] = '\0';
}
}
void CNSComboBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
BOOL bMatch;
// Ignor shift and control presses
if( m_bAllowSearch && nChar != VK_SHIFT && nChar != VK_CONTROL ){
if( nChar != VK_RETURN &&
(nChar == 4 || XP_IS_ALPHA(nChar) ||
XP_IS_DIGIT(nChar) || XP_IS_SPACE(nChar)) )
{
int iStart = 0;
if( nChar == VK_BACK ){
// Backup/delete key in buffer
if( m_iSearchPos > 0 ){
m_iSearchPos--;
}
} else {
// Append acceptable character to search buffer
m_pSearchBuf[m_iSearchPos] = nChar;
if( m_iSearchPos ){
// Start search from current item if we already had a string,
iStart = GetCurSel();
}
m_iSearchPos++;
}
m_pSearchBuf[m_iSearchPos] = '\0';
for( int i = iStart; i < GetCount(); i++ )
{
char * pItem = (char*)GetItemData(i);
if( *pItem == '_' ){
pItem++;
}
if( strlen(pItem) >= (size_t)m_iSearchPos ){
// Current item is at least as long, so compare
//
char save = pItem[m_iSearchPos];
pItem[m_iSearchPos] = '\0';
bMatch = ( 0 == stricmp(pItem, m_pSearchBuf) );
// Restore
pItem[m_iSearchPos] = save;
if( bMatch ){
// We found it - set selection
SetCurSel(i);
break;
}
}
}
if( !bMatch ){
// We didn't find next char, so backup
m_iSearchPos--;
m_pSearchBuf[m_iSearchPos] = '\0';
}
} else {
// Another other key resets the search string
m_iSearchPos = 0;
m_pSearchBuf[m_iSearchPos] = '\0';
}
}
CComboBox::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CNSComboBox::PreTranslateMessage(MSG* pMsg)
{
return CComboBox::PreTranslateMessage(pMsg);
}
/////////////////////////////////////////////////////////////////////////////
// Custom Combobox - containing colors
CColorComboBox::CColorComboBox() :
m_crColor(MIXED_COLORREF),
m_bCustomColor(0),
m_bMixedColors(0),
m_hPal(0),
m_pParent(0)
{
}
BEGIN_MESSAGE_MAP(CColorComboBox, CComboBox)
//{{AFX_MSG_MAP(CColorComboBox)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CColorComboBox::OnLButtonDown(UINT nFlags, CPoint cPoint)
{
if( m_pParent ){
// Send message to parent to do the Color Dialog
m_pParent->SendMessage(WM_COMMAND, ID_GET_COLOR, 0);
}
}
void CColorComboBox::OnLButtonUp(UINT nFlags, CPoint cPoint)
{
}
void CColorComboBox::OnLButtonDblClk(UINT nFlags, CPoint cPoint)
{
if( m_pParent ){
// Send message to parent to do the Color Dialog
m_pParent->SendMessage(WM_COMMAND, ID_GET_COLOR, 0);
}
}
int CColorComboBox::SubclassAndFill(CWnd* pParentWnd, UINT nID, COLORREF crDefColor)
{
m_pParent = pParentWnd;
if( SubclassDlgItem(nID, pParentWnd) ){
return FillList(crDefColor);
}
return 0;
}
BOOL CColorComboBox::CreateAndFill(RECT& rect, CWnd* pParentWnd, UINT nID, COLORREF crDefColor)
{
m_pParent = pParentWnd;
if( !Create(CBS_DROPDOWNLIST|CBS_OWNERDRAWFIXED|WS_VISIBLE|WS_TABSTOP|WS_VSCROLL,
rect, pParentWnd, nID) ){
TRACE0("Failed to create Font Color combo-box\n");
return FALSE;
}
if( wfe_pFont ){
SetFont(wfe_pFont);
}
return FillList(crDefColor);
}
int CColorComboBox::FillList(COLORREF crDefColor)
{
CDC * pDC = GetDC();
if( !pDC ) return 0;
m_hPal = WFE_GetUIPalette(GetParentFrame());
// WE NO LONGER FILL THE LIST - POPUP IS USED INSTEAD
ReleaseDC(pDC);
return TRUE;
}
void CColorComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
// all items are of fixed size
lpMIS->itemHeight = wfe_iListItemHeight;
}
void CColorComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
// We need to draw outside the supplied area,
// so use main combobox DC
HDC hDC = GetDC()->m_hDC;
HPALETTE hOldPal = NULL;
if( m_hPal )
{
hOldPal = ::SelectPalette( hDC, m_hPal, FALSE );
}
RECT rect = lpDIS->rcItem;
::InflateRect(&rect, 1, 1);
// Draw color sample
if (lpDIS->itemAction & ODA_DRAWENTIRE)
{
if( m_bMixedColors )
{
rect.top--;
rect.left--;
//rect.bottom++;
::FillRect(hDC, &rect, sysInfo.m_hbrBtnFace);
if( sysInfo.m_bWin4 )
{
// It looks very odd unless we add a line to close off button
HPEN penShadow = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnShadow);
HPEN hPenOld = (HPEN)::SelectObject(hDC, penShadow);
::MoveToEx(hDC, rect.right, rect.top, NULL);
::LineTo(hDC, rect.right, rect.bottom);
::SelectObject(hDC, hPenOld);
::DeleteObject(penShadow);
}
} else {
HBRUSH hBrush = ::CreateSolidBrush(m_crColor|0x02000000); // Like PALETTERGB
::FillRect(hDC, &rect, hBrush);
::DeleteObject(hBrush);
int32 iColorTotal = GetRValue(m_crColor) + GetGValue(m_crColor) + GetBValue(m_crColor);
COLORREF crColorHighlight = 0;
if( iColorTotal < 153 )
crColorHighlight = PALETTERGB(255,255,0);
else if( iColorTotal > 700 )
crColorHighlight = PALETTERGB(0,0,255);
if( sysInfo.m_bWin4 )
{
// Extra color highlight if color is too dark or light
if( crColorHighlight )
{
hBrush = ::CreateSolidBrush(crColorHighlight);
::FrameRect(hDC, &rect, hBrush);
::DeleteObject(hBrush);
}
} else {
// Older UIs have a flat-look for comboboxes,
// and need an extra border here
// And we use color if current color is too dark or bright
if( crColorHighlight )
{
hBrush = ::CreateSolidBrush(crColorHighlight);
} else {
hBrush = (HBRUSH)::GetStockObject(BLACK_BRUSH);
}
::FrameRect(hDC, &rect, hBrush);
if( crColorHighlight )
::DeleteObject(hBrush);
}
}
}
if(m_hPal)
{
::SelectPalette( hDC, hOldPal, FALSE );
}
::ReleaseDC(this->m_hWnd, hDC);
}
int CColorComboBox::CompareItem(LPCOMPAREITEMSTRUCT lpCIS)
{
// We should never sort!
return 0;
}
int CColorComboBox::SetColor(COLORREF cr)
{
int iIndex = -1;
if( cr == MIXED_COLORREF )
{
m_crColor = RGB(255,255,255);
}else if( cr == DEFAULT_COLORREF )
{
m_crColor = prefInfo.m_rgbForegroundColor;
iIndex = 0;
} else {
m_crColor = cr;
LO_Color LoColor;
LoColor.red = GetRValue(cr);
LoColor.green = GetGValue(cr);
LoColor.blue = GetBValue(cr);
iIndex = EDT_GetMatchingFontColorIndex(&LoColor);
}
m_bMixedColors = (cr == MIXED_COLORREF);
// Custom color is one not in our list
m_bCustomColor = !m_bMixedColors && iIndex == -1;
Invalidate(FALSE);
SetCurSel(iIndex);
return iIndex;
}
#define COLOR_ROWS 7
#define COLOR_COLS 10
// NOTE: This is same as the wfe_iFontHeight found for
// our 8-pt Sans Serif font (wfe_pFont)
// This might be a problem for some Asian fonts if they are taller?
#define COLOR_SWATCH_HEIGHT 16
#define COLOR_SWATCH_WIDTH 18
#define COLOR_SWATCH_SPACING 0
#define MAIN_COLORS_TOP (2*COLOR_SWATCH_HEIGHT + 4)
#define LAST_COLOR_TOP (COLOR_SWATCH_HEIGHT + 4)
#define COLOR_PICKER_HEIGHT (((COLOR_ROWS + 7)*COLOR_SWATCH_HEIGHT) + 26)
#define COLOR_PICKER_WIDTH (COLOR_COLS*COLOR_SWATCH_WIDTH + 7)
#define BUTTON_WIDTH (4*COLOR_SWATCH_WIDTH - 4)
// Index to the first USER custom color, which follows the Netscape colors
// (first custom color, the "last-used" is actually 0 in color array)
// Add 1 for the Last-Used color swatch above main color grid
// and another for the "Current color" swatch above quick palette
#define FIRST_CUSTOM_COLOR_INDEX (MAX_NS_COLORS + 2)
////////////////////////////////////////////////////////////////////////////////////////////
// CColorPicker Widget for picking colors
// We can't use Pretranslate or SetCapture under Win16,
// so we must derive from CWnd, not CDialog
IMPLEMENT_DYNAMIC(CColorPicker,CWnd);
CColorPicker::CColorPicker(CWnd * pParent,
MWContext * pMWContext,
COLORREF crCurrentColor,
COLORREF crDefColor,
UINT nIDCaption,
RECT * pCallerRect)
: CWnd(),
m_pParent(pParent),
m_pMWContext(pMWContext),
m_crCurrentColor(crCurrentColor),
m_crDefColor(crDefColor),
m_nIDCaption(nIDCaption),
m_pToolTip(0),
m_bOtherDown(0),
m_bAutoDown(0),
m_bHelpDown(0),
m_bRunning(TRUE),
m_bFirstMouseUp(TRUE),
m_bMouseDown(FALSE),
m_crDragColor(0)
{
// Caption choices are: "Text Color",
// or "[Page | Table | Cell] Background"
m_bBackground = (nIDCaption != IDS_TEXT_COLOR);
POINT ptOrigin;
if( pCallerRect )
{
m_CallerRect = *pCallerRect;
} else {
m_CallerRect.left = m_CallerRect.right = m_CallerRect.top = m_CallerRect.bottom = 0;
}
m_LoColor.red = m_LoColor.green = m_LoColor.blue = 0;
// If current is DEFAULT (i.e. "Automatic"), get appropriate default color
if( m_crCurrentColor == DEFAULT_COLORREF )
{
if( crDefColor == DEFAULT_COLORREF || crDefColor == MIXED_COLORREF )
{
// Get the "Default" color used by the Browser
m_crCurrentColor = prefInfo.m_rgbForegroundColor;
} else if( crDefColor == BACKGROUND_COLORREF )
{
// Get current page's background color
// as "default" for table backgrounds
CDCCX *pDC = VOID2CX(pMWContext->fe.cx, CDCCX);
m_crCurrentColor = pDC->m_rgbBackgroundColor;
} else
{
// Use the default color supplied
m_crCurrentColor = crDefColor;
}
}
if( m_CallerRect.left == 0 && m_CallerRect.top == 0 )
{
// No caller rect supplied - locate top at cursor Y and
// X so cursor pt. is at horizontal center
GetCursorPos(&ptOrigin);
ptOrigin.x -= (ED_TB_BUTTON_WIDTH / 2);
} else {
// The -1 lines up light highlight with that of parent
ptOrigin.x = m_CallerRect.left - 1;
// We may change this below if near bottom of screen
ptOrigin.y = m_CallerRect.bottom;
}
if (!CWnd::CreateEx(WS_EX_TOPMOST,
AfxRegisterWndClass(CS_SAVEBITS | CS_VREDRAW,
::LoadCursor( NULL, IDC_ARROW),
sysInfo.m_hbrBtnFace),
NULL, WS_POPUP /*| WS_VISIBLE*/ | WS_DLGFRAME,
ptOrigin.x, ptOrigin.y,
COLOR_PICKER_WIDTH, COLOR_PICKER_HEIGHT,
pParent->m_hWnd, NULL, NULL))
{
TRACE0("Warning: creation of CColorPicker window failed\n");
return;
}
SetFont(wfe_pFont);
// Add a tooltip control
m_pToolTip = new CNSToolTip2;
if(m_pToolTip && !m_pToolTip->Create(this, TTS_ALWAYSTIP) )
{
TRACE("Unable To create ToolTip\n");
delete m_pToolTip;
m_pToolTip = NULL;
} else {
// Lets use speedy tooltips
m_pToolTip->SetDelayTime(200);
#ifdef XP_WIN32
// We MUST do this for MFC tooltips
EnableToolTips(TRUE);
#endif // WIN32
}
int iTop = 2;
int iCustomTop;
int iLeft = 4;
int iCol = 0;
int iRow = 0;
int iRowLimit = COLOR_ROWS - 1; // Doesn't include custom colors
//int iXPOffset = 0;
int iCustomColor = 0; // Counter for custom colors
RECT rectOther; // For the "Other..." button
RECT rect;
RECT rectLabel;
char *pLabel; // Holds static pointer for szLoadString (dont free)
for( int i = 0; i < MAX_COLORS; i++ )
{
LO_Color LoColor;
if( i > 0 && i <= MAX_NS_COLORS ) // in main color grid
{
// Reset to first column
if( i == 1 )
{
iCol = 0;
}
// Set top to be used for all colors in main region
iTop = MAIN_COLORS_TOP;
EDT_GetNSColor(i-1, &LoColor);
m_crColors[i] = RGB(LoColor.red, LoColor.green, LoColor.blue);
}
else
{
if( i == 0 )
{
// The first swatch is the "last-picked" color
if( m_bBackground )
m_crColors[i] = wfe_crLastBkgrndColorPicked;
else
m_crColors[i] = wfe_crLastColorPicked;
// "Last-picked color" at left margin, below caption area
pLabel = szLoadString(IDS_LAST_USED_COLOR);
rectLabel.top = LAST_COLOR_TOP+2;
rectLabel.left = COLOR_SWATCH_WIDTH + 2;
rectLabel.right = COLOR_PICKER_WIDTH;
rectLabel. bottom = rectLabel.top + COLOR_SWATCH_HEIGHT;
if( !m_LastUsedLabel.Create(pLabel, WS_VISIBLE | WS_CHILD, rectLabel, this) )
return;
// Set the top of the color swatch
iTop = LAST_COLOR_TOP;
}
else if( i == MAX_NS_COLORS+1 ) // Should = FIRST_CUSTOM_COLOR_INDEX-1
{
// Current color swatch just below the main colors
m_crColors[i] = m_crCurrentColor;
// Set text label next to this color swatch
pLabel = szLoadString(IDS_CURRENT_COLOR);
iTop = MAIN_COLORS_TOP + (COLOR_ROWS * COLOR_SWATCH_HEIGHT) + 2;
rectLabel.top = iTop + 1;
rectLabel.left = COLOR_SWATCH_WIDTH + 2;
rectLabel.right = COLOR_PICKER_WIDTH - 6 - BUTTON_WIDTH;
rectLabel. bottom = rectLabel.top + COLOR_SWATCH_HEIGHT;
if( !m_CurrentLabel.Create(pLabel, WS_VISIBLE | WS_CHILD, rectLabel, this) )
return;
iCol = 0;
iRow = 0;
}
else if( i >= FIRST_CUSTOM_COLOR_INDEX )
{
// Get custom colors from global palette
m_crColors[i] = wfe_CustomPalette[iCustomColor++];
if( i == FIRST_CUSTOM_COLOR_INDEX )
{
// Add the "Automatic" button ( = "Default", i.e., no color in HTML)
// at the same vertical location as "Current color" swatch
// (Must create here to get tab order correct)
rectOther.top = iTop + 2;
rectOther.bottom = rectOther.top + 22;
rectOther.right = COLOR_PICKER_WIDTH - 8;
rectOther.left = rectOther.right - BUTTON_WIDTH;
m_OtherButton.Create(szLoadString(IDS_OTHER_BUTTON), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
rectOther, this, IDC_CHOOSE_COLOR);
// TODO: ADD A TOOLTIP FOR "AUTO" BUTTON for added instructions?
// Label above custom colors:
pLabel = szLoadString(IDS_CUSTOM_COLORS_LABEL);
rectLabel.left = 2;
rectLabel.right = rectOther.left - 1;
rectLabel.top = iTop + COLOR_SWATCH_HEIGHT + 2;
// We cut 2 pixels off font height for tighter fit (TODO: PROBLEM IN OTHER LANGUAGES?)
rectLabel.bottom = rectLabel.top + wfe_iFontHeight - 2;
if( !m_CustomColorsLabel.Create(pLabel, WS_VISIBLE | WS_CHILD, rectLabel, this) )
return;
// Top of custom colors row - place just below label
iTop = iCustomTop = rectLabel.bottom;
iCol = 0;
iRow = 0;
}
}
LoColor.red = GetRValue(m_crColors[i]);
LoColor.green = GetGValue(m_crColors[i]);
LoColor.blue = GetBValue(m_crColors[i]);
}
rect.left = iCol*COLOR_SWATCH_WIDTH;
rect.top = iTop + (iRow*COLOR_SWATCH_HEIGHT);
rect.right = rect.left + COLOR_SWATCH_WIDTH;
rect.bottom = rect.top + COLOR_SWATCH_HEIGHT;
// Create our custom buttons
m_pColorButtons[i] = new CColorButton(&m_crColors[i], &m_crColor);
if( !m_pColorButtons[i] ||
!m_pColorButtons[i]->Create(rect, this, IDC_LAST_USED_COLOR+i, &m_crColors[i], TRUE) )
{
return;
}
// Add tooltip showing color formated as "R=xxx G=xxx B=xxx HTML: #FFEEAA"
if( m_pToolTip )
{
if( m_crColors[i] == DEFAULT_COLORREF )
{
*m_ppTipText[i] = 0;
} else
{
wsprintf(m_ppTipText[i], szLoadString(IDS_COLOR_TIP_FORMAT),
LoColor.red, LoColor.green, LoColor.blue);
strcat(m_ppTipText[i], szLoadString(IDS_COLOR_TIP_HTML));
char * pEnd = m_ppTipText[i] + strlen(m_ppTipText[i]);
sprintf(pEnd, "#%02X%02X%02X",LoColor.red, LoColor.green, LoColor.blue);
m_pToolTip->AddTool(m_pColorButtons[i], m_ppTipText[i], &rect, IDC_LAST_USED_COLOR+i);
}
}
if( i >= FIRST_CUSTOM_COLOR_INDEX )
{
// We are within single custom color row
iCol++;
}
else if( i > 0 )
{
// Main color grid
// Add each button in columns first, add new column after every 7
if(iRow < iRowLimit)
{
iRow++;
} else {
iRow = 0;
iCol++;
}
}
}
// Add Number strings under custom color swatches
rect.left = 6;
rect.top = iCustomTop + COLOR_SWATCH_HEIGHT;
rect.bottom = rect.top + COLOR_SWATCH_HEIGHT;
for( i = 0; i < MAX_CUSTOM_COLORS; i++ )
{
rect.right = rect.left + COLOR_SWATCH_WIDTH;
char pNumber[16];
wsprintf(pNumber, "%d", (i < MAX_CUSTOM_COLORS-1) ? i+1 : 0);
if( !m_CustomColorNumber[i].Create(pNumber, WS_VISIBLE | WS_CHILD, rect, this) )
return;
// Move to next location
rect.left += COLOR_SWATCH_WIDTH;
}
// Place "Browser default" button in lower left corner:
rect.top = rect.bottom;
rect.bottom = rect.top + 22;
rect.left = 2;
rect.right = rect.left + BUTTON_WIDTH + 2*COLOR_SWATCH_WIDTH; // BUTTON_WIDTH
m_DefaultButton.Create(szLoadString(IDS_DEFAULT_BUTTON), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
rect, this, IDC_DEFAULT_COLOR);
// Now we can determine bottom of entire window
// Number added to this must be enough for 2 lines of text (this is now 30)
// This is weird, but adding about 4 results in same place as "Other" button button,
// seems like button is larger than 24???
int iTotalHeight = rect.bottom + 8;
// Place "Help" color button in lower right corner:
rect.right = COLOR_PICKER_WIDTH - 8;
rect.left = rect.right - BUTTON_WIDTH;
// NOTE: IDS_HELP_BUTTON string is in Browser resources
m_HelpButton.Create(szLoadString(IDS_HELP_BUTTON), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
rect, this, IDC_COLOR_HELP);
// Set our font for all static strings used
if( wfe_pFont )
{
// Set the font to our usual 8-pt font
m_OtherButton.SetFont(wfe_pFont);
m_HelpButton.SetFont(wfe_pFont);
m_LastUsedLabel.SetFont(wfe_pFont);
m_CurrentLabel.SetFont(wfe_pFont);
m_DefaultButton.SetFont(wfe_pFont);
m_CustomColorsLabel.SetFont(wfe_pFont);
for( int i = 0; i < MAX_CUSTOM_COLORS; i++ )
{
m_CustomColorNumber[i].SetFont(wfe_pFont);
}
}
// Check if we need to move up because we would go off the screen
if( (m_CallerRect.bottom + iTotalHeight) > sysInfo.m_iScreenHeight )
{
// Locate toolbar above the caller button
// if toolbar bottom would extend off bottom of screen
ptOrigin.y = m_CallerRect.top - iTotalHeight;
}
// Move and/or resize the window and show it for the first time
SetWindowPos(NULL, ptOrigin.x, ptOrigin.y, COLOR_PICKER_WIDTH, iTotalHeight, SWP_SHOWWINDOW );
// Capture mouse so we can detect clicking off the dialog
SetCapture();
// Snap focus to the first button
// Needed to allow Esc key to work
// after click down/up on the control that launched us
m_pColorButtons[0]->SetFocus();
m_crColor = m_crColors[0];
// Initialize the array of flags for Quick Palette
for ( i = 0; i < MAX_CUSTOM_COLORS; i++ )
m_bColorChanged[i] = FALSE;
}
void CColorPicker::OnPaint()
{
CPaintDC dc(this);
// Draw the caption text
int iRight = COLOR_PICKER_WIDTH-8;
CRect cRect(2,2,iRight-1, COLOR_SWATCH_HEIGHT);
dc.SetBkMode(TRANSPARENT);
dc.SetTextColor(sysInfo.m_clrBtnText);
CFont *pOldFont = dc.SelectObject(wfe_pFont);
CString cString(szLoadString(m_nIDCaption));
dc.DrawText(cString, cRect, DT_CENTER);
dc.SelectObject(pOldFont);
// Draw a depressed rect around caption
// This doesn't draw very well - it uses right-1 and bottom-1,
// and the lower-left corner doesn't look good
// WFE_DrawHighlight( dc.m_hDC, LPRECT(cRect), sysInfo.m_clrBtnShadow, sysInfo.m_clrBtnHilite );
CPen cPenShadow(PS_SOLID, 1, sysInfo.m_clrBtnShadow);
CPen cPenHilite(PS_SOLID, 1, sysInfo.m_clrBtnHilite);
CPen *pPenOld = (CPen*)dc.SelectObject(&cPenShadow);
int iBottom = COLOR_SWATCH_HEIGHT+ (wfe_iFontHeight > 16 ? 2: 1);
dc.MoveTo(1,iBottom);
dc.LineTo(1,1);
dc.LineTo(iRight,1);
dc.SelectObject(&cPenHilite);
dc.LineTo(iRight,iBottom);
dc.LineTo(1,iBottom);
dc.SelectObject(pPenOld);
}
COLORREF crReturnColor;
// Call this instead of DoModal() to wait in dialog and get result
COLORREF CColorPicker::GetColor(LO_Color * pLoColor)
{
// Wait here until user selects a color or
// cancels the dialog with ESC or by clicking outside window
while( m_bRunning ) FEU_StayingAlive();
// Return selected or custom color
if( pLoColor )
{
pLoColor->red = m_LoColor.red;
pLoColor->green = m_LoColor.green;
pLoColor->blue = m_LoColor.blue;
}
crReturnColor = m_crColor;
DestroyWindow();
return crReturnColor;
}
void CColorPicker::SetColorAndExit()
{
if( m_crColor != DEFAULT_COLORREF )
{
m_LoColor.red = GetRValue(m_crColor);
m_LoColor.green = GetGValue(m_crColor);
m_LoColor.blue = GetBValue(m_crColor);
}
// Set flag that will let us return to caller and destroy dialog
m_bRunning = FALSE;
}
void CColorPicker::CancelAndExit()
{
m_crColor = CANCEL_COLORREF;
m_bRunning = FALSE;
}
CColorPicker::~CColorPicker()
{
}
void CColorPicker::PostNcDestroy()
{
char pPref[32];
char pColorString[32];
// Save the last-picked color to appropriate pref
if( m_bBackground )
{
wsprintf(pColorString, "%d,%d,%d", GetRValue(wfe_crLastBkgrndColorPicked), GetGValue(wfe_crLastBkgrndColorPicked), GetBValue(wfe_crLastBkgrndColorPicked));
PREF_SetCharPref("editor.last_background_color_picked", pColorString);
} else {
wsprintf(pColorString, "%d,%d,%d", GetRValue(wfe_crLastColorPicked), GetGValue(wfe_crLastColorPicked), GetBValue(wfe_crLastColorPicked));
PREF_SetCharPref("editor.last_color_picked", pColorString);
}
// Save custom colors back to prefs
for ( int i = 0; i < MAX_CUSTOM_COLORS; i++ )
{
// Write new pref only if different than original value
if( m_bColorChanged[i] )
{
COLORREF crColor = wfe_CustomPalette[i]; // should = m_crColors[iColorIndex];
wsprintf(pColorString, "%d,%d,%d", GetRValue(crColor), GetGValue(crColor), GetBValue(crColor));
wsprintf(pPref, "editor.custom_color_%d", i);
PREF_SetCharPref(pPref, pColorString);
}
}
if( m_pToolTip )
delete m_pToolTip;
ReleaseCapture();
CWnd::PostNcDestroy();
}
BEGIN_MESSAGE_MAP(CColorPicker, CWnd)
//{{AFX_MSG_MAP(CColorPicker)
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_PAINT()
//}}AFX_MSG_MAP
#ifdef XP_WIN32
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
#endif
END_MESSAGE_MAP()
BOOL CColorPicker::PreTranslateMessage(MSG* pMsg)
{
if( m_pToolTip && pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
{
m_pToolTip->RelayEvent(pMsg);
}
if( pMsg->message == WM_KEYDOWN )
{
if( pMsg->wParam == VK_ESCAPE )
{
CancelAndExit();
}
else if( pMsg->wParam == VK_RETURN )
{
SetColorAndExit();
}
else if( pMsg->wParam == VK_F1 )
{
OnColorHelp();
}
else
{
// Are any number keys pressed?
// This is 1 less than number on key pressed
int iNumberIndex = pMsg->wParam - '1';
// "0" key is AFTER "9" on keyboard
// so treat it like a 10th color
if( iNumberIndex == -1 )
iNumberIndex = 9;
if( iNumberIndex >= 0 && iNumberIndex <= 9 ) // This won't work if MAX_CUSTOM_COLORS > 10
{
// Set the current focus color at the custom color matching number
m_crColors[FIRST_CUSTOM_COLOR_INDEX+iNumberIndex] = m_crColor;
m_pColorButtons[FIRST_CUSTOM_COLOR_INDEX+iNumberIndex]->Invalidate(FALSE);
}
}
}
return CWnd::PreTranslateMessage(pMsg);
}
BOOL CColorPicker::IsMouseOverDlg(CPoint cPoint)
{
CRect cRect;
GetWindowRect(&cRect);
ScreenToClient(&cRect);
return cRect.PtInRect(cPoint);
}
BOOL CColorPicker::IsMouseOverButton(CPoint cPoint, UINT nID)
{
CRect cRect;
((CButton*)GetDlgItem(nID))->GetWindowRect(&cRect);
ScreenToClient(&cRect);
return cRect.PtInRect(cPoint);
}
int CColorPicker::GetMouseOverColorIndex(CPoint cPoint)
{
CRect cRect;
for( int i = 0; i < MAX_COLORS; i++){
GetDlgItem(IDC_LAST_USED_COLOR+i)->GetWindowRect(&cRect);
ScreenToClient(&cRect);
if( cRect.PtInRect(cPoint) ){
// Select the color and return the index
// unless it is "default" (unknown)
if( m_crColors[i] != DEFAULT_COLORREF )
{
m_crColor = m_crColors[i];
return i;
}
}
}
return -1;
}
void CColorPicker::OnLButtonDown(UINT nFlags, CPoint cPoint)
{
POINT pt = {cPoint.x,cPoint.y};
// If user clicks outside of dialog, we are done
if( !IsMouseOverDlg(cPoint) ){
CancelAndExit();
return;
}
if( IsMouseOverButton(cPoint, IDC_CHOOSE_COLOR) && !m_bOtherDown ){
m_bOtherDown = TRUE;
((CButton*)GetDlgItem(IDC_CHOOSE_COLOR))->SetState(TRUE);
} else if( IsMouseOverButton(cPoint, IDC_DEFAULT_COLOR) && !m_bAutoDown ){
m_bAutoDown = TRUE;
((CButton*)GetDlgItem(IDC_DEFAULT_COLOR))->SetState(TRUE);
} else if( IsMouseOverButton(cPoint, IDC_COLOR_HELP) && !m_bHelpDown ){
m_bHelpDown = TRUE;
((CButton*)GetDlgItem(IDC_COLOR_HELP))->SetState(TRUE);
}
// Copy color for possible dragging
int i = GetMouseOverColorIndex(cPoint);
if( i >= 0 ){
m_crDragColor = m_crColors[i];
m_bMouseDown = TRUE;
m_iMouseDownColorIndex = i;
SetCursor(theApp.LoadCursor(IDC_DRAG_COLOR));
}
CWnd::OnLButtonDown(nFlags, cPoint);
}
void CColorPicker::OnLButtonUp(UINT nFlags, CPoint cPoint)
{
// Simulate how a combobox widget works,
// quit if mouse up is off the window, except if it comes up
// over the control that launched us
if( !IsMouseOverDlg(cPoint) )
{
// But check if over the caller rect
CRect cRect(m_CallerRect);
ScreenToClient(&cRect);
if( !cRect.PtInRect(cPoint) )
{
CancelAndExit();
return;
}
// Mouse came up over the caller control,
// so default to last color used
m_crColor = m_crColors[0];
} else {
// Detect mouse up on a color swatch select it
// or drop copied color
int i = GetMouseOverColorIndex(cPoint);
// Ignore first mouse up on current color
if( i == 0 && m_bFirstMouseUp )
return;
m_bFirstMouseUp = FALSE;
if( i >= 0 )
{
if( m_bMouseDown && i >= FIRST_CUSTOM_COLOR_INDEX &&
m_iMouseDownColorIndex != i) // TRUE when click down/up to select quick color
{
// We are dropping a color onto custom palette
m_crColors[i] = m_crDragColor;
int iCustomIndex = i - FIRST_CUSTOM_COLOR_INDEX;
wfe_CustomPalette[iCustomIndex] = m_crDragColor;
m_bColorChanged[iCustomIndex] = TRUE;
// Force redraw
m_pColorButtons[i]->Invalidate(FALSE);
} else if( !m_bMouseDown || m_iMouseDownColorIndex == i )
{
// Button came up in same color as mouse down,
// or up when not dragging is not possible
// because mouse was already down when picker started
m_crColor = m_crColors[i];
// Always save selected color as the "last color picked"
if( m_bBackground )
wfe_crLastBkgrndColorPicked = m_crColor;
else
wfe_crLastColorPicked = m_crColor;
SetColorAndExit();
return;
}
// We dropped color or didn't select,
// but we must be over a color swatch,
// so set appropriate cursor
SetCursor(theApp.LoadCursor(IDC_DRAG_ARROW));
}
if( IsMouseOverButton(cPoint, IDC_CHOOSE_COLOR) )
{
OnChooseColor();
return;
}
if( IsMouseOverButton(cPoint, IDC_DEFAULT_COLOR) )
{
OnDefaultColor();
return;
}
if( IsMouseOverButton(cPoint, IDC_COLOR_HELP) )
{
((CButton*)GetDlgItem(IDC_COLOR_HELP))->SetState(FALSE);
m_bHelpDown = FALSE;
OnColorHelp();
}
}
m_bMouseDown = FALSE;
CWnd::OnLButtonUp(nFlags, cPoint);
}
void CColorPicker::SetButtonState(CPoint cPoint, UINT nID, BOOL* pButtonDown )
{
BOOL bOverButton = IsMouseOverButton(cPoint, nID);
if( !bOverButton && *pButtonDown)
{
// Deselect button when mouse moves off
*pButtonDown = FALSE;
((CButton*)GetDlgItem(nID))->SetState(FALSE);
} else if( bOverButton && !*pButtonDown /*&& (nFlags & MK_LBUTTON)*/ )
{
*pButtonDown = TRUE;
((CButton*)GetDlgItem(nID))->SetState(TRUE);
}
}
void CColorPicker::OnMouseMove(UINT nFlags, CPoint cPoint)
{
int i = GetMouseOverColorIndex(cPoint);
if( i != 0 )
{
// If not over Current Color button,
// kill ignore-on-first-mouseup behavior
m_bFirstMouseUp = FALSE;
}
// Set button shade state to act like normal dialog button
// when mouse is held down
if( nFlags & MK_LBUTTON )
{
SetButtonState(cPoint, IDC_CHOOSE_COLOR, &m_bOtherDown);
SetButtonState(cPoint, IDC_DEFAULT_COLOR, &m_bAutoDown);
SetButtonState(cPoint, IDC_COLOR_HELP, &m_bHelpDown);
}
if( m_bMouseDown )
{
// Give user feedback via cursor
UINT nIDC;
if( m_iMouseDownColorIndex == i )
// Over source swatch - NULL icon is confusing - show arrow + color box
nIDC = IDC_DRAG_COLOR;
else if( i >= FIRST_CUSTOM_COLOR_INDEX )
// Over drop target
nIDC = IDC_DROP_COLOR;
else
// Over anything else - can't drop
nIDC = IDC_NO_DROP;
SetCursor(theApp.LoadCursor(nIDC));
} else {
if( i >= 0 )
{
// Tells user they can drag a color
SetCursor(theApp.LoadCursor(IDC_DRAG_ARROW));
if( GetFocus() != m_pColorButtons[i] )
{
// Bring focus to color where mouse is
m_pColorButtons[i]->SetFocus();
m_crColor = m_crColors[i];
}
}
else
{
// Not over color or dragging - regular cursor
SetCursor(theApp.LoadStandardCursor(IDC_ARROW));
}
}
CWnd::OnMouseMove(nFlags, cPoint);
}
//
#ifdef XP_WIN32
// This is needed for non-CFrame owners of a CToolTipCtrl
BOOL CColorPicker::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID =pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if( nID ) {
int i = nID - IDC_LAST_USED_COLOR;
if( i >= 0 && i < MAX_COLORS && m_ppTipText[i] ){
// Copy string into buffer - limit is 80 characters
strcpy( pTTT->szText, m_ppTipText[i]);
return(TRUE);
}
}
}
return(FALSE);
}
#endif
void CColorPicker::OnDefaultColor()
{
m_crColor = DEFAULT_COLORREF;
SetColorAndExit();
}
// Select any color via Window's color dialog
void CColorPicker::OnChooseColor()
{
// Use CC_PREVENTFULLOPEN in flags (2nd) param if we want to suppress editing
CColorDialog dlg(wfe_CustomPalette[0], CC_FULLOPEN, this);
// Place our current palette into the 16 Custom colors
// Copy colors so we don't change anything if
COLORREF crCustomColors[16];
memcpy((void*)crCustomColors, (void*)wfe_CustomPalette, sizeof(crCustomColors));
dlg.m_cc.lpCustColors = crCustomColors;
dlg.m_cc.lStructSize = sizeof( dlg.m_cc );
// TODO: We need to make a derived class to control common dialog palette
// or do hook for WM_INTDIALOG in m_cc struct
// so we can set the palette of the Window's CColorDlg
UINT nResult = dlg.DoModal();
if( nResult == IDOK ){
m_crColor = dlg.GetColor();
// Save this color as last color picked
if( m_bBackground )
wfe_crLastBkgrndColorPicked = m_crColor;
else
wfe_crLastColorPicked = m_crColor;
// Set flags for colors that changed
for ( int i = 0; i < MAX_CUSTOM_COLORS; i++ )
{
if( wfe_CustomPalette[i] != crCustomColors[i] )
m_bColorChanged[i] = TRUE;
}
// Copy custom colors back to global palette
memcpy((void*)wfe_CustomPalette, (void*)crCustomColors, sizeof(crCustomColors));
SetColorAndExit();
} else {
CancelAndExit();
}
}
void CColorPicker::OnColorHelp()
{
NetHelp(HELP_COLOR_PICKER);
}
/////////////////////////////////////////////////////////////////////////////
// CDropdownToolbar Popup window with thin border to place a vertical row of buttons
CDropdownToolbar::CDropdownToolbar(CWnd * pParent,
MWContext * pMWContext,
RECT * pCallerRect,
UINT nCallerID,
UINT nInitialID)
: CWnd(),
m_pParent(pParent),
m_pMWContext(pMWContext),
m_nCallerID(nCallerID),
m_nInitialID(nInitialID),
m_nButtonCount(0),
m_nAllocatedCount(0),
m_pData(NULL),
m_pToolTip(0),
m_bFirstButtonUp(TRUE)
{
if( pCallerRect ){
m_CallerRect = *pCallerRect;
} else {
m_CallerRect.left = m_CallerRect.right = m_CallerRect.top = m_CallerRect.bottom = 0;
}
if (!CWnd::CreateEx(WS_EX_TOPMOST, AfxRegisterWndClass(CS_SAVEBITS | CS_VREDRAW, ::LoadCursor( NULL, IDC_ARROW)),
NULL, WS_POPUP | WS_BORDER /*|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS*/,
0, 0, 0, 0, pParent->m_hWnd, NULL, NULL))
{
TRACE0("Warning: creation of CDropdownToolbar window failed\n");
return;
}
// Add a tooltip control
m_pToolTip = new CNSToolTip2;
if(m_pToolTip && !m_pToolTip->Create(this, TTS_ALWAYSTIP) ){
TRACE("Unable To create ToolTip\n");
delete m_pToolTip;
m_pToolTip = NULL;
}
if( m_pToolTip ){
m_pToolTip->Activate(TRUE);
// Lets use speedy tooltips
m_pToolTip->SetDelayTime(50);
#ifdef XP_WIN32
// We MUST do this for MFC tooltips
EnableToolTips(TRUE);
#endif // WIN32
}
}
CDropdownToolbar::~CDropdownToolbar()
{
if( m_pData ){
for( UINT i = 0; i < m_nButtonCount; i++ ){
if( m_pData[i].pButton ){
if( m_pData[i].pButtonName ) XP_FREE((void*)m_pData[i].pButtonName);
delete m_pData[i].pButton;
}
}
XP_FREE( m_pData );
}
if( m_pToolTip ){
delete m_pToolTip;
}
}
void CDropdownToolbar::PostNcDestroy()
{
ReleaseCapture();
CWnd::PostNcDestroy();
delete this;
}
// Create a CBitmapPushButton - resource name should be correct form for
// a CBitmapButton: "Button_" will load "Button_D.BMP" and "Button_U.BMP"
// bitmap files for Down and Up button images.
BOOL CDropdownToolbar::AddButton(LPSTR pButtonName, UINT nCommandID)
{
ASSERT(pButtonName);
ASSERT(nCommandID);
if( m_nAllocatedCount < (m_nButtonCount + 1) ){
m_nAllocatedCount += 8;
m_pData = (DropdownToolbarData*)XP_REALLOC(m_pData,
m_nAllocatedCount * sizeof(DropdownToolbarData));
}
if( m_pData ){
DropdownToolbarData *pData = &m_pData[m_nButtonCount];
pData->pButton = new CBitmapPushButton(TRUE); // Use "borderless" button style
if( ! pData->pButton ){
TRACE0("Failed to allocated new button for DropdownToolbar\n");
return FALSE;
}
pData->nCommandID = nCommandID;
pData->nBitmapID = 0;
pData->pButtonName = XP_STRDUP(pButtonName);
} else {
TRACE0("Failed to reallocated new DropdownToolbar data\n");
return FALSE;
}
m_nButtonCount++;
return TRUE;
}
BOOL CDropdownToolbar::AddButton(UINT nBitmapID, UINT nCommandID)
{
ASSERT(nBitmapID);
ASSERT(nCommandID);
if( m_nAllocatedCount < (m_nButtonCount + 1) ){
m_nAllocatedCount += 8;
m_pData = (DropdownToolbarData*)XP_REALLOC(m_pData,
m_nAllocatedCount * sizeof(DropdownToolbarData));
}
if( m_pData ){
DropdownToolbarData *pData = &m_pData[m_nButtonCount];
pData->pButton = new CBitmapPushButton(TRUE); // Use "borderless" button style
if( ! pData->pButton ){
TRACE0("Failed to allocated new button for DropdownToolbar\n");
return FALSE;
}
pData->nCommandID = nCommandID;
pData->pButtonName = NULL;
pData->nBitmapID = nBitmapID;
} else {
TRACE0("Failed to reallocated new DropdownToolbar data\n");
return FALSE;
}
m_nButtonCount++;
return TRUE;
}
// Call this AFTER adding all buttons to toolbaar
void CDropdownToolbar::Show()
{
if( m_nButtonCount == 0 )
return;
// Full height of toolbar frame
int iHeight = (ED_TB_BUTTON_HEIGHT * m_nButtonCount) + 2;
POINT ptOrigin;
if( m_CallerRect.left == 0 && m_CallerRect.top == 0 ){
// No caller rect supplied - locate top at cursor Y and
// X so cursor pt. is at horizontal center
GetCursorPos(&ptOrigin);
ptOrigin.x -= (ED_TB_BUTTON_WIDTH / 2);
} else {
// Minus 1 for the 1-pixel dialog border around dropdown
// (makes dropdown look centered under caller button)
ptOrigin.x = m_CallerRect.left + ((m_CallerRect.right - m_CallerRect.left - ED_TB_BUTTON_WIDTH) / 2);
if( (m_CallerRect.bottom + iHeight) > sysInfo.m_iScreenHeight ){
// Locate toolbar above the caller button
// if toolbar bottom would extend off bottom of screen
ptOrigin.y = m_CallerRect.top - iHeight;
} else {
ptOrigin.y = m_CallerRect.bottom;
}
}
// Set location and size (fits tight around all buttons)
SetWindowPos( &wndTopMost, ptOrigin.x, ptOrigin.y,
ED_TB_BUTTON_WIDTH + 2, iHeight, SWP_NOACTIVATE );
// Convert caller rect to toolbar's coordinates
// to use for mouse hit testing
if( m_CallerRect.left != 0 && m_CallerRect.top != 0 ){
ScreenToClient(&m_CallerRect);
}
// Create all the buttons and load bitmaps etc
if( m_pData && m_nButtonCount > 0 ){
DropdownToolbarData *pData = m_pData;
RECT rect = {0, 0, ED_TB_BUTTON_WIDTH, ED_TB_BUTTON_HEIGHT-1};
for( UINT i = 0; i < m_nButtonCount; i++, pData++ ){
UINT nStyle = BS_PUSHBUTTON | BS_OWNERDRAW | WS_CHILD;
if( i == 0 ){
nStyle |= WS_GROUP | WS_TABSTOP;
}
rect.bottom++;
if( ! pData->pButton->Create(pData->pButtonName, nStyle,
rect, this, pData->nCommandID) ){
TRACE0("Failed to allocated new button in DropdownToolbar\n");
BUTTON_FAILED:
delete pData->pButton;
if( pData->pButtonName ) {
XP_FREE(pData->pButtonName);
pData->pButtonName = NULL;
}
pData->pButton = NULL;
CWnd::DestroyWindow();
return;
}
rect.bottom--;
if( pData->pButtonName) {
CString buttonName(pData->pButtonName);
if( ! pData->pButton->LoadBitmaps(buttonName + _T("U"),
buttonName + _T("D"), 0, 0) ){
TRACE0("Failed to load bitmaps for button in DropdownToolbar\n");
goto BUTTON_FAILED;
}
} else if( pData->nBitmapID ){
if( ! pData->pButton->LoadBitmap(pData->nBitmapID) ){
TRACE0("Failed to load bitmaps for button in DropdownToolbar\n");
goto BUTTON_FAILED;
}
} else {
TRACE0("No bitmap name or ID supplied for button in DropdownToolbar\n");
goto BUTTON_FAILED;
}
// Set pushed-down state for button if requested
if( m_nInitialID > 0 && pData->nCommandID == m_nInitialID ){
pData->pButton->SetCheck(TRUE);
}
pData->pButton->ShowWindow(SW_SHOW);
// Add tooltip for the button
if( m_pToolTip ){
#ifdef XP_WIN16
m_pToolTip->DelTool(pData->pButton->m_hWnd, pData->nCommandID);
#endif
m_pToolTip->AddTool(pData->pButton, pData->nCommandID,
&rect, pData->nCommandID);
}
// Move to next button down
rect.top += ED_TB_BUTTON_HEIGHT;
rect.bottom += ED_TB_BUTTON_HEIGHT;
}
if( m_pToolTip ){
m_pToolTip->Activate(TRUE);
}
}
ShowWindow(SW_SHOW);
// Grab the mouse so a click outside the dialog closes toolbar
SetCapture();
// Restore active caption highlighting to parent frame
GetParentFrame()->SetActiveWindow();
}
IMPLEMENT_DYNAMIC(CDropdownToolbar,CWnd)
BEGIN_MESSAGE_MAP(CDropdownToolbar, CWnd)
//{{AFX_MSG_MAP(CDropdownToolbar)
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
#ifdef XP_WIN32
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
#endif
END_MESSAGE_MAP()
BOOL CDropdownToolbar::PreTranslateMessage(MSG* pMsg)
{
if( m_pToolTip && pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
{
#ifdef XP_WIN32
// This is needed to get around an MFC bug
// where tooltip is disabled after Modal Dialog is called
m_pToolTip->Activate(TRUE);
#endif
m_pToolTip->RelayEvent(pMsg);
}
return CWnd::PreTranslateMessage(pMsg);
}
//
#ifdef XP_WIN32
// This is needed for non-CFrame owners of a CToolTipCtrl
BOOL CDropdownToolbar::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID =pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID) {
char * pTipText = FEU_GetToolTipText(nID);
if( pTipText ){
// Copy string into buffer - limit is 80 characters
// (use even number for foreign characters
strncpy( pTTT->szText, pTipText, 78);
// Just in case tip was longer than 78 characters!
pTTT->szText[79] = '\0';
return(TRUE);
}
}
}
return(FALSE);
}
#endif
void CDropdownToolbar::OnMouseMove(UINT nFlags, CPoint cPoint)
{
CWnd::OnMouseMove(nFlags, cPoint);
BOOL bStatusSet = FALSE;
char * szStatus;
POINT pt = {cPoint.x, cPoint.y};
if( m_pMWContext && m_nCallerID && m_CallerRect.top != 0 &&
::PtInRect(&m_CallerRect, pt) ){
szStatus = szLoadString(m_nCallerID);
if( szStatus ){
// Display status line help for caller button
// First strip tooltip
char * pEnter = strchr( szStatus, '\n');
if( pEnter ){
*pEnter = '\0';
}
wfe_Progress(m_pMWContext, szStatus);
// We can skip testing toolbar buttons if we are in caller
bStatusSet = TRUE;
}
}
// First button rect
RECT rect = {0, 0, ED_TB_BUTTON_WIDTH - 1,
ED_TB_BUTTON_HEIGHT - 1};
for( UINT i = 0; i < m_nButtonCount; i++ ){
BOOL bInButton = ::PtInRect(&rect, pt);
// Display status line help if within the toolbar
if( m_pMWContext && bInButton && !bStatusSet ){
szStatus = szLoadString(m_pData[i].nCommandID);
if( szStatus ){
// WACKY FEATURE: Look for accelerator, eg. (Ctrl+x)
// in Tooltip portion after a '\n' and move it to
// show in case tooltip isn't showing
// (like when mouse button is down)
char * pEnter = strchr( szStatus, '\n');
if( pEnter ){
char * pParen = strchr( pEnter, '(');
if( pParen ){
*pEnter = ' ';
strcpy(pEnter+1, pParen);
} else {
// No accerlerator, cut off tooltip
*pEnter = '\0';
}
}
wfe_Progress(m_pMWContext, szStatus );
} else {
// If string is missing, a blank would be less
// confusing then restoring the previous string!
wfe_Progress(m_pMWContext, " ");
}
}
// Set focus to any button if we move over it
// and set button as selected if left mouse button is down
if( bInButton ){
if( (nFlags & MK_LBUTTON ) && !m_pData[i].pButton->m_bSelected ){
m_pData[i].pButton->SetState(TRUE);
}
if( !m_pData[i].pButton->m_bFocus ){
m_pData[i].pButton->SetFocus();
}
break;
}
// Note: We are outside of current button
// Unselect button we moved off of except if its in "pushdown"
if( !m_pData[i].pButton->m_bDown &&
m_pData[i].pButton->m_bSelected ) {
m_pData[i].pButton->SetState(FALSE);
break;
}
// Next button
rect.top += ED_TB_BUTTON_HEIGHT;
rect.bottom += ED_TB_BUTTON_HEIGHT;
}
}
void CDropdownToolbar::OnLButtonDown(UINT nFlags, CPoint cPoint)
{
// Find the button pressed and redraw
CRect rect(0, 0, ED_TB_BUTTON_WIDTH - 1,
ED_TB_BUTTON_HEIGHT - 1);
POINT pt = {cPoint.x, cPoint.y};
for( UINT i = 0; i < m_nButtonCount; i++ ){
if( rect.PtInRect(pt) ){
// Mark button as pressed and has focus
m_pData[i].pButton->SetState(TRUE);
m_pData[i].pButton->SetFocus();
m_pData[i].pButton->Invalidate();
break;
}
rect.top += ED_TB_BUTTON_HEIGHT;
rect.bottom += ED_TB_BUTTON_HEIGHT;
}
CWnd::OnLButtonDown(nFlags, cPoint);
}
// First button up will always destroy toolbar
// if not in caller button or a toolbar button
void CDropdownToolbar::OnLButtonUp(UINT nFlags, CPoint cPoint)
{
POINT pt = {cPoint.x, cPoint.y};
BOOL bExit = FALSE;
if( m_CallerRect.top != 0 ){
// Don't destroy toolbar if button came up within the
// caller's button - this allows tooltips to show up
// when mouse moves over button when not held down
// REMOVE THIS FOR TOOLBAR DURING MOUSE-DOWN ONLY
if( ::PtInRect(&m_CallerRect, pt) ){
// Ignore the first time button comes up
// so a simple up+down click doesn't close toolbar
if( m_bFirstButtonUp ){
CWnd::OnLButtonUp(nFlags, cPoint);
m_bFirstButtonUp = FALSE;
return;
}
// Any other time, just exit
bExit = TRUE;
}
}
if( !bExit ){
// Do Hittest for all buttons
CRect rect(0, 0, ED_TB_BUTTON_WIDTH - 1,
ED_TB_BUTTON_HEIGHT - 1);
for( UINT i = 0; i < m_nButtonCount; i++ ){
if( rect.PtInRect(pt) ){
// Post message to parent to do what we're supposed to do
// only if different from initial state (for pushbutton style)
if( m_pParent && m_pData[i].nCommandID != m_nInitialID ){
m_pParent->PostMessage(WM_COMMAND, m_pData[i].nCommandID);
m_pParent->SetFocus();
}
break;
}
rect.top += ED_TB_BUTTON_HEIGHT;
rect.bottom += ED_TB_BUTTON_HEIGHT;
}
}
// Restore previous status message
if( m_pMWContext ){
wfe_Progress(m_pMWContext, "");
}
DestroyWindow();
}
/////////////////////////////////////////////////////////////////////////////
// CTagDlg dialog - The Arbitrary tag editor
CTagDlg::CTagDlg(CWnd* pParent,
MWContext* pMWContext, // MUST be supplied!
char *pTagData )
: CDialog(CTagDlg::IDD, pParent),
m_pMWContext(pMWContext),
m_bInsert(0),
m_bValidTag(0)
{
//{{AFX_DATA_INIT(CTagDlg)
m_csTagData = pTagData;
//}}AFX_DATA_INIT
wfe_GetLayoutViewSize(pMWContext, &m_iFullWidth, &m_iFullHeight);
}
void CTagDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTagDlg)
DDX_Text(pDX, IDC_EDIT_TAG, m_csTagData);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTagDlg, CDialog)
//{{AFX_MSG_MAP(CTagDlg)
ON_BN_CLICKED(ID_HELP, OnHelp)
ON_BN_CLICKED(IDC_VERIFY_HTML, OnVerifyHtml)
//}}AFX_MSG_MAP
#ifdef XP_WIN32
ON_WM_HELPINFO()
#endif //XP_WIN32
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTagDlg message handlers
#ifdef XP_WIN32
BOOL CTagDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
{
OnHelp();
return TRUE;
}
#endif//XP_WIN32
BOOL CTagDlg::OnInitDialog()
{
// Switch back to NETSCAPE.EXE for resource hInstance
m_ResourceSwitcher.Reset();
if( ED_ELEMENT_UNKNOWN_TAG == EDT_GetCurrentElementType(m_pMWContext) ) {
m_csTagData = EDT_GetUnknownTagData(m_pMWContext);
} else {
m_bInsert = TRUE;
}
CDialog::OnInitDialog();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
Bool CTagDlg::DoVerifyTag( char* pTagString ){
ED_TagValidateResult e = EDT_ValidateTag((char*)LPCSTR(m_csTagData), FALSE );
UINT nIDS = 0;
switch( e ){
case ED_TAG_OK:
return TRUE;
case ED_TAG_UNOPENED:
nIDS = IDS_TAG_UNOPENED;
break;
case ED_TAG_UNCLOSED:
nIDS = IDS_TAG_UNCLOSED;
break;
case ED_TAG_UNTERMINATED_STRING:
nIDS = IDS_TAG_UNTERMINATED_STRING;
break;
case ED_TAG_PREMATURE_CLOSE:
nIDS = IDS_TAG_PREMATURE_CLOSE;
break;
case ED_TAG_TAGNAME_EXPECTED:
nIDS = IDS_TAG_TAGNAME_EXPECTED;
break;
default:
nIDS = IDS_TAG_ERROR;
}
MessageBox( szLoadString(nIDS),
szLoadString(IDS_ERROR_HTML_CAPTION),
MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
void CTagDlg::OnHelp()
{
NetHelp(HELP_HTML_TAG);
}
void CTagDlg::OnOK()
{
UpdateData(TRUE);
if( !DoVerifyTag( (char*)LPCSTR(m_csTagData) ) ){
return;
}
EDT_BeginBatchChanges(m_pMWContext);
CDialog::OnOK();
if( m_bInsert ){
EDT_InsertUnknownTag(m_pMWContext,(char*)LPCSTR(m_csTagData));
} else {
EDT_SetUnknownTagData(m_pMWContext, (char*)LPCSTR(m_csTagData));
}
EDT_EndBatchChanges(m_pMWContext);
//Note: For Attributes-only editing(e.g., HREF JavaScript),
// caller must get data from m_csTagData;
}
void CTagDlg::OnVerifyHtml()
{
UpdateData(TRUE);
DoVerifyTag((char*)LPCSTR(m_csTagData));
}
/////////////////////////////////////////////////////////////////////////////
// CHRuleDlg dialog Horizontal rule properties in single modal dialog
CHRuleDlg::CHRuleDlg(CWnd* pParent,
MWContext* pMWContext, // MUST be supplied!
EDT_HorizRuleData* pData )
: CDialog(CHRuleDlg::IDD, pParent),
m_pMWContext(pMWContext)
{
ASSERT(pMWContext);
if (pData){
m_pData = pData;
m_bInsert = FALSE;
} else {
m_pData = EDT_NewHorizRuleData();
m_bInsert = TRUE;
}
//{{AFX_DATA_INIT(CHRuleDlg)
m_nAlign = 1;
m_bShading = TRUE;
m_iWidth = 0;
m_iHeight = 0;
m_iWidthType = 0;
//}}AFX_DATA_INIT
wfe_GetLayoutViewSize(pMWContext, &m_iFullWidth, NULL);
}
void CHRuleDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CHRuleDlg)
DDX_Radio(pDX, IDC_HR_ALIGN_LEFT, m_nAlign);
DDX_Check(pDX, IDC_HR_SHADOW, m_bShading);
DDX_Check(pDX, IDC_HR_SAVE_DEFAULT, bSaveDefaultHRule);
DDX_CBIndex(pDX, IDC_HR_WIDTH_TYPE, m_iWidthType);
DDX_Text(pDX, IDC_HR_HEIGHT, m_iHeight);
DDV_MinMaxInt(pDX, m_iHeight, 1, 10000);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CHRuleDlg, CDialog)
//{{AFX_MSG_MAP(CHRuleDlg)
ON_BN_CLICKED(ID_HELP, OnHelp)
ON_BN_CLICKED(IDC_EXTRA_HTML, OnExtraHTML)
//}}AFX_MSG_MAP
#ifdef XP_WIN32
ON_WM_HELPINFO()
#endif //XP_WIN32
END_MESSAGE_MAP()
void CHRuleDlg::OnExtraHTML()
{
CExtraHTMLDlg dlg(this, &m_pData->pExtra, IDS_HRULE_TAG);
dlg.DoModal();
}
BOOL ValidateWidth(CDialog* pDlg, int* iWidth, int iWidthType)
{
char szMessage[256];
CEdit* pWidthControl = (CEdit*)(pDlg->GetDlgItem(IDC_HR_WIDTH));
ASSERT (pWidthControl);
char szWidth[16] = "";
char *szEndWidth;
pWidthControl->GetWindowText(szWidth, 15);
int width = (int)strtol( szWidth, &szEndWidth, 10 );
int iMaxWidth = (iWidthType == 0) ? 100 : 10000;
if( (width < 1 || width > iMaxWidth) || *szEndWidth != '\0'){
// Construct a string showing correct range
wsprintf( szMessage, szLoadString(IDS_INTEGER_RANGE_ERROR), 1, iMaxWidth );
// Notify user with similar message to the DDV_ validation system
pDlg->MessageBox(szMessage, szLoadString(AFX_IDS_APP_TITLE), MB_ICONEXCLAMATION | MB_OK);
// Put focus in the offending control
// And select all text, just like DDV functions
pWidthControl->SetFocus();
pWidthControl->SetSel(0, -1, TRUE);
return FALSE;
}
// Save values if they are good
if( width > 0 ){
*iWidth = width;
}
return TRUE;
}
void UpdateWidth(CDialog* pPage, int iWidth)
{
char szBuf[16];
wsprintf(szBuf, "%d", iWidth);
pPage->GetDlgItem(IDC_HR_WIDTH)->SetWindowText(szBuf);
}
/////////////////////////////////////////////////////////////////////////////
// CHRuleDlg message handlers
BOOL CHRuleDlg::OnInitDialog()
{
if ( m_pMWContext == NULL ||
m_pData == NULL ) {
// Must have data and context!
EndDialog(IDCANCEL);
}
// Switch back to NETSCAPE.EXE for resource hInstance
m_ResourceSwitcher.Reset();
switch (m_pData->align) {
case ED_ALIGN_LEFT:
m_nAlign = 0;
break;
case ED_ALIGN_RIGHT:
m_nAlign = 2;
break;
default:
// Default is ED_ALIGN_CENTER
m_nAlign = 1;
break;
}
m_iWidth = CASTINT(m_pData->iWidth);
m_iWidthType = m_pData->bWidthPercent ? 0 : 1;
m_iHeight = CASTINT(m_pData->size);
// NoShading is HTML tag,
// but its better to show positive attributes,
// so we use "3-D Shading", with default = TRUE
m_bShading = !m_pData->bNoShade;
CComboBox * pCombo = (CComboBox*)GetDlgItem(IDC_HR_WIDTH_TYPE);
ASSERT(pCombo);
pCombo->AddString(szLoadString(IDS_PERCENT_WINDOW));
pCombo->AddString(szLoadString(IDS_PIXELS));
// Set caption to indicate a new inserted object
if ( m_bInsert ){
SetWindowText( szLoadString(IDS_INSERT_HRULE) );
}
UpdateWidth(this, m_iWidth);
CDialog::OnInitDialog();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CHRuleDlg::OnHelp()
{
NetHelp(HELP_PROPS_HRULE);
}
#ifdef XP_WIN32
BOOL CHRuleDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
{
OnHelp();
return TRUE;
}
#endif//XP_WIN32
void CHRuleDlg::OnOK()
{
if( !UpdateData(TRUE) ||
!ValidateWidth(this, &m_iWidth, m_iWidthType ) ){
return;
}
EDT_BeginBatchChanges(m_pMWContext);
switch (m_nAlign) {
case 0:
m_pData->align = ED_ALIGN_LEFT;
break;
case 1:
m_pData->align = ED_ALIGN_CENTER;
break;
case 2:
m_pData->align = ED_ALIGN_RIGHT;
break;
}
m_pData->iWidth = m_iWidth;
m_pData->bWidthPercent = (m_iWidthType == 0);
m_pData->size = m_iHeight;
m_pData->bNoShade = !m_bShading;
if ( m_bInsert ) {
EDT_InsertHorizRule( m_pMWContext, m_pData );
} else {
EDT_SetHorizRuleData( m_pMWContext, m_pData );
}
EDT_EndBatchChanges(m_pMWContext);
if( bSaveDefaultHRule ){
// Save current values as default preferences
PREF_SetIntPref("editor.hrule.height",m_iHeight);
PREF_SetIntPref("editor.hrule.width",m_iWidth);
if( m_iWidthType == 0 ){
PREF_SetBoolPref("editor.hrule.width_percent",TRUE);
} else {
PREF_SetBoolPref("editor.hrule.width_percent",FALSE);
}
if( m_bShading ){
PREF_SetBoolPref("editor.hrule.shading",TRUE);
} else {
PREF_SetBoolPref("editor.hrule.shading",FALSE);
}
PREF_SetIntPref("editor.hrule.align",m_pData->align);
}
CDialog::OnOK();
}
BOOL CHRuleDlg::DestroyWindow()
{
if (m_pData) {
EDT_FreeHorizRuleData(m_pData);
}
return CDialog::DestroyWindow();
}
/////////////////////////////////////////////////////////////////////////////
// CTargetDlg dialog Set Target(named anchor) properties in single modal dialog
CTargetDlg::CTargetDlg(CWnd* pParent,
MWContext* pMWContext, // MUST be supplied!
char *pName) // Existing target
: CDialog(CTargetDlg::IDD, pParent),
m_pMWContext(pMWContext),
m_bInsert(0)
{
ASSERT(pMWContext);
//{{AFX_DATA_INIT(CTargetDlg)
m_csName = pName;
//}}AFX_DATA_INIT
}
void CTargetDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTargetDlg)
DDX_Text(pDX, IDC_TARGET_NAME, m_csName);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTargetDlg, CDialog)
//{{AFX_MSG_MAP(CTargetDlg)
ON_EN_CHANGE(IDC_TARGET_NAME, OnChangeTargetName)
ON_BN_CLICKED(ID_HELP, OnHelp)
//}}AFX_MSG_MAP
#ifdef XP_WIN32
ON_WM_HELPINFO()
#endif //XP_WIN32
END_MESSAGE_MAP()
// CTargetDlg message handlers
BOOL CTargetDlg::OnInitDialog()
{
// Switch back to NETSCAPE.EXE for resource hInstance
m_ResourceSwitcher.Reset();
if( ED_ELEMENT_TARGET == EDT_GetCurrentElementType(m_pMWContext) ) {
m_csName = EDT_GetTargetData(m_pMWContext);
} else {
m_bInsert = TRUE;
// Use current selected text as suggested target name...
char *pName = (char*)LO_GetSelectionText(ABSTRACTCX(m_pMWContext)->GetDocumentContext());
if ( pName ){
char *pTemp = pName;
char *pEnd = pName + min( XP_STRLEN(pName), 50);
// Skip over leading white-space
while( XP_IS_SPACE(*pTemp) && pTemp < pEnd ) pTemp++;
if( pTemp < pEnd ){
char *pStart = pTemp;
// Stop at any CR/LF and replace
// other whitespace with real spaces (OR UNDERSCORE?)
while( pTemp <= pEnd ){
if( *pTemp == '\n' || *pTemp == '\r' ){
// Stop at end of line
pEnd = pTemp;
break;
}
if( XP_IS_SPACE(*pTemp) ) *pTemp = ' ';
pTemp++;
}
pTemp = pEnd;
// Find last character before the last space from the end
while( !XP_IS_SPACE(*pTemp) && pTemp != pName ) pTemp--;
if( pTemp != pName ) *pTemp = '\0';
m_csName = pStart;
m_csName.TrimRight();
}
XP_FREE(pName);
}
}
// Get the list of existing targets to
// warn if target name is already used
m_pTargetList = EDT_GetAllDocumentTargets(m_pMWContext);
CDialog::OnInitDialog();
// Enable OK only if we have some text already
GetDlgItem(IDOK)->EnableWindow(!m_csName.IsEmpty());
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CTargetDlg::OnHelp()
{
NetHelp(HELP_PROPS_TARGET);
}
#ifdef XP_WIN32
BOOL CTargetDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
{
OnHelp();
return TRUE;
}
#endif//XP_WIN32
void CTargetDlg::OnOK()
{
EDT_BeginBatchChanges(m_pMWContext);
CDialog::OnOK();
// Remove trailing spaces and quote marks
CleanupString(m_csName);
// Strip off hash mark
if(!m_csName.IsEmpty() && m_csName.GetAt(0) == '#'){
m_csName = m_csName.Mid(1);;
}
if( !m_csName.IsEmpty() ){
if( m_bInsert ){
EDT_InsertTarget(m_pMWContext, (char*)LPCSTR(m_csName));
} else {
EDT_SetTargetData(m_pMWContext, (char*)LPCSTR(m_csName));
}
}
EDT_EndBatchChanges(m_pMWContext);
}
void CTargetDlg::OnChangeTargetName()
{
UpdateData(TRUE);
// Remove trailing spaces and quote marks, but
// use temp string to cleanup and don't send string back with UpdateData
// This upsets caret location etc.
CString csTemp = m_csName;
CleanupString(csTemp);
GetDlgItem(IDOK)->EnableWindow(!csTemp.IsEmpty());
}
////////////////////////////////////////////////////////////////////////////
// Special class to control Background color of static control
//
// CColorStatic
CColorStatic::
CColorStatic(COLORREF crTextColor, // Default is black text
COLORREF crBackColor, // on gray Background
ED_BorderStyle nStyle)
{
m_crTextColor = crTextColor;
m_crBackColor = crBackColor;
m_nBorderStyle = nStyle;
// Create a white brush for the Background
m_brush.CreateSolidBrush(crBackColor|0x02000000); // Like PALETTERGB
}
CColorStatic::~CColorStatic()
{
}
BEGIN_MESSAGE_MAP(CColorStatic, CStatic)
//{{AFX_MSG_MAP(CColorStatic)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CColorStatic message handlers
BOOL CColorStatic::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
LRESULT* pLResult)
{
int nCtlType = (int)HIWORD(lParam);
// If "message" is not the message you're after, do default processing:
if (message != WM_CTLCOLOR)
{
return CStatic::OnChildNotify(message,wParam,lParam,pLResult);
}
HDC hdcChild = (HDC)wParam;
SetTextColor(hdcChild, m_crTextColor);
SetBkColor(hdcChild, m_crTextColor);
// Send what would have been the return value of OnCtlColor() - the brush
// handle - back in pLResult:
*pLResult = (LRESULT)(m_brush.GetSafeHandle());
// Return TRUE to indicate that the message was handled:
return TRUE;
}
#define MAX_META_NAME_LEN 100
#define MAX_META_VALUE_LEN 400
enum {
EDIT_NONE,
EDIT_EQUIV,
EDIT_META
};
/////////////////////////////////////////////////////////////////////
// Document Properties Pages
//
// First page = general info
// "Fixed" Meta Tags we always include
//
CDocInfoPage::CDocInfoPage(CWnd* pParent, MWContext * pMWContext,
CEditorResourceSwitcher * pResourceSwitcher,
EDT_PageData * pPageData)
: CNetscapePropertyPage(CDocInfoPage::IDD),
m_pMWContext(pMWContext),
m_pResourceSwitcher(pResourceSwitcher),
m_bActivated(0),
m_pPageData(pPageData)
{
//{{AFX_DATA_INIT(CDocInfoPage)
m_csAuthor = _T("");
m_csClassification = _T("");
m_csDescription = _T("");
m_csTitle = _T("");
m_csURL = _T("");
m_csKeyWords = _T("");
//}}AFX_DATA_INIT
ASSERT(pMWContext);
ASSERT(pPageData);
#ifdef XP_WIN32
// Set the hInstance so we get template from editor's resource DLL
m_psp.hInstance = AfxGetResourceHandle();
#endif
}
////////////////////////////////////////////////////////////////////////
BOOL CDocInfoPage::OnSetActive()
{
if(m_pResourceSwitcher && !m_bActivated){
// We must be sure we have switched
// the first time here - before dialog creation
m_pResourceSwitcher->switchResources();
}
if(!CPropertyPage::OnSetActive())
return(FALSE);
if(m_bActivated)
return(TRUE);
// Switch back to EXE's resources
if( m_pResourceSwitcher ){
m_pResourceSwitcher->Reset();
}
m_bActivated = TRUE;
// This should be same as hist_ent->title??
m_csTitle = m_pPageData->pTitle;
History_entry * hist_ent = SHIST_GetCurrent(&m_pMWContext->hist);
if(hist_ent && hist_ent->address) {
m_csURL = hist_ent->address;
WFE_CondenseURL(m_csURL, 80, FALSE);
GetDlgItem(IDC_DOC_URL)->SetWindowText(CHAR_STR(m_csURL));
// If empty, fill in title with Filename part of URL without extension
if( m_csTitle.IsEmpty() ){
char * pTitle = EDT_GetPageTitleFromFilename(hist_ent->address);
if( pTitle ){
m_csTitle = pTitle;
XP_FREE(pTitle);
}
}
}
// Get data from meta tags:
int count = EDT_MetaDataCount(m_pMWContext);
for ( int i = 0; i < count; i++ ) {
EDT_MetaData* pData = EDT_GetMetaData(m_pMWContext, i);
if ( !pData->bHttpEquiv ) {
if ( 0 == _stricmp(pData->pName, "Author") ) {
m_csAuthor = pData->pContent;
} else if ( 0 == _stricmp(pData->pName, "Classification") ) {
m_csClassification = pData->pContent;
} else if ( 0 == _stricmp(pData->pName, "Description") ) {
m_csDescription = pData->pContent;
} else if ( 0 == _stricmp(pData->pName, "KeyWords") ) {
m_csKeyWords = pData->pContent;
}/* else if ( 0 == _stricmp(pData->pName, "Created") ) {
m_csCreateDate = pData->pContent;
} else if ( 0 == _stricmp(pData->pName, "Last-Modified") ) {
m_csUpdateDate = pData->pContent;
}*/
}
}
if( m_csAuthor.IsEmpty() ){
// Get name from preferences if none supplied
char * pAuthor = NULL;
PREF_CopyCharPref("editor.author", &pAuthor);
m_csAuthor = pAuthor;
XP_FREEIF(pAuthor);
}
UpdateData(FALSE);
return(TRUE);
}
// Create a MetaData structure and save it
// This commits change - NO BUFFERING
// Be sure to strip off spaces and quotes before calling this
void CDocInfoPage::SetMetaData(char * pName, char * pValue)
{
EDT_MetaData *pData = EDT_NewMetaData();
if ( pData ) {
pData->bHttpEquiv = FALSE;
if ( pName && XP_STRLEN(pName) > 0 ) {
pData->pName = XP_STRDUP(pName);
if ( pValue && XP_STRLEN(pValue) > 0 ) {
pData->pContent = XP_STRDUP(pValue);
EDT_SetMetaData(m_pMWContext, pData);
} else {
// (Don't really need to do this)
pData->pContent = NULL;
// Remove the item
EDT_DeleteMetaData(m_pMWContext, pData);
}
OkToClose();
}
EDT_FreeMetaData(pData);
}
}
void CDocInfoPage::OnHelp()
{
NetHelp(HELP_DOC_PROPS_GENERAL);
}
void CDocInfoPage::OnOK()
{
CPropertyPage::OnOK();
// never visited this page or no change -- don't bother
if(!m_bActivated ||
!IS_APPLY_ENABLED(this)){
return;
}
m_bActivated = TRUE;
// EDT_BeginBatchChanges(m_pMWContext);
// Replace Title and FontDefURL
XP_FREEIF(m_pPageData->pTitle);
CleanupString(m_csTitle);
if ( !m_csTitle.IsEmpty() ) {
m_pPageData->pTitle = XP_STRDUP(m_csTitle);
}
EDT_SetPageData(m_pMWContext, m_pPageData);
// Trim quotes and set data meta tags
CleanupString(m_csAuthor);
if ( !m_csAuthor.IsEmpty() ) {
// Don't wipe out author field if empty?
SetMetaData("Author", CHAR_STR(m_csAuthor));
}
CleanupString(m_csClassification);
SetMetaData("Classification", CHAR_STR(m_csClassification));
CleanupString(m_csDescription);
SetMetaData("Description", CHAR_STR(m_csDescription));
CleanupString(m_csKeyWords);
SetMetaData("KeyWords", CHAR_STR(m_csKeyWords));
// TODO: MAKE THIS STRING IF NEW DOC???
// SetMetaData(FALSE, "Created", CHAR_STR());
// SetMetaData(FALSE, "Last-Modified", CHAR_STR());
OkToClose();
//EDT_EndBatchChanges(m_pMWContext);
}
void CDocInfoPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDocInfoPage)
DDX_Text(pDX, IDC_DOC_AUTHOR, m_csAuthor);
DDX_Text(pDX, IDC_DOC_CLASIFICATION, m_csClassification);
DDX_Text(pDX, IDC_DOC_DESCRIPTION, m_csDescription);
DDX_Text(pDX, IDC_DOC_TITLE, m_csTitle);
DDX_Text(pDX, IDC_DOC_URL, m_csURL);
DDX_Text(pDX, IDC_KEYWORDS, m_csKeyWords);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDocInfoPage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CDocInfoPage)
ON_EN_CHANGE(IDC_DOC_AUTHOR, EnableApply)
ON_EN_CHANGE(IDC_DOC_CLASIFICATION, EnableApply)
ON_EN_CHANGE(IDC_DOC_DESCRIPTION, EnableApply)
ON_EN_CHANGE(IDC_DOC_TITLE, EnableApply)
ON_EN_CHANGE(IDC_KEYWORDS, EnableApply)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CDocInfoPage::EnableApply()
{
SetModified(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// Local helpers for color params converversions
// Allocate and initialize a new scheme struct and add it to list
EDT_ColorSchemeData * AddNewColorData( XP_List *pSchemeData )
{
EDT_ColorSchemeData * pColorData = XP_NEW(EDT_ColorSchemeData);
if(!pColorData) {
return NULL;
}
memset(pColorData, 0, sizeof(EDT_ColorSchemeData));
XP_ListAddObjectToEnd(pSchemeData, pColorData);
return pColorData;
}
//////////////////////////////////////////////////////////////////////
/*
// For reference: the built-in default colors
LO_DEFAULT_FG_RED 0
LO_DEFAULT_FG_GREEN 0
LO_DEFAULT_FG_BLUE 0
LO_DEFAULT_BG_RED 192
LO_DEFAULT_BG_GREEN 192
LO_DEFAULT_BG_BLUE 192
LO_UNVISITED_ANCHOR_RED 0
LO_UNVISITED_ANCHOR_GREEN 0
LO_UNVISITED_ANCHOR_BLUE 238
LO_VISITED_ANCHOR_RED 85
LO_VISITED_ANCHOR_GREEN 26
LO_VISITED_ANCHOR_BLUE 139
LO_SELECTED_ANCHOR_RED 255
LO_SELECTED_ANCHOR_GREEN 0
LO_SELECTED_ANCHOR_BLUE 0
// Offsets for getting defaults from lo_master_colors
// eg:
red = lo_master_colors[LO_COLOR_FG].red;
green = lo_master_colors[LO_COLOR_FG].green;
blue = lo_master_colors[LO_COLOR_FG].blue;
LO_COLOR_BG 0
LO_COLOR_FG 1
LO_COLOR_LINK 2
LO_COLOR_VLINK 3
LO_COLOR_ALINK 4
*/
/////////////////////////////////////////////////////////////////////
CDocColorPage::CDocColorPage(CWnd* pParent,
UINT nIDCaption,
UINT nIDFocus,
MWContext * pMWContext,
CEditorResourceSwitcher * pResourceSwitcher,
EDT_PageData * pPageData )
: CNetscapePropertyPage(CDocColorPage::IDD, nIDCaption, nIDFocus),
m_bActivated(0),
m_pMWContext(pMWContext),
m_pResourceSwitcher(pResourceSwitcher),
m_pPageData(pPageData),
m_bImageChanged(0),
m_bValidImage(0),
m_pSchemeData(0),
m_hPal(0)
{
ASSERT(pMWContext);
//{{AFX_DATA_INIT(CDocColorPage)
m_csBackgroundImage = _T("");
m_csSelectedScheme = _T("");
m_bNoSave = 0;
//}}AFX_DATA_INIT
//m_csCustomBackgroundImage = _T("");
m_csBrowserBackgroundImage = _T("");
#ifdef XP_WIN32
// Set the hInstance so we get template from editor's resource DLL
m_psp.hInstance = AfxGetResourceHandle();
#endif
}
CDocColorPage::~CDocColorPage()
{
// Destroy the scheme list
// TODO: Move to XP code
if ( m_pSchemeData ) {
EDT_ColorSchemeData *pColorData;
XP_List * list_ptr = m_pSchemeData;
while ((pColorData = (EDT_ColorSchemeData *)XP_ListNextObject(list_ptr))) {
if ( pColorData->pSchemeName ) {
XP_FREE( pColorData->pSchemeName );
}
if ( pColorData->pBackgroundImage ) {
XP_FREE( pColorData->pBackgroundImage );
}
XP_FREE(pColorData);
}
XP_ListDestroy(m_pSchemeData);
}
}
void CDocColorPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDocColorPage)
DDX_Text(pDX, IDC_BKGRND_IMAGE, m_csBackgroundImage);
DDX_CBString(pDX, IDC_SCHEME_LIST, m_csSelectedScheme);
DDX_Check(pDX, IDC_NO_SAVE_IMAGE, m_bNoSave);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDocColorPage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CDocColorPage)
ON_BN_CLICKED(IDC_BKGRND_USE_IMAGE, OnUseBkgrndImage)
ON_BN_CLICKED(IDC_CHOOSE_BACKGROUND, OnChooseBkgrndImage)
ON_CBN_SELCHANGE(IDC_SCHEME_LIST, OnSelchangeSchemeList)
ON_EN_CHANGE(IDC_BKGRND_IMAGE, OnChangeBkgrndImage)
ON_EN_KILLFOCUS(IDC_BKGRND_IMAGE, OnKillfocusBkgrndImage)
ON_WM_PAINT()
ON_BN_CLICKED(IDC_CHOOSE_TEXT_COLOR, OnChooseTextColor)
ON_BN_CLICKED(IDC_CHOOSE_LINK_COLOR, OnChooseLinkColor)
ON_BN_CLICKED(IDC_CHOOSE_ACTIVELINK_COLOR, OnChooseActivelinkColor)
ON_BN_CLICKED(IDC_CHOOSE_FOLLOWEDLINK_COLOR, OnChooseFollowedlinkColor)
ON_BN_CLICKED(IDC_CHOOSE_BKGRND_COLOR, OnChooseBkgrndColor)
ON_BN_CLICKED(IDC_SET_DOC_COLORS, OnColorsRadioButtons)
ON_BN_CLICKED(IDC_USE_BROWSER_COLORS, OnColorsRadioButtons)
ON_BN_CLICKED(IDC_USE_AS_DEFAULT, OnUseAsDefault)
ON_BN_CLICKED(IDC_NO_SAVE_IMAGE, OnNoSave)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#include "timer.h" //For nettimer.OnIdle()
BOOL CDocColorPage::OnSetActive()
{
if(m_pResourceSwitcher && !m_bActivated){
// We must be sure we have switched
// the first time here - before dialog creation
m_pResourceSwitcher->switchResources();
}
if(!CPropertyPage::OnSetActive())
return(FALSE);
if(m_bActivated)
return(TRUE);
// Switch back to EXE's resources
if( m_pResourceSwitcher ){
m_pResourceSwitcher->Reset();
}
m_hPal = WFE_GetUIPalette(GetParentFrame());
if( !m_TextColorButton.Subclass(this, IDC_CHOOSE_TEXT_COLOR, &m_crText) ||
!m_LinkColorButton.Subclass(this, IDC_CHOOSE_LINK_COLOR, &m_crLink) ||
!m_ActiveLinkColorButton.Subclass(this, IDC_CHOOSE_ACTIVELINK_COLOR, &m_crActiveLink) ||
!m_FollowedLinkColorButton.Subclass(this, IDC_CHOOSE_FOLLOWEDLINK_COLOR, &m_crFollowedLink) ||
!m_BackgroundColorButton.Subclass(this, IDC_CHOOSE_BKGRND_COLOR, &m_crBackground) ){
return FALSE;
}
// TODO - do stuff here
m_bActivated = TRUE;
CComboBox * pSchemeListBox = (CComboBox*)GetDlgItem(IDC_SCHEME_LIST);
CFont fontPreview;
// Create a font for the preview window
if( GetSystemMetrics(SM_DBCSENABLED) ){
HFONT hFont = NULL;
#ifdef _WIN32
hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
#endif
if (!hFont){
hFont = (HFONT)GetStockObject(SYSTEM_FONT);
}
fontPreview.Attach(hFont);
GetDlgItem(IDC_DOC_COLOR_PREVIEW)->SetFont(&fontPreview);
} else {
// Get a 1-pixel font
LOGFONT logFont;
memset(&logFont, 0, sizeof(logFont));
logFont.lfHeight = -18; // about 14 points?
logFont.lfWeight = FW_BOLD;
logFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
lstrcpy(logFont.lfFaceName,"MS Serif");
if( fontPreview.CreateFontIndirect(&logFont) ){
GetDlgItem(IDC_DOC_COLOR_PREVIEW)->SetFont(&fontPreview);
} else {
TRACE0("Could Not create preview for Color Dialog\n");
}
}
// Get current stuff from preferences
char * prefStr = NULL;
PREF_CopyCharPref("editor.color_scheme",&prefStr);
if (prefStr) {
m_csSelectedScheme = prefStr;
XP_FREE(prefStr);
} else m_csSelectedScheme = "";
// Construct a list of Schemes
// TODO: Make this a global list and move to XP code
m_pSchemeData = XP_ListNew();
EDT_ColorSchemeData * pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
// First scheme is always the Netscape Default Colors
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_COLOR_SCHEME_NS_DEFAULT));
COLORREF clr;
PREF_GetColorPrefDWord("editor.text_color",&clr);
WFE_SetLO_Color( clr, &pColorData->ColorText );
PREF_GetColorPrefDWord("editor.link_color",&clr);
WFE_SetLO_Color( clr, &pColorData->ColorLink );
PREF_GetColorPrefDWord("editor.active_link_color",&clr);
WFE_SetLO_Color( clr, &pColorData->ColorActiveLink );
PREF_GetColorPrefDWord("editor.followed_link_color",&clr);
WFE_SetLO_Color( clr, &pColorData->ColorFollowedLink );
PREF_GetColorPrefDWord("editor.background_color",&clr);
WFE_SetLO_Color( clr, &pColorData->ColorBackground );
// Add name to listbox
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_WHITE));
WFE_SetLO_Color( RGB(0,0,0),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(255,255,255),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(255,0,0),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,0,128),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(0,0,255),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_OFFWHITE));
WFE_SetLO_Color( RGB(0,0,0),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(255,240,240),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(255,0,0),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,0,128),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(0,0,255),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_LTYELLOW));
WFE_SetLO_Color( RGB(0,0,0),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(255,255,192),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(0,0,255),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,0,128),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(255,0,255),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_YELLOW));
WFE_SetLO_Color( RGB(64,0,64),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(255,255,128),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(0,0,255),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(0,128, 0),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(255,0,128),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_LTBLUE));
WFE_SetLO_Color( RGB(0,0,0),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(192,192,255),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(0,0,255),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,0,128),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(255,0,128),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_MEDBLUE));
WFE_SetLO_Color( RGB(0,0,0),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(128,128,192),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(255,255,255),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,0,128),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(255,255,0),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLUE_ON_ORANGE));
WFE_SetLO_Color( RGB(0,0,128),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(255,192,64),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(0,0,255),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(0,128,0),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(0,255,255),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_BLACK));
WFE_SetLO_Color( RGB(255,255,255),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(0,0,0),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(255,255,0),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(192,192,192),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(192,255,192),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_GREEN));
WFE_SetLO_Color( RGB(255,255,255),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(0,64,0),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(255,255,0),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,255,128),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(0,255,64),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_BLUE));
WFE_SetLO_Color( RGB(255,255,255),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(0,0,128),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(255,255,0),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,128,255),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(255,0,255),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
pColorData = AddNewColorData( m_pSchemeData );
if ( pColorData ) {
pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_VIOLET));
WFE_SetLO_Color( RGB(255,255,255),
&pColorData->ColorText );
WFE_SetLO_Color( RGB(128,0,128),
&pColorData->ColorBackground );
WFE_SetLO_Color( RGB(0,255,255),
&pColorData->ColorLink );
WFE_SetLO_Color( RGB(128,255,255),
&pColorData->ColorFollowedLink );
WFE_SetLO_Color( RGB(0,255,0),
&pColorData->ColorActiveLink );
pSchemeListBox->AddString(pColorData->pSchemeName);
}
// Get Browser preference colors
m_crBrowserText = prefInfo.m_rgbForegroundColor;
m_crBrowserLink = prefInfo.m_rgbAnchorColor;
m_crBrowserFollowedLink = prefInfo.m_rgbVisitedColor;
m_crBrowserBackground = prefInfo.m_rgbBackgroundColor;
// m_pPageData may be NULL if we are not an Editor
// (preferences dialog called from a browser)
//
// We are in Document Properties Mode
// Initialize from current document
// Note: If the color isn't set,
// this will get the color from display master colors
m_crCustomBackground = WFE_LO2COLORREF( m_pPageData->pColorBackground,LO_COLOR_BG );
m_crCustomText = WFE_LO2COLORREF( m_pPageData->pColorText, LO_COLOR_FG );
m_crCustomLink = WFE_LO2COLORREF( m_pPageData->pColorLink, LO_COLOR_LINK );
m_crCustomActiveLink = WFE_LO2COLORREF( m_pPageData->pColorActiveLink, LO_COLOR_ALINK );
m_crCustomFollowedLink = WFE_LO2COLORREF( m_pPageData->pColorFollowedLink, LO_COLOR_VLINK );
if (( m_pPageData->pBackgroundImage )&&( XP_STRLEN(m_pPageData->pBackgroundImage) )) {
m_csBackgroundImage = m_pPageData->pBackgroundImage;
// Set checkbox - we have an image
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(1);
} else {
// Get the default image from preferences in case they want to use it
char * szBack = NULL;
PREF_CopyCharPref("editor.background_image",&szBack);
m_csBackgroundImage = szBack;
XP_FREEIF(szBack);
// But DON'T set the checkbox -- image will not be used
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
}
// If ANY color is set, then we will assume "Custom" mode
m_bCustomColors =
( m_pPageData->pColorBackground ||
m_pPageData->pColorText ||
m_pPageData->pColorLink ||
m_pPageData->pColorActiveLink ||
m_pPageData->pColorFollowedLink );
// Save current state so we don't repaint unnecessarily
m_bWasCustomColors = m_bCustomColors;
// Flag to leave image at original location and not save with page
m_bNoSave = m_pPageData->bBackgroundNoSave;
if( m_bCustomColors ){
// We will start in Custom Colors mode
// Redraw only if current state is Browser colors
// Don't unselect scheme
UseCustomColors(!m_bWasCustomColors, FALSE);
} else {
// We will start with Browser colors
// Don't do update stuff
UseBrowserColors(FALSE);
}
// Initialize radio buttons and color swatches
((CButton*)GetDlgItem(IDC_SET_DOC_COLORS))->SetCheck( m_bCustomColors ? 1 : 0 );
((CButton*)GetDlgItem(IDC_USE_BROWSER_COLORS))->SetCheck( m_bCustomColors ? 0 : 1 );
// Disables Apply button (probably don't need to do this)
SetModified(FALSE);
UpdateData(FALSE);
return(TRUE);
}
// Use bUpdateControls = FALSE if initializing,
// Use TRUE when switching from CustomColor state to Browser colors
void CDocColorPage::UseBrowserColors(BOOL bRedraw)
{
m_bCustomColors = m_bWasCustomColors = FALSE;
((CButton*)GetDlgItem(IDC_SET_DOC_COLORS))->SetCheck(0);
((CButton*)GetDlgItem(IDC_USE_BROWSER_COLORS))->SetCheck(1);
// Initialize from current preferences
m_crBackground = m_crBrowserBackground;
m_crText = m_crBrowserText;
m_crLink = m_crBrowserLink;
// Browser doesn't store this color
m_crActiveLink = m_crBrowserLink;
m_crFollowedLink = m_crBrowserFollowedLink;
if( bRedraw ){
Invalidate(FALSE);
}
SetModified(TRUE);
}
// Redraw dialog to show color swatches -- use bRedraw = FALSE if no colors changing
void CDocColorPage::UseCustomColors(BOOL bRedraw, BOOL bUnselectScheme)
{
m_bCustomColors = m_bWasCustomColors = TRUE;
((CButton*)GetDlgItem(IDC_SET_DOC_COLORS))->SetCheck(1);
((CButton*)GetDlgItem(IDC_USE_BROWSER_COLORS))->SetCheck(0);
if( bUnselectScheme ){
// Get selected scheme name
// (Also gets background image image name, which we ignore here)
UpdateData(TRUE);
// TODO: Modify this in the future to
// reset only if not one of built-in
// schemes?
// Get currently-selected scheme
// to use as default name for saving
m_csSaveScheme = m_csSelectedScheme;
// Unselect scheme list when editing built-in schemes,
// to remove impression that user can modify them
((CComboBox*)GetDlgItem(IDC_SCHEME_LIST))->SetCurSel(-1);
}
m_crBackground = m_crCustomBackground;
m_crText = m_crCustomText;
m_crLink = m_crCustomLink;
m_crActiveLink = m_crCustomActiveLink;
m_crFollowedLink = m_crCustomFollowedLink;
if( bRedraw ){
// Redraw color swatches and text samples
Invalidate(FALSE);
}
// Set Apply button states if we are in Properties mode
SetModified(TRUE);
}
BOOL CDocColorPage::OnKillActive()
{
if(m_bActivated){
if( !UpdateData(TRUE) ){
return FALSE;
}
if ( !m_csBackgroundImage.IsEmpty() ) {
if ( m_bImageChanged && !m_bValidImage ) {
if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
!wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/ ) ){
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
return FALSE;
}
// Send changed image back to editbox in case this is Apply usage
UpdateData(FALSE);
}
}
if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
!m_csBackgroundImage.IsEmpty() ){
int iLastDot = m_csBackgroundImage.ReverseFind('.');
CString csExt;
if(iLastDot > 0)
csExt= m_csBackgroundImage.Mid(iLastDot);
//we must check to see if file is a bmp!
if (0 == csExt.CompareNoCase(".bmp"))
{
char *t_outputfilename=wfe_ConvertImage(m_csBackgroundImage.GetBuffer(0),(void *)this,m_pMWContext);
if (t_outputfilename)
{
m_csBackgroundImage=t_outputfilename;
wfe_ValidateImage( m_pMWContext, m_csBackgroundImage );
XP_FREE(t_outputfilename);
UpdateData(FALSE);//we need to update m_csImage!
}
else
return FALSE;
}
}
}
return TRUE;
}
void CDocColorPage::OnHelp()
{
NetHelp(HELP_DOC_PROPS_APPEARANCE);
}
void CDocColorPage::OnOK()
{
//Note: Get and Validate data done in OnKillActive()
CPropertyPage::OnOK();
// never visited this page,
// or no change when used in Doc. Properties mode -- don't bother
if( !m_bActivated ||
!IS_APPLY_ENABLED(this) ){
return;
}
// Save settings for current document
// Erase current background image in doc
if ( m_pPageData->pBackgroundImage ) {
XP_FREE( m_pPageData->pBackgroundImage );
m_pPageData->pBackgroundImage = NULL;
}
if ( m_bCustomColors ) {
// Set all custom colors
WFE_SetLO_ColorPtr( m_crCustomText, &m_pPageData->pColorText );
WFE_SetLO_ColorPtr( m_crCustomLink, &m_pPageData->pColorLink );
WFE_SetLO_ColorPtr( m_crCustomActiveLink, &m_pPageData->pColorActiveLink );
WFE_SetLO_ColorPtr( m_crCustomFollowedLink, &m_pPageData->pColorFollowedLink );
// Set color even if we use an image
// (Color tag is written to doc, but image tag overrides)
WFE_SetLO_ColorPtr( m_crCustomBackground, &m_pPageData->pColorBackground );
} else {
// Use browser colors means storing no tags in document
// Clear all colors and background image to set the document's tags
// Note: We ignore the Browser's background image,
// based on the judgement that if they don't want colors,
// then the browser's image would be irrelavent (and distracting) while editing
WFE_FreeLO_Color( &m_pPageData->pColorText );
WFE_FreeLO_Color( &m_pPageData->pColorLink );
WFE_FreeLO_Color( &m_pPageData->pColorActiveLink );
WFE_FreeLO_Color( &m_pPageData->pColorFollowedLink );
WFE_FreeLO_Color( &m_pPageData->pColorBackground );
}
if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
!m_csBackgroundImage.IsEmpty() ){
m_pPageData->pBackgroundImage = XP_STRDUP(m_csBackgroundImage);
// Save state of flag from checkbox
m_pPageData->bBackgroundNoSave = m_bNoSave;
}
// Disable Apply an change "OK" to "Close"
OkToClose();
// Clear data-modified flag
SetModified(FALSE);
// This sets tag data for doc and calls front end
// to setbackground colors and image
EDT_SetPageData(m_pMWContext, m_pPageData);
// This forces redraw of entire window
// (there is some missing redraw areas at top of window)
::InvalidateRect(PANECX(m_pMWContext)->GetPane(), NULL, TRUE);
if( ((CButton*)GetDlgItem(IDC_USE_AS_DEFAULT))->GetCheck() ){
// Save current settings to Preferences
if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
!m_csBackgroundImage.IsEmpty() ){
PREF_SetBoolPref("editor.use_background_image",TRUE);
PREF_SetCharPref("editor.background_image",LPCSTR(m_csBackgroundImage));
} else {
PREF_SetBoolPref("editor.use_background_image",FALSE);
}
if ( m_bCustomColors ) {
PREF_SetBoolPref("editor.use_custom_colors",TRUE);
PREF_SetCharPref("editor.color_scheme",(char*)LPCSTR(m_csSelectedScheme));
PREF_SetColorPrefDWord("editor.text_color",m_crCustomText);
PREF_SetColorPrefDWord("editor.link_color",m_crCustomLink);
PREF_SetColorPrefDWord("editor.active_link_color",m_crCustomActiveLink);
PREF_SetColorPrefDWord("editor.followed_link_color",m_crCustomFollowedLink);
PREF_SetColorPrefDWord("editor.background_color",m_crCustomBackground);
} else {
// Note: don't change previous color preferences
PREF_SetBoolPref("editor.use_custom_colors",FALSE);
}
}
}
void CDocColorPage::OnUseAsDefault()
{
SetModified(TRUE);
}
void CDocColorPage::OnColorsRadioButtons()
{
// Get checkbox state and change colors appropriately
// but only if different than previous mode
m_bCustomColors = IsDlgButtonChecked(IDC_SET_DOC_COLORS);
if(m_bWasCustomColors != m_bCustomColors){
if(m_bCustomColors){
UseCustomColors();
} else {
UseBrowserColors();
}
// Send the appropriate string to the background image editbox
UpdateData(FALSE);
}
}
void CDocColorPage::OnRemoveScheme()
{
SetModified(TRUE);
}
void CDocColorPage::OnSaveScheme()
{
SetModified(TRUE);
}
void CDocColorPage::OnSelchangeSchemeList()
{
// Get data - we want selected color scheme
UpdateData(TRUE);
if ( m_csSelectedScheme.IsEmpty() ) {
return;
}
// Find the scheme in the list and extract color info
EDT_ColorSchemeData *pColorData;
XP_List * list_ptr = m_pSchemeData;
while ((pColorData = (EDT_ColorSchemeData *)XP_ListNextObject(list_ptr))) {
if ( 0 == XP_STRCMP(pColorData->pSchemeName, m_csSelectedScheme) ) {
m_crCustomText =
WFE_LO2COLORREF( &pColorData->ColorText, LO_COLOR_FG );
m_crCustomLink =
WFE_LO2COLORREF( &pColorData->ColorLink, LO_COLOR_LINK );
m_crCustomActiveLink =
WFE_LO2COLORREF( &pColorData->ColorActiveLink, LO_COLOR_ALINK );
m_crCustomFollowedLink =
WFE_LO2COLORREF( &pColorData->ColorFollowedLink, LO_COLOR_VLINK );
m_crCustomBackground =
WFE_LO2COLORREF( &pColorData->ColorBackground, LO_COLOR_BG );
if ( pColorData->pBackgroundImage ) {
// Scheme may include a background image...
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(1);
m_csBackgroundImage = pColorData->pBackgroundImage;
}
// ...but if scheme doesn't have image, then leave existing
// image and checkbox state
break;
}
}
// Do repaint, but don't unselect the scheme listbox
UseCustomColors(TRUE, FALSE);
}
BOOL CDocColorPage::ChooseColor(COLORREF * pColor, CColorButton * pButton, COLORREF crDefault, BOOL bBackground )
{
RECT rect;
pButton->GetWindowRect(&rect);
CColorPicker ColorPicker(this, m_pMWContext, m_bCustomColors ? *pColor : DEFAULT_COLORREF, crDefault,
bBackground ? IDS_PAGE_BACKGROUND : IDS_TEXT_COLOR, &rect);
COLORREF crNew = ColorPicker.GetColor();
if( crNew != CANCEL_COLORREF ){
if( crNew == DEFAULT_COLORREF){
*pColor = crDefault;
} else {
*pColor = crNew;
}
// Send new color to control
UpdateData(FALSE);
// We must be in custom color mode now
UseCustomColors();
pButton->Update();
return TRUE;
}
return FALSE;
}
void CDocColorPage::OnChooseTextColor()
{
ChooseColor(&m_crCustomText, &m_TextColorButton, m_crBrowserText);
}
void CDocColorPage::OnChooseLinkColor()
{
ChooseColor(&m_crCustomLink, &m_LinkColorButton, m_crBrowserLink );
}
void CDocColorPage::OnChooseActivelinkColor()
{
ChooseColor(&m_crCustomActiveLink, &m_ActiveLinkColorButton, m_crBrowserLink);
}
void CDocColorPage::OnChooseFollowedlinkColor()
{
ChooseColor(&m_crCustomFollowedLink, &m_FollowedLinkColorButton, m_crBrowserFollowedLink);
}
void CDocColorPage::OnChooseBkgrndColor()
{
if ( ChooseColor(&m_crCustomBackground, &m_BackgroundColorButton, m_crBrowserBackground, TRUE) ) {
// Change to custom colors if we were Browser mode
UseCustomColors(!m_bWasCustomColors);
}
}
void CDocColorPage::OnChangeBkgrndImage()
{
// Set flags to trigger validation on Killfocus
m_bValidImage = FALSE;
m_bImageChanged = TRUE;
UpdateData(TRUE);
CString csTemp = m_csBackgroundImage;
csTemp.TrimLeft();
csTemp.TrimRight();
// Set checkbox if there are any characters, clear if empty
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(!csTemp.IsEmpty());
SetModified(TRUE);
// NEW: Allow selecting an image if we are in Browser color mode
// UseCustomColors(!m_bWasCustomColors);
}
void CDocColorPage::OnKillfocusBkgrndImage()
{
#if 0
// Use this if we want to validate as soon as they leave the editbox
// Get the image name, make it a relative file-type URL,
// then send it back to editbox
if( m_bImageChanged &&
UpdateData(TRUE) ){
if( !wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/ ) ){
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
}
m_bValidImage = TRUE;
UpdateData(FALSE);
}
#endif
}
// Called from the View after saving file to disk -- has new background
// image URL relative to current document
void CDocColorPage::SetImageFileSaved(char * pImageURL)
{
m_csBackgroundImage = pImageURL;
UpdateData(FALSE);
}
void CDocColorPage::OnUseBkgrndImage()
{
int iUseImageBackground = ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck();;
SetModified(TRUE);
if( iUseImageBackground ){
// User decided to use the image, so do trigger validation
if( !wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/ ) ){
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
}
m_bValidImage = TRUE;
}
// TODO: Try to display image in our preview box
// Need to load file and convert to bitmap
// Redraw only if current state is Browser colors
// NEW: Allow selecting an image if we are in Browser color mode
// UseCustomColors(!m_bWasCustomColors);
}
void CDocColorPage::OnChooseBkgrndImage()
{
char * szFilename = wfe_GetExistingImageFileName(this->m_hWnd,
szLoadString(IDS_SELECT_IMAGE), TRUE);
if ( szFilename == NULL ){
return;
}
m_csBackgroundImage = szFilename;
if( !wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/ ) ){
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
}
// Send new name to editbox
UpdateData(FALSE);
XP_FREE( szFilename );
m_bValidImage = TRUE;
m_bImageChanged = FALSE;
// Note: allow background image without forcing custom colors
((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(1);
SetModified(TRUE);
}
void CDocColorPage::OnPaint()
{
CWnd *pPreview = GetDlgItem(IDC_DOC_COLOR_PREVIEW);
// TODO: Quit here if we don't use text preview in "Use Browser Colors" mode
// Wierd Windows! We must do this else
// no painting at all occurs!
CPaintDC dc(this); // device context for painting
// Get the DC to the Preview window
CDC * pDC = pPreview->GetDC();
if( !pDC ) return;
CRect cRect;
HPALETTE hOldPal = NULL;
if( m_hPal ){
hOldPal = ::SelectPalette( pDC->m_hDC, m_hPal, FALSE );
}
// find out how much area we can draw into
pPreview->GetClientRect(&cRect);
// color for the inside
CBrush brush(m_crBackground|0x02000000); // Like PALETTERGB
CBrush * pOldBrush = (CBrush *) pDC->SelectObject(&brush);
pDC->LPtoDP(&cRect);
cRect.InflateRect(-1,-1);
// draw the background
pDC->FillRect(cRect, &brush);
// set the background color
pDC->SetBkColor(m_crBackground);
pDC->SetTextColor(m_crText);
pDC->SetBkMode(TRANSPARENT);
// Draw 4 sample text strings
CString csText = szLoadString(IDS_TEXT);
int iNextLine = (cRect.Height() - 2) / 4;
int iTextTop = 2;
int iTextLeft = 6;
char* csSample = szLoadString(IDS_TEXT);
CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
CSize sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
csSample = szLoadString(IDS_LINK_TEXT);
pDC->SetTextColor(m_crLink);
// This puts "Link text" on 2nd line:
iTextTop += iNextLine;
CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
// Underline link samples
sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
CPen penLink(PS_SOLID, 2, m_crLink);
CPen *pOldPen = pDC->SelectObject(&penLink);
pDC->MoveTo(iTextLeft, iTextTop + sizeText.cy + 1);
pDC->LineTo(iTextLeft + sizeText.cx, iTextTop + sizeText.cy + 1);
// Move to a new line of text
iTextTop += iNextLine;
csSample = szLoadString(IDS_ACTIVE_LINK_TEXT);
sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
pDC->SetTextColor(m_crActiveLink);
CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
CPen penActive(PS_SOLID, 2, m_crActiveLink);
pDC->SelectObject(&penActive);
pDC->MoveTo(iTextLeft, iTextTop + sizeText.cy + 1);
pDC->LineTo(iTextLeft + sizeText.cx, iTextTop + sizeText.cy + 1);
// Next line
iTextTop += iNextLine;
csSample = szLoadString(IDS_FOLLOWED_LINK);
sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
pDC->SetTextColor(m_crFollowedLink);
CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
CPen penFollowed(PS_SOLID, 2, m_crFollowedLink);
pDC->SelectObject(&penFollowed);
pDC->MoveTo(iTextLeft, iTextTop + sizeText.cy + 1);
pDC->LineTo(iTextLeft + sizeText.cx, iTextTop + sizeText.cy + 1);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
if(m_hPal){
::SelectPalette( pDC->m_hDC, hOldPal, FALSE );
}
// give the CDC back to the system
pPreview->ReleaseDC(pDC);
}
void CDocColorPage::OnNoSave()
{
SetModified(TRUE);
}
////////////////////////////////////////////////////
CDocMetaPage::CDocMetaPage(CWnd* pParent, MWContext * pMWContext,
CEditorResourceSwitcher * pResourceSwitcher)
: CNetscapePropertyPage(CDocMetaPage::IDD),
m_bActivated(FALSE),
m_pMWContext(pMWContext),
m_pResourceSwitcher(pResourceSwitcher)
{
//{{AFX_DATA_INIT(CDocMetaPage)
//}}AFX_DATA_INIT
ASSERT(pMWContext);
#ifdef XP_WIN32
// Set the hInstance so we get template from editor's resource DLL
m_psp.hInstance = AfxGetResourceHandle();
#endif
}
BOOL CDocMetaPage::OnSetActive()
{
if(m_pResourceSwitcher && !m_bActivated){
// We must be sure we have switched
// the first time here - before dialog creation
m_pResourceSwitcher->switchResources();
}
if(!CPropertyPage::OnSetActive())
return(FALSE);
if(m_bActivated)
return(TRUE);
// Switch back to EXE's resources
if( m_pResourceSwitcher ){
m_pResourceSwitcher->Reset();
}
((CEdit*)GetDlgItem(IDC_VAR_NAME))->LimitText(MAX_META_NAME_LEN);
((CEdit*)GetDlgItem(IDC_VAR_VALUE))->LimitText(MAX_META_VALUE_LEN);
// Get all the items for the lists editbox
GetMetaData();
// Setup list for a new meta item
((CListBox*)GetDlgItem(IDC_META_LIST))->SetCurSel(m_iMetaCount);
m_bActivated = TRUE;
return(TRUE);
}
void CDocMetaPage::OnSelchangeEquivList()
{
CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
int iSelEquiv = pEquivList->GetCurSel();
int iSelMeta = pMetaList->GetCurSel();
BOOL bCanSetOrDelete = FALSE;
// Only one list can be selected at a time
// We use selected list as a "radio button" to inform
// user which list the Name/Value pair applies to
pMetaList->SetCurSel(-1);
// Don't set Name and Value if selecting the last item
// unless we are switch from other list
if ( iSelEquiv >= 0 &&
(-1 != iSelMeta ||
iSelEquiv != m_iEquivCount) ) {
CString csEntry;
CString csName;
CString csValue;
pEquivList->GetText(iSelEquiv, csEntry);
if (GetNameAndValue(csEntry, csName, csValue)) {
((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetWindowText( LPCSTR(csName) );
((CEdit*)GetDlgItem(IDC_VAR_VALUE))->SetWindowText( LPCSTR(csValue) );
bCanSetOrDelete = TRUE;
} else {
ClearNameAndValue();
}
} else {
// This will set button states depending on NAME and CONTENT strings
OnChangeVarNameOrValue();
return;
}
SetModified(TRUE);
EnableButtons(bCanSetOrDelete);
}
void CDocMetaPage::OnSelchangeMetaList()
{
CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
int iSelMeta = pMetaList->GetCurSel();
int iSelEquiv = pEquivList->GetCurSel();
BOOL bCanSetOrDelete = FALSE;
// Only one list can be selected at a time
pEquivList->SetCurSel(-1);
// Don't set Name and Value if selecting the last item
// unless we are switch from other list
if ( iSelMeta >= 0 &&
(-1 != iSelEquiv ||
iSelMeta != m_iMetaCount)) {
CString csEntry;
CString csName;
CString csValue;
pMetaList->GetText(iSelMeta, csEntry);
if (GetNameAndValue(csEntry, csName, csValue)) {
((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetWindowText( LPCSTR(csName) );
((CEdit*)GetDlgItem(IDC_VAR_VALUE))->SetWindowText( LPCSTR(csValue) );
bCanSetOrDelete = TRUE;
} else {
ClearNameAndValue();
}
} else {
// This will set button states depending on NAME and CONTENT strings
OnChangeVarNameOrValue();
return;
}
SetModified(TRUE);
EnableButtons(bCanSetOrDelete);
}
// Make clicking below list items the same as
// selecting the last (empty) item so we
// always change lists when clicked on
void CDocMetaPage::OnSetfocusEquivList()
{
if (((CListBox*)GetDlgItem(IDC_EQUIV_LIST))->GetCurSel() == -1 ) {
((CListBox*)GetDlgItem(IDC_EQUIV_LIST))->SetCurSel(m_iEquivCount);
OnSelchangeEquivList();
}
}
void CDocMetaPage::OnSetfocusMetaList()
{
if (((CListBox*)GetDlgItem(IDC_META_LIST))->GetCurSel() == -1 ) {
((CListBox*)GetDlgItem(IDC_META_LIST))->SetCurSel(m_iMetaCount);
OnSelchangeMetaList();
}
}
void CDocMetaPage::OnChangeVarNameOrValue()
{
CString csName;
GetDlgItem(IDC_VAR_NAME)->GetWindowText(csName);
CString csValue;
GetDlgItem(IDC_VAR_VALUE)->GetWindowText(csValue);
CleanupString(csName);
CleanupString(csValue);
GetDlgItem(IDC_VAR_SET)->EnableWindow(!csName.IsEmpty() && !csValue.IsEmpty());
GetDlgItem(IDC_VAR_NEW)->EnableWindow(!csName.IsEmpty() || !csValue.IsEmpty());
GetDlgItem(IDC_VAR_DELETE)->EnableWindow(!csName.IsEmpty() );
SetModified(TRUE);
}
void CDocMetaPage::OnVarSet()
{
CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
CString csName;
GetDlgItem(IDC_VAR_NAME)->GetWindowText(csName);
CString csValue;
GetDlgItem(IDC_VAR_VALUE)->GetWindowText(csValue);
CleanupString(csName);
CleanupString(csValue);
if ( !csName.IsEmpty() ) {
int iEqual = csName.Find('=');
if ( iEqual != -1 ) {
csName = csName.Left(iEqual);
CleanupString(csName);
}
CString csSearch = csName + "=";
BOOL bEquiv;
// We determine which list to use by which was last selected
if ( pEquivList->GetCurSel() != -1 ) {
SetMetaData(TRUE, CHAR_STR(csName), CHAR_STR(csValue));
bEquiv = TRUE;
} else {
SetMetaData(FALSE, CHAR_STR(csName), CHAR_STR(csValue));
bEquiv = FALSE;
}
// Get data and rebuild both listboxes
GetMetaData();
// Set the selection to the blank last item in the list
if (bEquiv) {
pEquivList->SetCurSel(m_iEquivCount);
pMetaList->SetCurSel(-1);
} else {
pMetaList->SetCurSel(m_iMetaCount);
pEquivList->SetCurSel(-1);
}
// Nothing to delete now
((CButton*)GetDlgItem(IDC_VAR_DELETE))->EnableWindow(FALSE);
}
((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetFocus();
}
void CDocMetaPage::OnVarDelete()
{
CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
int nSel = pEquivList->GetCurSel();
CString csSelString;
CString csName;
CString csValue;
BOOL bEquiv = FALSE;
// Get the strings from which ever list has the selected item
if ( nSel != -1 ) {
pEquivList->GetText(nSel, csSelString);
bEquiv = TRUE;
} else {
nSel = pMetaList->GetCurSel();
if ( nSel != -1 ) {
pMetaList->GetText(nSel, csSelString);
}
}
if ( nSel != -1 && GetNameAndValue(csSelString, csName, csValue ) ) {
// TRUE = delete entry in EDT data with selected Name-Value pair
SetMetaData(bEquiv, CHAR_STR(csName), CHAR_STR(csValue), TRUE);
// Rebuild the list
GetMetaData();
SetModified(TRUE);
}
// Set selection to end of list just deleted
// (or to end of meta list if error deleting)
if ( bEquiv ) {
pEquivList->SetCurSel(m_iEquivCount);
} else {
pMetaList->SetCurSel(m_iMetaCount);
}
((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetFocus();
}
void CDocMetaPage::OnVarNew()
{
CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
// Clear the Name-Value edit boxes and
// remove selection in lists
ClearNameAndValue();
// Reset the selected item to the blank at end
// of list already selected
if ( pEquivList->GetCurSel() != -1 ) {
pEquivList->SetCurSel(m_iEquivCount);
pMetaList->SetCurSel(-1);
} else {
pMetaList->SetCurSel(m_iMetaCount);
}
// Disable all buttons
EnableButtons(FALSE);
((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetFocus();
}
void CDocMetaPage::EnableButtons(BOOL bEnable)
{
((CButton*)GetDlgItem(IDC_VAR_SET))->EnableWindow(bEnable);
((CButton*)GetDlgItem(IDC_VAR_DELETE))->EnableWindow(bEnable);
((CButton*)GetDlgItem(IDC_VAR_NEW))->EnableWindow(bEnable);
}
void CDocMetaPage::ClearNameAndValue()
{
((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetWindowText("");
((CEdit*)GetDlgItem(IDC_VAR_VALUE))->SetWindowText("");
EnableButtons(FALSE);
}
void CDocMetaPage::GetMetaData()
{
CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
// Rebuild our list from the Edit data
pEquivList->ResetContent();
pMetaList->ResetContent();
// Name = 100, content = 400
char pName[MAX_META_NAME_LEN+1];
char pValue[MAX_META_VALUE_LEN+1];
CString csEntry;
m_iEquivCount = 0;
m_iMetaCount = 0;
int count = EDT_MetaDataCount(m_pMWContext);
for ( int i = 0; i < count; i++ ) {
EDT_MetaData* pData = EDT_GetMetaData(m_pMWContext, i);
PR_snprintf(pName, MAX_META_NAME_LEN, "%s", pData->pName);
PR_snprintf(pValue, MAX_META_VALUE_LEN, "%s", pData->pContent);
csEntry = pName;
csEntry += "=";
csEntry += pValue;
if ( pData->bHttpEquiv ) {
pEquivList->AddString(csEntry);
m_iEquivCount++;
} else if ( 0 != _stricmp(pName, "Author") &&
0 != _stricmp(pName, "Description") &&
0 != _stricmp(pName, "Generator") &&
0 != _stricmp(pName, "Last-Modified") &&
0 != _stricmp(pName, "Created") &&
0 != _stricmp(pName, "Classification") &&
0 != _stricmp(pName, "Keywords")
/* && 0 != _stricmp(pName, "SourceURL") */
) {
// Skip the fields used in General Info page
// TODO: PUT META STRINGS IN RESOURCES?
pMetaList->AddString(csEntry);
m_iMetaCount++;
}
}
// We add a blank string to each list
// to ensure a selectable item when none really exists
// Note: Listbox should NOT be sorted for this to work right
pEquivList->AddString("");
pMetaList->AddString("");
ClearNameAndValue();
}
// Create a MetaData structure and save it
// This commits change - NO BUFFERING
// Be sure to strip off spaces and quotes before calling this
void CDocMetaPage::SetMetaData(BOOL bHttpEquiv, char * pName, char * pValue, BOOL bDelete)
{
CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
CString csSelString;
CString csName;
CString csValue;
int nSel = pEquivList->GetCurSel();
// Get the strings from which ever list has the selected item
if ( nSel != -1 )
{
pEquivList->GetText(nSel, csSelString);
} else {
nSel = pMetaList->GetCurSel();
if ( nSel != -1 )
pMetaList->GetText(nSel, csSelString);
}
GetNameAndValue(csSelString, csName, csValue);
EDT_MetaData *pData = EDT_NewMetaData();
if ( pData )
{
pData->bHttpEquiv = bHttpEquiv;
if ( pName && XP_STRLEN(pName) > 0 )
{
pData->pName = XP_STRDUP(pName);
if ( pValue && *pValue )
{
pData->pContent = XP_STRDUP(pValue);
if( csName == pName )
{
// The NAME in edit box is same as in the selected item,
// copy the Content value so we replace specifically that item
pData->pPrevContent = XP_STRDUP(CHAR_STR(csValue));
// We want to delete this entry
if( bDelete)
XP_FREEIF(pData->pContent);
}
else
{
// We don't match an existing selection
// Set this so the item is appended to the list
// rather than replacing the first existing item
// with the same name. This allows multiple items.
pData->pPrevContent = pData->pContent;
}
EDT_SetMetaData(m_pMWContext, pData);
}
OkToClose();
}
EDT_FreeMetaData(pData);
}
}
void CDocMetaPage::OnHelp()
{
NetHelp(HELP_DOC_PROPS_ADVANCED);
}
void CDocMetaPage::OnOK()
{
CPropertyPage::OnOK();
// never visited this page or no change -- don't bother
if(!m_bActivated ||
!IS_APPLY_ENABLED(this)){
return;
}
//EDT_BeginBatchChanges(m_pMWContext);
// Set anything in the current Name/Value strings
OnVarSet();
OkToClose();
//EDT_EndBatchChanges(m_pMWContext);
}
void CDocMetaPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDocMetaPage)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDocMetaPage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CDocMetaPage)
ON_LBN_SELCHANGE(IDC_EQUIV_LIST, OnSelchangeEquivList)
ON_LBN_SELCHANGE(IDC_META_LIST, OnSelchangeMetaList)
ON_BN_CLICKED(IDC_VAR_SET, OnVarSet)
ON_BN_CLICKED(IDC_VAR_DELETE, OnVarDelete)
ON_BN_CLICKED(IDC_VAR_NEW, OnVarNew)
ON_EN_CHANGE(IDC_VAR_NAME, OnChangeVarNameOrValue)
ON_EN_CHANGE(IDC_VAR_VALUE, OnChangeVarNameOrValue)
ON_LBN_SETFOCUS(IDC_EQUIV_LIST, OnSetfocusEquivList)
ON_LBN_SETFOCUS(IDC_META_LIST, OnSetfocusMetaList)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// This needs to match contents of Font Size drop-down listbox
// 0 = "Default", 1 - 7 = font sizes, 8 = "Don't Change"
static int iDontChangeFontSizeIndex = 8;
static int iDontChangeFontColorIndex = 0;
///////////////////////////////////////////////////////////////////
CCharacterPage::CCharacterPage(CWnd* pParent,
MWContext *pMWContext,
CEditorResourceSwitcher * pResourceSwitcher,
EDT_CharacterData *pData)
: CNetscapePropertyPage(CCharacterPage::IDD),
m_pMWContext(pMWContext),
m_pResourceSwitcher(pResourceSwitcher),
m_pData(pData),
m_bActivated(0),
m_pPageData(0),
m_crDefault(0),
m_bCustomColor(0),
m_iNoChangeFontSize(0),
m_iNoChangeFontFace(0),
m_iOtherIndex(0),
m_bMultipleFonts(0),
m_bUseDefault(0)
{
//{{AFX_DATA_INIT(CCharacterPage)
//}}AFX_DATA_INIT
ASSERT(pMWContext);
// Could we ever get here and have no data?
// We shouldn't, but maybe we shouldn't assume it here
// and just gray all controls if no character data.
ASSERT(pData);
#ifdef XP_WIN32
// Set the hInstance so we get template from editor's resource DLL
m_psp.hInstance = AfxGetResourceHandle();
#endif
}
void CCharacterPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCharacterPage)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCharacterPage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CCharacterPage)
ON_BN_CLICKED(IDC_OVERRIDE_COLOR, EnableApply)
ON_BN_CLICKED(IDC_DONT_CHANGE_COLOR, EnableApply)
ON_BN_CLICKED(IDC_CHECK_BOLD, EnableApply)
ON_BN_CLICKED(IDC_CHECK_ITALIC, EnableApply)
ON_BN_CLICKED(IDC_CHECK_UNDERLINE, EnableApply)
ON_BN_CLICKED(IDC_CHECK_STRIKETHROUGH, EnableApply)
ON_BN_CLICKED(IDC_CHECK_BLINK, EnableApply)
ON_BN_CLICKED(IDC_CHECK_NOBREAK, EnableApply)
ON_BN_CLICKED(IDC_CHECK_SUBSCRIPT, OnCheckSubscript)
ON_BN_CLICKED(IDC_CHECK_SUPERSCRIPT, OnCheckSuperscript)
ON_BN_CLICKED(IDC_CLEAR_ALL_STYLES, OnClearAllStyles)
ON_BN_CLICKED(IDC_CLEAR_TEXT_STYLES, OnClearTextStyles)
ON_CBN_SELCHANGE(IDC_FONT_SIZE_COMBO, OnSelchangeFontSize)
ON_CBN_SELCHANGE(IDC_FONT_SIZE_COMBO2, OnSelchangeFontSize)
ON_CBN_SELCHANGE(IDC_FONTFACE_COMBO, OnSelchangeFontFace)
ON_CBN_EDITCHANGE(IDC_FONTFACE_COMBO, OnChangeFontFace)
ON_CBN_EDITCHANGE(IDC_FONT_SIZE_COMBO2, EnableApply)
ON_CBN_SELENDOK(IDC_FONTFACE_COMBO, OnSelendokFontFace)
ON_BN_CLICKED(IDC_CHOOSE_COLOR, OnChooseColor)
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// ON_BN_CLICKED(IDC_CHOOSE_FONT, OnChooseLocalFont)
BOOL CCharacterPage::OnSetActive()
{
if(m_pResourceSwitcher && !m_bActivated){
// We must be sure we have switched
// the first time here - before dialog creation
m_pResourceSwitcher->switchResources();
}
if(!CPropertyPage::OnSetActive())
return FALSE;
if(m_bActivated)
return TRUE;
// Switch back to EXE's resources
if( m_pResourceSwitcher ){
m_pResourceSwitcher->Reset();
}
m_pPageData = EDT_GetPageData(m_pMWContext);
if( m_pPageData == NULL ){
return FALSE;
}
// Note: Don't set m_bActivated yet! -- SEE BELOW
// Attach color picker button to our color button class
if( !m_TextColorButton.Subclass(this, IDC_CHOOSE_COLOR, &m_crColor) ){
return FALSE;
}
// Get the "Default" color used by the Browser
m_crDefault = prefInfo.m_rgbForegroundColor;
// Get current color at cursor or selection
m_crColor = WFE_GetCurrentFontColor(m_pMWContext);
BOOL bUseColor = TRUE;
if( m_crColor == DEFAULT_COLORREF){
// Show the default color on the button
m_crColor = m_crDefault;
m_bUseDefault = TRUE;
}
if( m_crColor == MIXED_COLORREF ){
// Change the text on radio button to: "Don't change (mixed colors)
GetDlgItem(IDC_DONT_CHANGE_COLOR)->SetWindowText(szLoadString(IDS_MIXED_COLORS));
((CButton*)GetDlgItem(IDC_DONT_CHANGE_COLOR))->SetCheck(1);
} else {
((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->SetCheck(1);
}
// Attach CNSComboBox class to existing control to do user-drawing
if( !m_FontFaceCombo.Subclass(this, IDC_FONTFACE_COMBO) ){
return FALSE;
}
// Fill the combobox with global lists of fonts (MUST BE STATIC STRINGS!)
// This will add "Other..." at bottom of list only if too many fonts are installed
m_iOtherIndex = wfe_FillFontComboBox(&m_FontFaceCombo);
// Get current font face and index to it in font list
char * pFace = EDT_GetFontFace(m_pMWContext);
int iFontIndex = m_FontFaceCombo.FindSelectedOrSetText(pFace);
// Save whether or not we have mulitple fonts at startup
m_bMultipleFonts = (pFace == NULL);
char * pNoChangeText = m_bMultipleFonts ? ed_pMixedFonts : ed_pDontChange;
// Add the "Dont Change" item at the bottom
m_iNoChangeFontFace = m_FontFaceCombo.AddString(pNoChangeText);
// Set the message explaining the font after selecting it in listbox
SetFontFaceMessage(iFontIndex);
// We need to rebuild font size display if font face changes from
// Variable to Fixed Width or vice versa, so monitor state
m_bFixedWidth = (iFontIndex == 1);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_BOLD)),TF_BOLD);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_ITALIC)), TF_ITALIC);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_UNDERLINE)), TF_UNDERLINE);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_STRIKETHROUGH)), TF_STRIKEOUT);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT)), TF_SUPER);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT)), TF_SUB);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_BLINK)), TF_BLINK);
InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_NOBREAK)), TF_NOBREAK);
// We have 2 comboboxes: 1 droplist for regular (relative size) mode,
// and combobox with edit style for advanced mode
if( !m_FontSizeCombo.Subclass(this, wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ?
IDC_FONT_SIZE_COMBO2 : IDC_FONT_SIZE_COMBO) ){
return FALSE;
}
// Hide the combobox we will not use
GetDlgItem(wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ? IDC_FONT_SIZE_COMBO : IDC_FONT_SIZE_COMBO2)->ShowWindow(SW_HIDE);
// Fill Font Size combo. 3rd param is TRUE if font face = Fixed Width
wfe_FillFontSizeCombo(m_pMWContext, &m_FontSizeCombo, m_bFixedWidth);
// Add the "Dont Change" item at the bottom
m_iNoChangeFontSize = m_FontSizeCombo.AddString(ed_pDontChange);
// Change message to that describing advanced mode
if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ){
GetDlgItem(IDC_FONT_SIZE_MSG)->SetWindowText(szLoadString(IDS_ADVANCED_FONTSIZE_MSG));
}
// Set FontSize combobox selected
int iSel = -1;
if( m_pData->mask & TF_FONT_SIZE ){
// If no size, use default instead
iSel = m_pData->iSize ? m_pData->iSize - 1 : 2;
m_FontSizeCombo.SetCurSel(iSel);
// Weird -- we must set string manually
char * pSelected = (char*)m_FontSizeCombo.GetItemData(iSel);
if( *pSelected == '_'){
pSelected++;
}
m_FontSizeCombo.SetWindowText(pSelected);
} else if( (m_pData->mask & TF_FONT_POINT_SIZE) && m_pData->iPointSize ){
char pSize[16];
wsprintf(pSize, "%d", m_pData->iPointSize);
m_FontSizeCombo.FindSelectedOrSetText(pSize, MAX_FONT_SIZE);
}
// We set this last because initialization
// uses it to know first-time through
m_bActivated = TRUE;
// Send data to controls
UpdateData(FALSE);
return(TRUE);
}
void CCharacterPage::OnHelp()
{
NetHelp(HELP_PROPS_CHARACTER);
}
BOOL CCharacterPage::OnKillActive()
{
if( ! GetAndValidateFontSizes() ){
return FALSE;
}
// Contrary to MFC help, this does NOT call our OnOK
return CPropertyPage::OnKillActive();
}
BOOL CCharacterPage::GetAndValidateFontSizes()
{
int iSel = m_FontSizeCombo.GetCurSel();
if( iSel == iDontChangeFontSizeIndex ||
(iSel == -1 && wfe_iFontSizeMode != ED_FONTSIZE_ADVANCED) ){
// Ignore this attribute
FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
return TRUE;
}
if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED){
CString csAbsoluteSize;
m_FontSizeCombo.GetWindowText(csAbsoluteSize);
csAbsoluteSize.TrimLeft();
csAbsoluteSize.TrimRight();
// Empty is OK - same as "Don't change"
// So get the Relative size
if( csAbsoluteSize.IsEmpty() ){
// We may be ignore this attribute if no
// relative size is selected
FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
m_pData->iPointSize = 0;
} else if( iSel == -1 || iSel >= MAX_FONT_SIZE ){
char* pEnd;
int32 iSize = (int)strtol( LPCSTR(csAbsoluteSize), &pEnd, 10 );
// Bad conversion if end pointer isn't at terminal null;
if( *pEnd != '\0' ||
iSize < MIN_FONT_SIZE_RELATIVE ||
iSize > ED_FONT_POINT_SIZE_MAX ){
char szMessage[256];
// Construct a string showing correct range
wsprintf( szMessage, szLoadString(IDS_INTEGER_RANGE_ERROR),
ED_FONT_POINT_SIZE_MIN, ED_FONT_POINT_SIZE_MAX );
// Notify user with similar message to the DDV_ validation system
MessageBox(szMessage, szLoadString(AFX_IDS_APP_TITLE), MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
if( iSize >= MIN_FONT_SIZE_RELATIVE && iSize <= 4 ){
// Assume they really wanted the Relative scale
iSel = iSize + 3;
m_pData->iPointSize = 0;
} else {
// Size is OK - store it
m_pData->iPointSize = (int16)iSize;
// Set bit mask to indicate we want PointSize, not HTML relative size
FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
FE_SET_BIT(m_pData->mask, TF_FONT_POINT_SIZE);
FE_SET_BIT(m_pData->values, TF_FONT_POINT_SIZE);
m_pData->iPointSize = (int16)iSize;
}
}
}
if( m_pData->iPointSize == 0){
if( m_iNoChangeFontSize > 0 && iSel == m_iNoChangeFontSize ){
// Clear the bit so we will ignore this attribute
FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
} else if( iSel >= 0 && iSel < MAX_FONT_SIZE ){
// Set the size to the designated value - XP handles default
// (3rd item = "default", i.e., no SIZE param written)
FE_SET_BIT(m_pData->mask, TF_FONT_SIZE);
FE_SET_BIT(m_pData->values, TF_FONT_SIZE);
m_pData->iSize = iSel+1;
}
}
return TRUE;
}
void CCharacterPage::OnOK()
{
CPropertyPage::OnOK();
// never visited this page or no change -- don't bother
if(!m_bActivated ||
!IS_APPLY_ENABLED(this)){
return;
}
//EDT_BeginBatchChanges(m_pMWContext);
if( !GetAndValidateFontSizes() ){
return;
}
// Set color if checkbox is checked
if( ((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->GetCheck() ){
if( m_bUseDefault ){
// Set the color to the default size by
// setting mask bit and clearing value
FE_SET_BIT(m_pData->mask, TF_FONT_COLOR);
FE_CLEAR_BIT(m_pData->values, TF_FONT_COLOR);
} else {
// Set the color to the designated value
FE_SET_BIT(m_pData->mask, TF_FONT_COLOR);
FE_SET_BIT(m_pData->values, TF_FONT_COLOR);
WFE_SetLO_ColorPtr( m_crColor, &m_pData->pColor );
}
} else {
// Ignore this attribute
FE_CLEAR_BIT(m_pData->mask, TF_FONT_COLOR);
}
int iSel = m_FontFaceCombo.GetCurSel();
CString csFace;
char * pNewFace = NULL;
if( iSel == -1 ){
m_FontFaceCombo.GetWindowText(csFace);
csFace.TrimLeft();
csFace.TrimRight();
if( !csFace.IsEmpty() ){
// We have a local font name
pNewFace = (char*)LPCSTR(csFace);
FE_SET_BIT(m_pData->mask, TF_FONT_FACE);
}
} else if( m_iNoChangeFontFace > 0 && iSel == m_iNoChangeFontFace ){
// Clear the bit so we will ignore this attribute
FE_CLEAR_BIT(m_pData->mask, TF_FONT_FACE);
} else {
// We may be sure of the font and its in our list
// (EDT_SetFontFace will set default variable or fixed width
// correctly using the supplied "font face" string
FE_SET_BIT(m_pData->mask, TF_FONT_FACE);
// Get pointer to fontface string in combobox
pNewFace = (char*)m_FontFaceCombo.GetItemData(iSel);
}
// Set the bits in our data struct
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_BOLD)), TF_BOLD);
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_ITALIC)), TF_ITALIC);
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_UNDERLINE)), TF_UNDERLINE);
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_STRIKETHROUGH)), TF_STRIKEOUT);
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT)), TF_SUPER);
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT)), TF_SUB);
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_BLINK)), TF_BLINK);
SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_NOBREAK)), TF_NOBREAK);
// Set font face in the supplied struct and set all character data
EDT_SetFontFace(m_pMWContext, m_pData, iSel, pNewFace);
OkToClose();
//EDT_EndBatchChanges(m_pMWContext);
}
void CCharacterPage::InitCheckbox(CButton *pButton, ED_TextFormat tf)
{
// Get current style but clear all relevant button-style bits
UINT nStyle = CASTUINT(pButton->GetButtonStyle() & 0xFFFFFFF0L);
if( m_pData->mask & tf ) {
// We know the style, so we can use 2-state boxes
nStyle |= BS_AUTOCHECKBOX;
} else {
// We don't know the style, so we use 3-state boxes
// so user can return to the "don't change" state
nStyle |= BS_AUTO3STATE;
}
pButton->SetButtonStyle(nStyle);
SetCheck(pButton, tf);
}
int CCharacterPage::SetCheck(CButton *pButton, ED_TextFormat tf)
{
int iCheck = 2; // Uncertain/mixed state
if( m_pData->mask & tf){
iCheck = (m_pData->values & tf) ? 1 : 0;
}
pButton->SetCheck(iCheck);
return iCheck;
}
void CCharacterPage::SetCharacterStyle(CButton *pButton, ED_TextFormat tf)
{
int iCheck = pButton->GetCheck();
if( iCheck == 2 ){
// Don't change this style - clear mask bit
FE_CLEAR_BIT(m_pData->mask,tf);
} else {
// Set the style -- set mask bit
FE_SET_BIT(m_pData->mask, tf);
}
if( iCheck == 1){
// Set the value bit
FE_SET_BIT(m_pData->values,tf);
} else {
FE_CLEAR_BIT(m_pData->values,tf);
}
}
void CCharacterPage::OnChooseLocalFont()
{
CFontDialog dlg(NULL, CF_SCREENFONTS | CF_TTONLY | CF_NOSIZESEL | CF_NOSTYLESEL | CF_NOSCRIPTSEL, NULL, this);
if( dlg.DoModal() ){
CString csNewFont = dlg.GetFaceName();
CString csStyle = dlg.GetStyleName();
int iSize = dlg.GetSize();
m_FontFaceCombo.SetWindowText(LPCSTR(csNewFont));
GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText(szLoadString(IDS_TRUE_TYPE));
SetModified(TRUE);
}
}
void CCharacterPage::OnChooseColor()
{
// Get the combobox location so we popup new dialog just under it
RECT rect;
GetDlgItem(IDC_CHOOSE_COLOR)->GetWindowRect(&rect);
CColorPicker ColorPicker(this, m_pMWContext, m_crColor, DEFAULT_COLORREF, IDS_TEXT_COLOR, &rect);
COLORREF crNew = ColorPicker.GetColor();
if( crNew != CANCEL_COLORREF ){
if( crNew == DEFAULT_COLORREF ){
m_crColor = m_crDefault;
m_bUseDefault = TRUE;
} else {
m_crColor = crNew;
m_bUseDefault = FALSE;
}
// Refresh color button
m_TextColorButton.Update();
// Set radio buttons to show "Use color"
((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->SetCheck(1);
((CButton*)GetDlgItem(IDC_DONT_CHANGE_COLOR))->SetCheck(0);
SetModified(TRUE);
}
}
void CCharacterPage::EnableApply()
{
SetModified(TRUE);
}
void CCharacterPage::OnCheckSubscript()
{
// Super and Sub are mutually exclusive
// Problem: This wipes out mixed-state items!
if( ((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT))->GetCheck() == 1 ){
((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT))->SetCheck(0);
}
SetModified(TRUE);
}
void CCharacterPage::OnCheckSuperscript()
{
// Super and Sub are mutually exclusive
// Problem: This wipes out mixed-state items!
if( ((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT))->GetCheck() == 1 ){
((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT))->SetCheck(0);
}
SetModified(TRUE);
}
// Next 2 don't change the doc,
// just change the control states
void CCharacterPage::OnClearAllStyles()
{
// Remove all styles in the controls
// Set to the "default" font size
m_FontSizeCombo.SetCurSel(2);
// Update the display
OnSelchangeFontSize();
// Set to default color
m_bUseDefault = TRUE;
m_crColor = m_crDefault;
m_TextColorButton.Update();
((CButton*)GetDlgItem(IDC_DONT_CHANGE_COLOR))->SetCheck(0);
((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->SetCheck(1);
// Set to default variable font face
m_FontFaceCombo.SetCurSel(0);
OnSelchangeFontFace();
OnClearTextStyles();
}
void CCharacterPage::OnClearTextStyles()
{
((CButton*)GetDlgItem(IDC_CHECK_BOLD))->SetCheck(0);
((CButton*)GetDlgItem(IDC_CHECK_ITALIC))->SetCheck(0);
((CButton*)GetDlgItem(IDC_CHECK_UNDERLINE))->SetCheck(0);
((CButton*)GetDlgItem(IDC_CHECK_STRIKETHROUGH))->SetCheck(0);
((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT))->SetCheck(0);
((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT))->SetCheck(0);
((CButton*)GetDlgItem(IDC_CHECK_BLINK))->SetCheck(0);
((CButton*)GetDlgItem(IDC_CHECK_NOBREAK))->SetCheck(0);
SetModified(TRUE);
}
void CCharacterPage::OnChangeFontFace()
{
GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText("");
SetModified(TRUE);
// Do any autosearch here?
}
void CCharacterPage::SetFontFaceMessage(int iSel)
{
UINT nID;
if( iSel == -1 ||
(iSel == m_iNoChangeFontFace && !m_bMultipleFonts) ||
(m_iOtherIndex && iSel == m_iOtherIndex) ){
GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText("");
return;
}
if( iSel == m_iNoChangeFontFace ){
nID = IDS_MULTIPLE_FONTS;
} else if( iSel == 0){
nID = IDS_DEFAULT_VARIABLE;
} else if ( iSel == 1 ){
nID = IDS_DEFAULT_FIXED_WIDTH;
} else {
char * pFace = (char*)m_FontFaceCombo.GetItemData(iSel);
// Give a different message if we find an "XP" font face
if( pFace != EDT_TranslateToXPFontFace(pFace) ){
nID = IDS_XP_FONT;
} else {
nID = IDS_LOCAL_FONT;
}
}
GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText(szLoadString(nID));
}
void CCharacterPage::OnSelchangeFontFace()
{
int iSel = m_FontFaceCombo.GetCurSel();
if( m_iOtherIndex && iSel == m_iOtherIndex ){
m_FontFaceCombo.SetCurSel(-1);
iSel = -1;
}
if( iSel >= 0 ){
char * pSelected = (char*)m_FontFaceCombo.GetItemData(iSel);
if( *pSelected == '_'){
pSelected++;
}
m_FontFaceCombo.SetWindowText(pSelected);
}
// Rebuild font size list if changing from variable to fixed width or vice versa
if( m_bFixedWidth != (iSel == 1) ){
m_bFixedWidth = (iSel == 1);
wfe_FillFontSizeCombo(m_pMWContext, &m_FontSizeCombo, m_bFixedWidth);
}
SetFontFaceMessage(iSel);
SetModified(TRUE);
}
void CCharacterPage::OnSelendokFontFace()
{
int iSel = m_FontFaceCombo.GetCurSel();
if( m_iOtherIndex &&
iSel == m_iOtherIndex ){
m_FontFaceCombo.SetCurSel(-1);
OnChooseLocalFont();
return;
}
}
void CCharacterPage::OnSelchangeFontSize()
{
// User can use the last item to not change any sizes,
// but it looks better to show blank combobox field
int iSel = m_FontSizeCombo.GetCurSel();
if( iSel == iDontChangeFontSizeIndex ){
m_FontSizeCombo.SetCurSel(-1);
}
if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ){
// We must set text manually in edit box
if( iSel >= 0 ){
char * pSelected = (char*)m_FontSizeCombo.GetItemData(iSel);
if( *pSelected == '_'){
pSelected++;
}
m_FontSizeCombo.SetWindowText(pSelected);
} else {
m_FontSizeCombo.SetWindowText("");
}
} else {
m_pData->iPointSize = 0;
}
SetModified(TRUE);
}
void CCharacterPage::OnClose()
{
// Free extra data we allocated
if( m_pPageData ){
EDT_FreePageData(m_pPageData);
}
CNetscapePropertyPage::OnClose();
}
///////////////////////////////////////////////////////////////////
/*
// For quick reference:
typedef enum {
ED_LIST_TYPE_DEFAULT,
ED_LIST_TYPE_DIGIT,
ED_LIST_TYPE_ROMAN,
ED_LIST_TYPE_BIG_LETTERS,
ED_LIST_TYPE_SMALL_LETTERS,
ED_LIST_TYPE_CIRCLE,
ED_LIST_TYPE_SQUARE,
ED_LIST_TYPE_DISC,
} ED_ListType;
struct _EDT_ListData {
intn iTagType; P_UNUM_LIST, P_NUM_LIST, P_BLOCKQUOTE, P_DESC_LIST
Bool bCompact;
ED_ListType eType;
int iStart; automatically maps, start is 1
};
*/
//Container styles:
enum {
ED_NO_CONTAINER,
ED_LIST,
ED_BLOCKQUOTE
};
// List Styles
enum {
ED_UNUM_LIST,
ED_NUM_LIST,
ED_DESC_LIST
};
//Numbered List Item styles
enum {
ED_AUTOMATIC,
ED_DIGIT,
ED_BIG_ROMAN,
ED_SMALL_ROMAN,
ED_BIG_LETTERS,
ED_SMALL_LETTERS
};
//Unumbered List Item styles
enum {
ED_SOLID_CIRCLE = 1, // We share ED_AUTOMATIC,
ED_OPEN_CIRCLE,
ED_SOLID_SQUARE
};
#define ED_DEFAULT -1
// This is in edframe.cpp. Its the tag types that map
// onto the listbox index, just as in the paragraph format toolbar
extern TagType FEED_nParagraphTags[];
// Fixed index values for Paragraph tags list
#define ED_PARA_NORMAL 0
#define ED_PARA_LIST 9
#define ED_PARA_DESC_TITLE 10
#define ED_PARA_DESC_TEXT 11
/////////////////////////////////////////
// Paragraph / Lists / Alignment
//
CParagraphPage::CParagraphPage(CWnd* pParent, MWContext * pMWContext,
CEditorResourceSwitcher * pResourceSwitcher)
: CNetscapePropertyPage(CParagraphPage::IDD),
m_pMWContext(pMWContext),
m_pResourceSwitcher(pResourceSwitcher),
m_pListData(NULL),
m_bActivated(0),
m_Align(ED_ALIGN_LEFT),
m_iParagraphStyle(0),
m_iContainerStyle(0),
m_iListStyle(-1),
m_iBulletStyle(0),
m_iNumberStyle(0),
m_iMixedStyle(0)
{
//{{AFX_DATA_INIT(CParagraphPage)
m_iStartNumber = 1;
m_bCompact = FALSE;
//}}AFX_DATA_INIT
ASSERT(pMWContext);
#ifdef XP_WIN32
// Set the hInstance so we get template from editor's resource DLL
m_psp.hInstance = AfxGetResourceHandle();
#endif
}
void CParagraphPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CParagraphPage)
DDX_Text(pDX, IDC_LIST_START_NUMBER, m_iStartNumber);
DDV_MinMaxInt(pDX, m_iStartNumber, 1, 10000);
DDX_Check(pDX, IDC_COMPACT_LIST, m_bCompact);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CParagraphPage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CParagraphPage)
ON_BN_CLICKED(IDC_ALIGN_CENTER, OnAlignCenter)
ON_BN_CLICKED(IDC_ALIGN_LEFT, OnAlignLeft)
ON_BN_CLICKED(IDC_ALIGN_RIGHT, OnAlignRight)
ON_CBN_SELCHANGE(IDC_CONTAINER_STYLES, OnSelchangeContainerStyle)
ON_CBN_SELCHANGE(IDC_LIST_ITEM_STYLES, OnSelchangeListItemStyle)
ON_EN_CHANGE(IDC_LIST_START_NUMBER, OnChangeListStartNumber)
ON_CBN_SELCHANGE(IDC_LIST_STYLES, OnSelchangeListStyles)
ON_CBN_SELCHANGE(IDC_PARAGRAPH_STYLES, OnSelchangeParagraphStyles)
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CParagraphPage::OnSetActive()
{
int i;
if(m_pResourceSwitcher && !m_bActivated){
// We must be sure we have switched
// the first time here - before dialog creation
m_pResourceSwitcher->switchResources();
}
if(!CPropertyPage::OnSetActive())
return(FALSE);
if(m_bActivated)
return(TRUE);
// Switch back to EXE's resources
if( m_pResourceSwitcher ){
m_pResourceSwitcher->Reset();
}
m_bActivated = TRUE;
CComboBox * pContainerStyles;
CComboBox * pListStyles;
// Initialize alignment param and radio buttons
m_Align = EDT_GetParagraphAlign( m_pMWContext );
switch (m_Align) {
case ED_ALIGN_CENTER:
case ED_ALIGN_ABSCENTER:
((CButton*)GetDlgItem(IDC_ALIGN_CENTER))->SetCheck(1);
break;
case ED_ALIGN_RIGHT:
((CButton*)GetDlgItem(IDC_ALIGN_RIGHT))->SetCheck(1);
break;
default:
((CButton*)GetDlgItem(IDC_ALIGN_LEFT))->SetCheck(1);
// We end up here for ED_ALIGN_DEFAULT as well as ED_ALIGN_LEFT
m_Align = ED_ALIGN_LEFT;
break;
}
CComboBox *pParagraphStyles = (CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES);
m_ParagraphFormat = EDT_GetParagraphFormatting(m_pMWContext);
//Try to get Container data
// (We can't do this just for list because we may be
// a block quote, which may have any paragraph style)
m_pListData = EDT_GetListData(m_pMWContext);
// Fill the Paragraph styles list:
for ( i = 0; FEED_nParagraphTags[i] != P_UNKNOWN; i++ ){
// Major KLUDGE: We want "Description List" to appear in Toolbar Combobox,
// but not in this combobox - we put it in List Styles combo instead
// if( FEED_nParagraphTags[i] != P_DESC_LIST)
pParagraphStyles->AddString(szLoadString(
CASTUINT(ID_LIST_TEXT_PARAGRAPH_BASE+FEED_nParagraphTags[i])));
}
// We will add another item at end to allow user to see
// "Mixed (don't change)" in listbox
m_iMixedStyle = i;
// Figure out the Paragraph style:
if( m_ParagraphFormat == P_UNKNOWN ){
m_iParagraphStyle = m_iMixedStyle;
pParagraphStyles->AddString(szLoadString(IDS_MIXED_STYLE));
}
else for( i = 0; FEED_nParagraphTags[i] != P_UNKNOWN; i++ ){
if( FEED_nParagraphTags[i] == m_ParagraphFormat ){
m_iParagraphStyle = i;
break;
}
}
if( m_pListData ) {
m_iContainerStyle = ED_LIST;
switch( m_pListData->iTagType ){
case P_UNUM_LIST:
m_iListStyle = ED_UNUM_LIST;
break;
case P_NUM_LIST:
m_iListStyle = ED_NUM_LIST;
m_iStartNumber = CASTINT(m_pListData->iStart);
break;
case P_BLOCKQUOTE:
m_iContainerStyle = ED_BLOCKQUOTE;
m_iListStyle = ED_DEFAULT;
break;
case P_DESC_LIST:
m_iListStyle = ED_DESC_LIST;
break;
}
m_iBulletStyle = m_iNumberStyle = ED_DEFAULT;
switch( m_pListData->eType ){
case ED_LIST_TYPE_DIGIT:
m_iNumberStyle = ED_DIGIT;
break;
case ED_LIST_TYPE_BIG_ROMAN:
m_iNumberStyle = ED_BIG_ROMAN;
break;
case ED_LIST_TYPE_SMALL_ROMAN:
m_iNumberStyle = ED_SMALL_ROMAN;
break;
case ED_LIST_TYPE_BIG_LETTERS:
m_iNumberStyle = ED_BIG_LETTERS;
break;
case ED_LIST_TYPE_SMALL_LETTERS:
m_iNumberStyle = ED_SMALL_LETTERS;
break;
case ED_LIST_TYPE_DISC:
m_iBulletStyle = ED_SOLID_CIRCLE;
break;
case ED_LIST_TYPE_CIRCLE:
m_iBulletStyle = ED_OPEN_CIRCLE;
break;
case ED_LIST_TYPE_SQUARE:
m_iBulletStyle = ED_SOLID_SQUARE;
break;
}
m_bCompact = m_pListData->bCompact;
} else {
m_iContainerStyle = ED_NO_CONTAINER;
}
VERIFY(pContainerStyles = (CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES));
VERIFY(pListStyles = (CComboBox*)GetDlgItem(IDC_LIST_STYLES));
// Fill the Container styles list
pContainerStyles->AddString(szLoadString(IDS_DEFAULT));
pContainerStyles->AddString(szLoadString(IDS_LIST));
pContainerStyles->AddString(szLoadString(IDS_BLOCK_QUOTE));
// Fill the List styles list
pListStyles->AddString(szLoadString(IDS_UNUM_LIST));
pListStyles->AddString(szLoadString(IDS_NUM_LIST));
pListStyles->AddString(szLoadString(IDS_DESCRIPTION_LIST));
// Remove/rebuild item styles depending on current state
UpdateLists();
// TODO - How to get current alignment?
// (Set align radio button to this value)
// Send data to controls
UpdateData(FALSE);
return(TRUE);
}
void CParagraphPage::OnHelp()
{
NetHelp(HELP_PROPS_PARAGRAPH);
}
void CParagraphPage::OnOK()
{
CPropertyPage::OnOK();
// never visited this page or no change -- don't bother
if(!m_bActivated ||
!IS_APPLY_ENABLED(this)){
return;
}
//EDT_BeginBatchChanges(m_pMWContext);
m_iParagraphStyle = ((CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES))->GetCurSel();
m_iContainerStyle = ((CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES))->GetCurSel();
m_iListStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
// Set alignment if it was changed
EDT_SetParagraphAlign( m_pMWContext, m_Align );
// Default values
TagType iTagType = P_UNUM_LIST;
ED_ListType iListItemType = ED_LIST_TYPE_DEFAULT;
CComboBox * pListItemStyles = (CComboBox*)GetDlgItem(IDC_LIST_ITEM_STYLES);
if( m_iContainerStyle == ED_BLOCKQUOTE ){
iTagType = P_BLOCKQUOTE;
} else if( m_iContainerStyle == ED_LIST ){
switch( m_iListStyle ){
case ED_NUM_LIST:
iTagType = P_NUM_LIST;
break;
case ED_DESC_LIST:
iTagType = P_DESC_LIST;
break;
//Note: UNUM_LIST is default
}
if( iTagType == P_UNUM_LIST ) {
m_iBulletStyle = pListItemStyles->GetCurSel();
switch( m_iBulletStyle ){
case ED_SOLID_CIRCLE:
iListItemType = ED_LIST_TYPE_DISC;
break;
case ED_OPEN_CIRCLE:
iListItemType = ED_LIST_TYPE_CIRCLE;
break;
case ED_SOLID_SQUARE:
iListItemType = ED_LIST_TYPE_SQUARE;
break;
}
} else if( iTagType == P_NUM_LIST ) {
m_iNumberStyle = pListItemStyles->GetCurSel();
switch( m_iNumberStyle ){
case ED_DIGIT:
iListItemType = ED_LIST_TYPE_DIGIT;
break;
case ED_BIG_ROMAN:
iListItemType = ED_LIST_TYPE_BIG_ROMAN;
break;
case ED_SMALL_ROMAN:
iListItemType = ED_LIST_TYPE_SMALL_ROMAN;
break;
case ED_BIG_LETTERS:
iListItemType = ED_LIST_TYPE_BIG_LETTERS;
break;
case ED_SMALL_LETTERS:
iListItemType = ED_LIST_TYPE_SMALL_LETTERS;
break;
}
}
}
// We should have been maintaining paragraph style
// to match container/list style, so this should work
// But if "Don't change" style, NEVER set the container style
// NOTE: This will remove any list if new container format is not appropriate
if( m_iParagraphStyle != m_iMixedStyle ){
TagType NewFormat = FEED_nParagraphTags[m_iParagraphStyle];
if( m_ParagraphFormat != NewFormat ){
EDT_MorphContainer( m_pMWContext, NewFormat);
// Get the list data for the new list we might have created
// or if we destroyed the list by changing paragraph style
m_pListData = EDT_GetListData(m_pMWContext);
// Save the new format
m_ParagraphFormat = NewFormat;
}
}
// Set List type and attributes
if ( m_pListData ) {
// If no container, we Outdented above, so don't set data here
if( m_iContainerStyle != ED_NO_CONTAINER ) {
m_pListData->iTagType = iTagType;
m_pListData->eType = iListItemType;
m_pListData->bCompact = m_bCompact;
m_pListData->iStart = m_iStartNumber;
// Now we can change the list attribute:
EDT_SetListData( m_pMWContext, m_pListData );
}
}
OkToClose();
//EDT_EndBatchChanges(m_pMWContext);
}
// Set listbox selected items depending on current state
// Primary key is m_iContainerStyle
// Other style values will be kept but ignored when setting
// selected item or disabling/enabling dependent listboxes
// Goal is to show list style and bullet/numbering only if appropriate
//
void CParagraphPage::UpdateLists()
{
// Set selected items
((CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES))->SetCurSel(m_iParagraphStyle);
((CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES))->SetCurSel(m_iContainerStyle);
// Remove and disable the selection in List Styles if not a List,
// else show what kind of list it is
((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->SetCurSel(
m_iContainerStyle == ED_LIST ? m_iListStyle : -1);
((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->EnableWindow(m_iContainerStyle == ED_LIST);
// Rebuild the List Items styles list
CComboBox * pListItemStyles = (CComboBox*)GetDlgItem(IDC_LIST_ITEM_STYLES);
pListItemStyles->ResetContent();
CWnd *pListItemLabel = GetDlgItem(IDC_LIST_ITEM_LABEL);
BOOL bEnableStartNumber = FALSE;
BOOL bEnableItemList = FALSE;
if ( m_iContainerStyle == ED_LIST ){
if( m_iListStyle == ED_UNUM_LIST ||
m_iListStyle == ED_NUM_LIST ){
pListItemStyles->EnableWindow(TRUE);
pListItemStyles->AddString(szLoadString(IDS_AUTOMATIC));
bEnableItemList = TRUE;
if( m_iListStyle == ED_UNUM_LIST ){
// Be sure we are at least on the first item
m_iBulletStyle = max(0,m_iBulletStyle);
pListItemStyles->AddString(szLoadString(IDS_SOLID_CIRCLE));
pListItemStyles->AddString(szLoadString(IDS_OPEN_CIRCLE));
pListItemStyles->AddString(szLoadString(IDS_SOLID_SQUARE));
pListItemStyles->SetCurSel(m_iBulletStyle);
pListItemLabel->SetWindowText(szLoadString(IDS_BULLET_STYLE));
} else if( m_iListStyle == ED_NUM_LIST ){
m_iNumberStyle = max(0,m_iNumberStyle);
pListItemStyles->AddString(szLoadString(IDS_DIGIT));
pListItemStyles->AddString(szLoadString(IDS_BIG_ROMAN));
pListItemStyles->AddString(szLoadString(IDS_SMALL_ROMAN));
pListItemStyles->AddString(szLoadString(IDS_BIG_LETTERS));
pListItemStyles->AddString(szLoadString(IDS_SMALL_LETTERS));
pListItemStyles->SetCurSel(m_iNumberStyle);
pListItemLabel->SetWindowText(szLoadString(IDS_NUMBER_STYLE));
bEnableStartNumber = TRUE;
}
}
}
// Set enable depending on bullet or number styles
pListItemStyles->EnableWindow(bEnableItemList);
if( !bEnableItemList ) {
// Remove label if disabled
pListItemLabel->SetWindowText("");
}
// Disable start number if not a numbered list
GetDlgItem(IDC_LIST_START_NUMBER)->EnableWindow(bEnableStartNumber);
}
void CParagraphPage::ChangeParagraphStyle()
{
// Selecting one of the list item will force a list container
if( m_iParagraphStyle == ED_PARA_LIST )
{
m_iContainerStyle = ED_LIST;
// Either numbered or unnumbered list style is OK
if( m_iListStyle != ED_NUM_LIST )
m_iListStyle = ED_UNUM_LIST;
else if( m_iListStyle != ED_UNUM_LIST )
m_iListStyle = ED_NUM_LIST;
}
else if( m_iParagraphStyle == ED_PARA_DESC_TITLE || m_iParagraphStyle == ED_PARA_DESC_TEXT)
{
m_iContainerStyle = ED_LIST;
//if( m_iListStyle == ED_DEFAULT )
m_iListStyle = ED_DESC_LIST;
} else if( m_iContainerStyle == ED_LIST ){
// Remove List container
// Note that it is left as is for BLOCK QUOTE
m_iContainerStyle = ED_NO_CONTAINER;
}
UpdateLists();
}
void CParagraphPage::OnSelchangeParagraphStyles()
{
SetModified(TRUE);
m_iParagraphStyle = ((CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES))->GetCurSel();
ChangeParagraphStyle();
}
void CParagraphPage::OnSelchangeContainerStyle()
{
SetModified(TRUE);
m_iContainerStyle = ((CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES))->GetCurSel();
// Force List paragraph style
if( m_iContainerStyle == ED_LIST )
{
// If not already a list item, set it now
if( m_iParagraphStyle < ED_PARA_LIST )
m_iParagraphStyle = ED_PARA_LIST;
}
else if( m_iParagraphStyle >= ED_PARA_LIST )
{
// For no container or BLOCKQUOTE,
// any list item must be converted to normal
m_iParagraphStyle = ED_PARA_NORMAL;
}
ChangeParagraphStyle();
}
void CParagraphPage::OnSelchangeListStyles()
{
SetModified(TRUE);
m_iListStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
if( m_iListStyle == ED_DESC_LIST )
{
// Set appropriate paragraph style for definition list
if( m_iParagraphStyle < ED_PARA_DESC_TITLE )
m_iParagraphStyle = ED_PARA_DESC_TITLE;
}
else
{
// Changing to either numbered or bulleted list
m_iParagraphStyle = ED_PARA_LIST;
}
ChangeParagraphStyle();
}
void CParagraphPage::OnSelchangeListItemStyle()
{
SetModified(TRUE);
m_iListStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
int iListItemStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
// Just record index in proper list item category
if( m_iListStyle == ED_UNUM_LIST){
m_iBulletStyle = iListItemStyle;
} else if( m_iListStyle == ED_NUM_LIST){
m_iNumberStyle = iListItemStyle;
}
}
void CParagraphPage::OnChangeListStartNumber()
{
SetModified(TRUE);
}
void CParagraphPage::OnAlignCenter()
{
m_Align = ED_ALIGN_ABSCENTER; // ED_ALIGN_CENTER;
SetModified(TRUE);
}
void CParagraphPage::OnAlignLeft()
{
m_Align = ED_ALIGN_LEFT;
SetModified(TRUE);
}
void CParagraphPage::OnAlignRight()
{
m_Align = ED_ALIGN_RIGHT;
SetModified(TRUE);
}
void CParagraphPage::OnClose()
{
// We can't release data in OnOK
// since we may stay around after
// it is called for "Apply" function
if( m_pListData ){
EDT_FreeListData(m_pListData);
}
CNetscapePropertyPage::OnClose();
}
//////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CColorButton, CButton)
CColorButton::CColorButton(COLORREF * pColorRef, COLORREF * pSetFocusColor) :
m_pColorRef(pColorRef),
m_pSetFocusColor(pSetFocusColor),
m_hPal(0),
m_bColorSwatchMode(0),
m_pToolTip(0)
{
}
CColorButton::~CColorButton()
{
if( m_pToolTip ){
delete m_pToolTip;
}
}
BEGIN_MESSAGE_MAP(CColorButton, CButton)
//{{AFX_MSG_MAP(CColorButton)
ON_WM_MOUSEMOVE()
ON_WM_SETFOCUS()
//}}AFX_MSG_MAP
#ifdef XP_WIN32
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
#endif
END_MESSAGE_MAP()
BOOL CColorButton::PreTranslateMessage(MSG* pMsg)
{
if( m_pToolTip && pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
{
#ifdef XP_WIN32
// This is needed to get around an MFC bug
// where tooltip is disabled after Modal Dialog is called
m_pToolTip->Activate(TRUE);
#endif
m_pToolTip->RelayEvent(pMsg);
}
return CButton::PreTranslateMessage(pMsg);
}
//
#ifdef XP_WIN32
// This is needed for non-CFrame owners of a CToolTipCtrl
BOOL CColorButton::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID =pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
if(::GetDlgCtrlID((HWND)nID) == 1) {
strcpy(pTTT->szText, m_pTipText);
return(TRUE);
}
}
return(FALSE);
}
#endif
BOOL CColorButton::Subclass(CWnd * pParentWnd, UINT nID, COLORREF * pColorRef, BOOL bColorSwatchMode)
{
if(!pParentWnd || !pColorRef){
return FALSE;
}
m_pColorRef = pColorRef;
m_bColorSwatchMode = bColorSwatchMode;
// Attach derived class to existing control and route messages to parent dialog
BOOL bResult = SubclassDlgItem(nID, pParentWnd);
// Must do subclass before we can use GetParentFrame()
m_hPal = WFE_GetUIPalette(GetParentFrame());
AddToolTip();
return bResult;
}
BOOL CColorButton::Create(RECT& rect, CWnd * pParentWnd, UINT nID, COLORREF * pColorRef, BOOL bColorSwatchMode)
{
if(!pParentWnd || !pColorRef){
return FALSE;
}
m_pColorRef = pColorRef;
m_bColorSwatchMode = bColorSwatchMode;
BOOL bResult = CButton::Create(NULL, BS_PUSHBUTTON|BS_OWNERDRAW|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
rect, pParentWnd, nID);
// Must do Create before we can use GetParentFrame()
m_hPal = WFE_GetUIPalette(GetParentFrame());
AddToolTip();
return bResult;
}
void CColorButton::Update()
{
// Redraw the button
Invalidate(FALSE);
// Update tooltip for new color
if( m_pToolTip ){
// Make a tip with "R=xxx G=xxx B=xxx"
wsprintf(m_pTipText, szLoadString(IDS_COLOR_TIP_FORMAT),
GetRValue(*m_pColorRef),GetGValue(*m_pColorRef),GetBValue(*m_pColorRef));
strcat(m_pTipText, szLoadString(IDS_COLOR_TIP_HTML));
char * pEnd = m_pTipText + strlen(m_pTipText);
sprintf(pEnd, "#%02X%02X%02X",GetRValue(*m_pColorRef),GetGValue(*m_pColorRef),GetBValue(*m_pColorRef));
m_pToolTip->UpdateTipText(m_pTipText, this, 1);
}
}
void CColorButton::AddToolTip()
{
// Add tooltip only if a real button
// In "color swatch mode", the parent CColorPicker
// has 1 tooltip associated with all the button controls
if( !m_bColorSwatchMode ){
// Add a tooltip control
m_pToolTip = new CNSToolTip2;
if(m_pToolTip && !m_pToolTip->Create(this, TTS_ALWAYSTIP) ){
TRACE("Unable To create ToolTip\n");
delete m_pToolTip;
m_pToolTip = NULL;
return;
}
// Lets use speedy tooltips
m_pToolTip->SetDelayTime(200);
#ifdef XP_WIN32
// We MUST do this for MFC tooltips
EnableToolTips(TRUE);
#endif // WIN32
RECT rect;
GetClientRect(&rect);
m_pToolTip->AddTool(this, m_pTipText, &rect, 1);
// Set the text to show the colors
Update();
}
}
void CColorButton::OnMouseMove(UINT nFlags, CPoint point)
{
CButton::OnMouseMove(nFlags, point);
// For the "Color swatch" mode, automatically pull focus to
// the button with any mouse over
if( m_bColorSwatchMode && GetFocus() != this ){
// Set the color for the caller
// This allows just mouse move to set the color
// after user presses Enter key without clicking on a color button
// and also lets us use OnOK() for all button clicks
SetFocus();
}
}
void CColorButton::OnSetFocus(CWnd* pOldWnd)
{
// Send the color back to the caller
if( m_pSetFocusColor ){
*m_pSetFocusColor = *m_pColorRef;
}
CButton::OnSetFocus(pOldWnd);
}
#define COLOR_DROPDOWN_WIDTH 10
void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
HPALETTE hOldPal = NULL;
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
if( m_hPal )
{
hOldPal = ::SelectPalette( pDC->m_hDC, m_hPal, FALSE );
}
BOOL bSelected = lpDIS->itemState & ODS_SELECTED;
HDC hDC = lpDIS->hDC;
RECT rect = lpDIS->rcItem;
if( !m_bColorSwatchMode )
{
// We can't draw on last pixels of right and bottom???
rect.right--;
rect.bottom--;
}
// Use the button face color as our background
::FillRect(hDC, &rect, sysInfo.m_hbrBtnFace);
HPEN penShadow = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnShadow);
HPEN penHighlight = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnHilite);
HPEN penBlack = ::CreatePen(PS_SOLID, 1, RGB(0,0,0));
HPEN penOld = (HPEN)::SelectObject(hDC, penBlack);
RECT rectColor = rect;
if( m_bColorSwatchMode )
{
// Draw the depressed 3D look like Window's color picker,
// Note that there is a built-in blank border
// only focus rect draws on actual window borders
::InflateRect(&rect, -2, -2);
rectColor.left += 4;
rectColor.top += 4;
rectColor.right -= 3;
rectColor.bottom -= 3;
} else {
rectColor.left += 2;
rectColor.top += 2;
rectColor.bottom -= 1;
rectColor.right -= (COLOR_DROPDOWN_WIDTH + 7);
}
// Draw depressed border for color swatch
::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
::LineTo(hDC, rect.left+1, rect.top+1);
::LineTo(hDC, rect.right, rect.top+1);
::SelectObject(hDC, penShadow);
::MoveToEx(hDC, rect.left, rect.bottom, NULL);
::LineTo(hDC, rect.left, rect.top);
::LineTo(hDC, rect.right+1, rect.top);
::SelectObject(hDC, penHighlight);
::MoveToEx(hDC, rect.left+1, rect.bottom, NULL);
::LineTo(hDC, rect.right, rect.bottom);
::LineTo(hDC, rect.right, rect.top);
::SelectObject(hDC, penBlack);
if( !m_bColorSwatchMode )
{
::InflateRect(&rect, -2, -2);
rect.top++;
rect.left = rect.right - (COLOR_DROPDOWN_WIDTH + 4);
// Location of drop-down arrow
// Width is actually COLOR_DROPDOWN_WIDTH-4,
// but LineTo needs extra pixel to end where we want
int iTWidth = COLOR_DROPDOWN_WIDTH - 3;
int iTLeft = rect.right - iTWidth - 4;
int iTTop = rect.top + ((rect.bottom - rect.top)/2) - 2;
// Offset down and right for pressed-down state
if( lpDIS->itemState & ODS_SELECTED )
{
iTLeft++;
iTTop++;
}
// Draw the black drop-down triangle
while( iTWidth >= 0 )
{
::MoveToEx(hDC, iTLeft, iTTop, NULL);
::LineTo(hDC, iTLeft + iTWidth, iTTop);
iTTop++;
iTLeft++;
iTWidth -= 2;
}
if( lpDIS->itemState & ODS_SELECTED )
{
rect.right++;
rect.bottom++;
HBRUSH brushShadow = ::CreateSolidBrush(sysInfo.m_clrBtnShadow|0x02000000);
::FrameRect(hDC, &rect, brushShadow);
::DeleteObject(brushShadow);
} else {
// Draw the raised 3D button shadows
::MoveToEx(hDC, rect.left, rect.bottom, NULL);
::LineTo(hDC, rect.right, rect.bottom);
::LineTo(hDC, rect.right, rect.top-1);
::SelectObject(hDC, penShadow);
::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
::LineTo(hDC, rect.right-1, rect.bottom-1);
::LineTo(hDC, rect.right-1, rect.top);
::SelectObject(hDC, penHighlight);
::MoveToEx(hDC, rect.left, rect.bottom-1, NULL);
::LineTo(hDC, rect.left, rect.top);
::LineTo(hDC, rect.right, rect.top);
}
}
// Draw the color rectangle unless we have a "no color" or "default" state
if( *m_pColorRef != NO_COLORREF && *m_pColorRef != DEFAULT_COLORREF)
{
HBRUSH brushColor = ::CreateSolidBrush((*m_pColorRef)|0x02000000); // Like PALETTERGB
// Fill a rect with supplied color
HBRUSH brushOld = (HBRUSH)::SelectObject(hDC, brushColor);
::FillRect(hDC, &rectColor, brushColor);
::SelectObject(hDC, brushOld);
::DeleteObject(brushColor);
}
// Manually draw the focus rect
if( lpDIS->itemState & ODS_FOCUS )
{
RECT rectFocus;
if( m_bColorSwatchMode )
{
rectFocus = lpDIS->rcItem;
rect.left++;
rect.top++;
} else {
rectFocus = rectColor;
::InflateRect(&rectFocus, -1, -1);
}
::DrawFocusRect(hDC, &rectFocus);
}
// Cleanup
::SelectObject(hDC, penOld);
::DeleteObject(penShadow);
::DeleteObject(penHighlight);
::DeleteObject(penBlack);
if(m_hPal)
{
::SelectPalette( pDC->m_hDC, hOldPal, FALSE );
}
}
/////////////////////////////////////////////////////////////////////////////
// CBitmapPushButton
// Allows toolbar-like pushbutton behavior
CBitmapPushButton::CBitmapPushButton(BOOL bNoBorder) :
m_bDown(0),
m_bFocus(0),
m_bSelected(0),
m_hPal(0),
m_bNoBorder(bNoBorder)
{
}
int CBitmapPushButton::OnCreate(LPCREATESTRUCT lpCreateStruct )
{
if( -1 == CBitmapButton::OnCreate(lpCreateStruct) ){
return -1;
}
// Get the global default palette
m_hPal = WFE_GetUIPalette(GetParentFrame());
return 0;
}
CBitmapPushButton::~CBitmapPushButton()
{
}
BEGIN_MESSAGE_MAP(CBitmapPushButton, CBitmapButton)
//{{AFX_MSG_MAP(CBitmapPushButton)
ON_WM_CREATE()
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CBitmapPushButton::LoadBitmap(UINT nBitmapID)
{
// delete old bitmaps (if present)
m_bitmap.DeleteObject();
m_bitmapSel.DeleteObject();
m_bitmapFocus.DeleteObject();
m_bitmapDisabled.DeleteObject();
if ( !m_bitmap.LoadBitmap( nBitmapID ) ) {
return FALSE;
}
return TRUE;
}
void CBitmapPushButton::SetCheck(BOOL bCheck)
{
BOOL bChanged = m_bDown != bCheck;
m_bDown = bCheck;
SetState(bCheck);
if(bChanged){
// We need to force redraw sometimes
Invalidate(FALSE);
}
}
/////////////////////////////////////////////////////////////////////////////
// CBitmapPushButton message handlers
void CBitmapPushButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
// Save current focus state so we know what
// button is pressed via keyboard in CDropdownToolbar handler
m_bFocus = (lpDIS->itemState & ODS_FOCUS);
// If our state is pushed down ("checked"),
// then always force selected bit so
// we don't unselect when losing focus
if(m_bDown) {
lpDIS->itemState |= ODS_SELECTED;
}
m_bSelected = lpDIS->itemState & ODS_SELECTED;
// Draw the bitmap ourselves to do transparent overlay
// Get the bitmap for the image
HBITMAP hBmpImg = 0;
if(m_bSelected && m_bitmapSel.m_hObject ){
// HBITMAP(m_bitmapSel) doesn't work in old MFC (Win16)
hBmpImg = (HBITMAP)m_bitmapSel.m_hObject;
} else if( m_bFocus && m_bitmapFocus.m_hObject ) {
hBmpImg = (HBITMAP)m_bitmapFocus.m_hObject;
} else if ( (lpDIS->itemState & ODS_DISABLED) && m_bitmapDisabled.m_hObject ) {
hBmpImg = (HBITMAP)m_bitmapDisabled.m_hObject;
} else {
// Check for no bitmap at all!
if( !m_bitmap.m_hObject ){
return;
}
hBmpImg = (HBITMAP)m_bitmap.m_hObject;
}
HDC hDC = lpDIS->hDC;
HDC hBmpDC = ::CreateCompatibleDC(hDC);
RECT rect = lpDIS->rcItem;
// Use the button face color as our background
::FillRect(hDC, &rect, sysInfo.m_hbrBtnFace);
// If no bitmap, we must be disabled and no image supplied - leave blank TODO: GRAY IMAGE
// WEIRD - m_bitmapDisabled.m_hObject is not NULL
// if( hBmpImg ){
if( ! (lpDIS->itemState & ODS_DISABLED) ){
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hBmpDC, hBmpImg);
// Get this for the real bimap width and height
BITMAP bmp;
::GetObject(hBmpImg, sizeof(bmp), &bmp);
int x, y;
// Center the image within the button
x = rect.left + ((rect.right - rect.left) - bmp.bmWidth) / 2;
y = rect.top + ((rect.bottom - rect.top) - bmp.bmHeight) / 2;
// If button is pushed down, shift image right and down 1 pixel,
// (but only if not using supplied selected bitmap)
if(m_bSelected && m_bitmapSel.m_hObject == NULL ){
x++;
y++;
}
// Call the handy transparent blit function to paint the bitmap over whatever colors exist.
::FEU_TransBlt( hDC, x, y , bmp.bmWidth, bmp.bmHeight,
hBmpDC, 0, 0, m_hPal);
::SelectObject(hBmpDC, hOldBmp);
::DeleteDC(hBmpDC);
}
// Draw the 3D shadow borders
// Reduce to use inclusive border
rect.right --;
rect.bottom --;
::InflateRect(&rect, -1, -1);
HPEN penShadow = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnShadow);
HPEN penHighlight = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnHilite);
HPEN penBlack = ::CreatePen(PS_SOLID, 1, RGB(0,0,0));
HPEN penOld = (HPEN)::SelectObject(hDC, penBlack);
if( m_bSelected ){
// Draw the depressed 3D button shadows
// only if bitmap wasn't supplied
if( m_bitmapSel.m_hObject == NULL ){
::MoveToEx(hDC, rect.left, rect.bottom, NULL);
::LineTo(hDC, rect.left, rect.top);
::LineTo(hDC, rect.right+1, rect.top);
::SelectObject(hDC, penShadow);
::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
::LineTo(hDC, rect.left+1, rect.top+1);
::LineTo(hDC, rect.right, rect.top+1);
::SelectObject(hDC, penHighlight);
::LineTo(hDC, rect.right, rect.bottom);
::LineTo(hDC, rect.left, rect.bottom);
}
} else if( !m_bNoBorder ){
// Draw the raised 3D button shadows
::MoveToEx(hDC, rect.left, rect.bottom, NULL);
::LineTo(hDC, rect.right, rect.bottom);
::LineTo(hDC, rect.right, rect.top-1);
::SelectObject(hDC, penShadow);
::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
::LineTo(hDC, rect.right-1, rect.bottom-1);
::LineTo(hDC, rect.right-1, rect.top);
::SelectObject(hDC, penHighlight);
::MoveToEx(hDC, rect.left, rect.bottom-1, NULL);
::LineTo(hDC, rect.left, rect.top);
::LineTo(hDC, rect.right, rect.top);
}
// Manually draw the focus rect if we don't have an image
// This is optimized for a 1-pixel highlight bevel
// and 2-pixel shadow bevel
// Note that CBitmapButton will NEVER
// show a distinct Selected+Focus state,
// so this supplies that feature
if( m_bFocus && m_bitmapFocus.m_hObject == NULL ){
if( !m_bSelected ){
// Draw the raised 3D button shadows if we are not pressing down
::SelectObject(hDC, penHighlight);
::MoveToEx(hDC, rect.left, rect.bottom-1, NULL);
::LineTo(hDC, rect.left, rect.top);
::LineTo(hDC, rect.right, rect.top);
::SelectObject(hDC, penShadow);
::MoveToEx(hDC, rect.left, rect.bottom, NULL);
::LineTo(hDC, rect.right, rect.bottom);
::LineTo(hDC, rect.right, rect.top-1);
}
// Draw a solid black frame just outside of 3D shadow rect
::InflateRect(&rect, 1, 1);
// Stupid algorithm doesn't include actual right/bottom
rect.bottom++;
rect.right++;
FrameRect(hDC, &rect, (HBRUSH)::GetStockObject(BLACK_BRUSH));
}
// Cleanup
::SelectObject(hDC, penOld);
::DeleteObject(penShadow);
::DeleteObject(penHighlight);
::DeleteObject(penBlack);
}
// Collection of Alignment/Size/Border controls used by
// Image, Java, and PlugIn dialogs
/////////////////////////////////////////////////////////////////////
CAlignControls::CAlignControls() :
m_nIDAlign(0),
m_EdAlign(ED_ALIGN_DEFAULT)
{
}
BOOL CAlignControls::Init(CWnd *pParent)
{
ASSERT(pParent);
m_pParent = pParent;
// Load the bitmaps for our alignment buttons
VERIFY(m_BtnAlignTop.AutoLoad(IDC_EDAL_T, pParent));
VERIFY(m_BtnAlignCenter.AutoLoad(IDC_EDAL_C, pParent));
VERIFY(m_BtnAlignCenterBaseline.AutoLoad(IDC_EDALCB, pParent));
VERIFY(m_BtnAlignBottomBaseline.AutoLoad(IDC_EDAL_A, pParent));
VERIFY(m_BtnAlignBottom.AutoLoad(IDC_EDAL_B, pParent));
VERIFY(m_BtnAlignLeft.AutoLoad(IDC_EDAL_L, pParent));
VERIFY(m_BtnAlignRight.AutoLoad(IDC_EDAL_R, pParent));
// Intialize controls
SetAlignment();
return TRUE;
}
// Return if we really changed the align state
// as compared to the previous state
BOOL CAlignControls::OnAlignButtonClick(UINT nID)
{
if ( nID == 0 ) {
nID = m_nIDAlign ? m_nIDAlign : IDC_EDAL_B;
}
BOOL bChanged = nID != m_nIDAlign;
m_nIDAlign = nID;
m_BtnAlignTop.SetCheck(m_nIDAlign == IDC_EDAL_T);
m_BtnAlignCenter.SetCheck(m_nIDAlign == IDC_EDAL_C);
m_BtnAlignCenterBaseline.SetCheck(m_nIDAlign == IDC_EDALCB);
m_BtnAlignBottomBaseline.SetCheck(m_nIDAlign == IDC_EDAL_A);
m_BtnAlignBottom.SetCheck(m_nIDAlign == IDC_EDAL_B);
m_BtnAlignLeft.SetCheck(m_nIDAlign == IDC_EDAL_L);
m_BtnAlignRight.SetCheck(m_nIDAlign == IDC_EDAL_R);
if(bChanged &&
m_pParent->IsKindOf(RUNTIME_CLASS(CPropertyPage))){
((CPropertyPage*)m_pParent)->SetModified(TRUE);
}
return bChanged;
}
ED_Alignment CAlignControls::GetAlignment()
{
// NOTE: ED_ defines are backward for Center and Bottom
// we should change them in EDTTYPES.H, but too much
// other code depends on them being wrong!
switch( m_nIDAlign ){
case IDC_EDAL_T:
m_EdAlign = ED_ALIGN_TOP;
break;
case IDC_EDAL_C:
case IDC_EDALCB:
m_EdAlign = ED_ALIGN_ABSCENTER; // Should write "CENTER" to HTML
break;
case IDC_EDAL_L:
m_EdAlign = ED_ALIGN_LEFT;
break;
case IDC_EDAL_R:
m_EdAlign = ED_ALIGN_RIGHT;
break;
default:
m_EdAlign = ED_ALIGN_BASELINE; // Should write no param (default)
break;
}
return m_EdAlign;
}
void CAlignControls::SetAlignment()
{
OnAlignButtonClick(m_nIDAlign);
}
//////////////////////////////////////////////////
// Image dialog page.
// Note that we must supply Image data since we may be sharing
// it with Href data.
// Thus we need a flag to tell us to insert new image.
/////////////////////////////////////////////////////////////////////
CImagePage::CImagePage(CWnd* pParent, MWContext * pMWContext,
CEditorResourceSwitcher * pResourceSwitcher,
EDT_ImageData * pData, BOOL bInsert)
: CNetscapePropertyPage(CImagePage::IDD),
m_pMWContext(pMWContext),
m_pResourceSwitcher(pResourceSwitcher),
m_bActivated(0),
m_bInsert(bInsert),
m_pData(pData)
{
ASSERT(pMWContext);
ASSERT(pData);
//{{AFX_DATA_INIT(CImagePage)
m_csImage = _T("");
m_csAltText = _T("");
m_bNoSave = 0;
m_bSetAsBackground = 0;
m_iHeight = 0;
m_iWidth = 0;
m_iHSpace = 0;
m_iVSpace = 0;
m_iBorder = 0;
m_bDefaultBorder = FALSE;
m_iHeightPixOrPercent = 0;
m_iWidthPixOrPercent = 0;
m_bLockAspect = 1;
//}}AFX_DATA_INIT
m_csHref = _T("");
m_csImageStart = _T("");
m_csLastValidImage = _T("");
// m_csLastValidLowRes = _T("");
m_bValidImage = FALSE;
// m_bValidLowRes = FALSE;
m_bImageChanged = FALSE;
m_bOriginalButtonPressed = FALSE;
m_bLockAspect = TRUE;
wfe_GetLayoutViewSize(pMWContext, &m_iFullWidth, &m_iFullHeight);
#ifdef XP_WIN32
// Set the hInstance so we get template from editor's resource DLL
m_psp.hInstance = AfxGetResourceHandle();
#endif
}
void CImagePage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CImagePage)
DDX_Text(pDX, IDC_IMAGE_URL, m_csImage);
DDX_Check(pDX, IDC_NO_SAVE_IMAGE, m_bNoSave);
DDX_Check(pDX, IDC_LOCK_ASPECT, m_bLockAspect);
DDX_Check(pDX, IDC_MAKE_IMAGE_BACKGROUND, m_bSetAsBackground);
DDX_Text(pDX, IDC_IMAGE_HEIGHT, m_iHeight);
DDV_MinMaxInt(pDX, m_iHeight, 0, 10000);
DDX_Text(pDX, IDC_IMAGE_WIDTH, m_iWidth);
DDV_MinMaxInt(pDX, m_iWidth, 0, 10000);
DDX_Text(pDX, IDC_IMAGE_SPACE_HORIZ, m_iHSpace);
DDV_MinMaxInt(pDX, m_iHSpace, 0, 1000);
DDX_Text(pDX, IDC_IMAGE_SPACE_VERT, m_iVSpace);
DDV_MinMaxInt(pDX, m_iVSpace, 0, 1000);
DDX_Text(pDX, IDC_IMAGE_BORDER, m_iBorder);
DDV_MinMaxInt(pDX, m_iBorder, 0, 1000);
DDX_CBIndex(pDX, IDC_HEIGHT_PIX_OR_PERCENT, m_iHeightPixOrPercent);
DDX_CBIndex(pDX, IDC_WIDTH_PIX_OR_PERCENT, m_iWidthPixOrPercent);
DDX_Text(pDX, IDC_IMAGE_ALT_TEXT, m_csAltText);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CImagePage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CImagePage)
ON_BN_CLICKED(IDC_IMAGE_FILE, OnImageFile)
ON_EN_CHANGE(IDC_IMAGE_URL, OnChangeImageURL)
ON_EN_KILLFOCUS(IDC_IMAGE_URL, OnKillfocusImage)
ON_BN_CLICKED(IDC_IMAGE_ORIGINAL_SIZE, OnImageOriginalSize)
ON_BN_CLICKED(IDC_EDIT_IMAGE, OnEditImage)
ON_BN_CLICKED(IDC_NO_SAVE_IMAGE, OnNoSave)
ON_BN_CLICKED(IDC_REMOVE_ISMAP, OnRemoveIsmap)
ON_BN_CLICKED(IDC_MAKE_IMAGE_BACKGROUND, OnSetAsBackground)
ON_BN_CLICKED(IDC_EDAL_A, OnAlignBaseline)
ON_BN_CLICKED(IDC_EDAL_B, OnAlignBottom)
ON_BN_CLICKED(IDC_EDAL_C, OnAlignCenter)
ON_BN_CLICKED(IDC_EDAL_L, OnAlignLeft)
ON_BN_CLICKED(IDC_EDAL_R, OnAlignRight)
ON_BN_CLICKED(IDC_EDAL_T, OnAlignTop)
ON_BN_CLICKED(IDC_EDALCB, OnAlignCenterBaseline)
ON_EN_CHANGE(IDC_IMAGE_HEIGHT, OnChangeHeight)
ON_EN_CHANGE(IDC_IMAGE_WIDTH, OnChangeWidth)
ON_CBN_SELCHANGE(IDC_HEIGHT_PIX_OR_PERCENT, OnSelchangeHeightPixOrPercent)
ON_CBN_SELCHANGE(IDC_WIDTH_PIX_OR_PERCENT, OnSelchangeWidthPixOrPercent)
ON_EN_CHANGE(IDC_IMAGE_SPACE_HORIZ, OnChangeSpaceHoriz)
ON_EN_CHANGE(IDC_IMAGE_SPACE_VERT, OnChangeSpaceVert)
ON_EN_CHANGE(IDC_IMAGE_BORDER, OnChangeBorder)
ON_BN_CLICKED(IDC_EXTRA_HTML, OnExtraHTML)
ON_BN_CLICKED(IDC_LOCK_ASPECT, OnLockAspect)
ON_EN_CHANGE(IDC_IMAGE_ALT_TEXT, OnChangeAltText)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CImagePage::OnSetActive()
{
if(m_pResourceSwitcher && !m_bActivated){
// We must be sure we have switched
// the first time here - before dialog creation
m_pResourceSwitcher->switchResources();
}
if(!CPropertyPage::OnSetActive())
return(FALSE);
if(m_bActivated)
return(TRUE);
// Switch back to EXE's resources
if( m_pResourceSwitcher ){
m_pResourceSwitcher->Reset();
}
if ( m_pData->pSrc && XP_STRLEN(m_pData->pSrc) > 0 ){
m_csImage = XP_STRDUP(m_pData->pSrc);
}
else if ( !m_bInsert ) {
TRACE0("No Image Filename for Image Properties\n");
return FALSE;
}
m_bActivated = TRUE;
// Translate ImageData defines Align buttons index
// NOTE: ED_ defines are backward for Center and Bottom
// we should change them in EDTTYPES.H, but too much
// other code depends on them being wrong!
m_AlignControls.m_EdAlign = m_pData->align;
switch ( m_pData->align ){
case ED_ALIGN_LEFT:
m_AlignControls.m_nIDAlign = IDC_EDAL_L;
break;
case ED_ALIGN_RIGHT:
m_AlignControls.m_nIDAlign = IDC_EDAL_R;
break;
case ED_ALIGN_TOP:
case ED_ALIGN_ABSTOP:
m_AlignControls.m_nIDAlign = IDC_EDAL_T;
break;
case ED_ALIGN_ABSCENTER:
m_AlignControls.m_nIDAlign = IDC_EDALCB;
break;
case ED_ALIGN_CENTER:
m_AlignControls.m_nIDAlign = IDC_EDAL_C;
break;
case ED_ALIGN_BOTTOM:
m_AlignControls.m_nIDAlign = IDC_EDAL_B;
break;
case ED_ALIGN_ABSBOTTOM:
case ED_ALIGN_BASELINE:
default:
m_AlignControls.m_nIDAlign = IDC_EDAL_A;
break;
}
// Intialize the common Alignment / Sizing controls;
if ( !m_AlignControls.Init(this) ) {
return FALSE;
}
// Use suplied values only if they existed,
// use our defaults (5 pixels) for new object
if ( ! m_bInsert ){
m_iVSpace = CASTINT(m_pData->iVSpace);
m_iHSpace = CASTINT(m_pData->iHSpace);
}
if( m_pData->iBorder >= 0 ){
m_iBorder = CASTINT(m_pData->iBorder);
} else {
// We were given the default border value of -1
// Set flag to restore -1 if user doesn't change it,
// but it shows as 0 in the edit box
m_bDefaultBorder = TRUE;
m_iBorder = EDT_GetDefaultBorderWidth(m_pMWContext);
}
m_iWidth = CASTINT(m_pData->iWidth);
m_iHeight = CASTINT(m_pData->iHeight);
m_iHeightPixOrPercent = m_pData->bHeightPercent ? 1 : 0;
m_iWidthPixOrPercent = m_pData->bWidthPercent ? 1 : 0;
// We try to get the "Original" dimensions, or at least
// those when image was last loaded
if( m_pData->iOriginalWidth ){
m_iOriginalWidth = m_pData->iOriginalWidth;
m_iOriginalHeight = m_pData->iOriginalHeight;
} else {
m_iOriginalWidth = m_pData->iWidth;
m_iOriginalHeight = m_pData->iHeight;
}
// Avoid divide by zero
m_iOriginalWidth = max(1, m_iOriginalWidth);
m_iOriginalHeight = max(1, m_iOriginalHeight);
// Fill drop-lists of units
wfe_InitPixOrPercentCombos(this);
// Controls specific to Image page:
m_csAltText = m_pData->pAlt;
// Get possible HREF for image
if(m_pData->pHREFData && m_pData->pHREFData->pURL){
m_csHref = m_pData->pHREFData->pURL;
}
// Save initial image name to test
// before creating a link
m_csImageStart = m_csImage;
// Also save last valid image filenames
m_csLastValidImage = m_csImage;
m_bImageChanged = FALSE;
// Only allow removing bIsMap on images that already have it,
// i.e., we can't add it to raw images (YET!)
(GetDlgItem(IDC_REMOVE_ISMAP))->EnableWindow(m_pData->bIsMap);
SetOKEnable();
m_bNoSave = m_pData->bNoSave;
SetLockAspectEnable();
// Send data to controls
UpdateData(FALSE);
// Allow Apply button to be active if we are inserting a new object
SetModified(m_bInsert);
return(TRUE);
}
void CImagePage::OnHelp()
{
NetHelp(HELP_PROPS_IMAGE);
}
void CImagePage::SetOKEnable()
{
// Enable OK only if we have both Image URL and Alt text,
// but Alt text isn't needed if image will be used for background
(GetParent()->GetDlgItem(IDOK))->EnableWindow( !(m_csImage.IsEmpty()) &&
(m_bSetAsBackground || !(m_csAltText.IsEmpty())) );
}
void CImagePage::OnOK()
{
//EDT_BeginBatchChanges(m_pMWContext);
// Always set HREF data for image if struct exists, even if we didn't visit this page
// since the value may be changed by CLinkPage
if( m_pData->pHREFData )
{
// If m_pData->pHREFData->pURL is NULL or empty, this clears any existing link
EDT_SetHREFData(m_pMWContext, m_pData->pHREFData);
}
if(!m_bActivated ||
// no change
!IS_APPLY_ENABLED(this) ||
// or error in data
!UpdateData(TRUE) )
{
//EDT_EndBatchChanges(m_pMWContext);
return;
}
if ( m_csImage.IsEmpty() )
{
// No image -- do nothing
// WHAT IF THERE IS A LOWRES IMAGE??? ADD MESSAGEBOX?
if ( m_bInsert )
return;
// TODO: delete current image here?
// Currently, EDT_SetImageData does not check for m_pImageData = NULL;
return;
}
// Validate/Relativize images
// (Shouldn't really need this - validation is done on killfocus of edit boxes)
if ( m_bImageChanged && !m_bValidImage )
{
if ( !wfe_ValidateImage( m_pMWContext, m_csImage ) )
{
m_bValidImage = TRUE;
UpdateData(FALSE);
return;
}
}
int iLastDot = m_csImage.ReverseFind('.');
CString csExt;
if(iLastDot > 0)
csExt= m_csImage.Mid(iLastDot);
//we must check to see if file is a bmp!
if (0 == csExt.CompareNoCase(".bmp"))
{
char *t_outputfilename=wfe_ConvertImage(m_csImage.GetBuffer(0),(void *)this,m_pMWContext);
if (t_outputfilename)
{
m_csImage=t_outputfilename;
wfe_ValidateImage( m_pMWContext, m_csImage );
XP_FREE(t_outputfilename);
UpdateData(FALSE);//we need to update m_csImage!
}
else
return;
}
if( m_bSetAsBackground )
{
// Real simple - ignore all data except for image name and save
EDT_PageData * pPageData = EDT_GetPageData(m_pMWContext);
if( pPageData )
{
XP_FREEIF(pPageData->pBackgroundImage);
pPageData->pBackgroundImage = XP_STRDUP((char*)LPCSTR(m_csImage));
pPageData->bBackgroundNoSave = m_bNoSave;
EDT_SetPageData(m_pMWContext, pPageData);
EDT_FreePageData(pPageData);
}
} else {
// Get the Alignment/Size data
m_pData->align = m_AlignControls.GetAlignment();
if( m_bOriginalButtonPressed )
{
// Trick backend into getting size from image,
// not the values edited
m_pData->iWidth = 0;
m_pData->iHeight = 0;
} else {
m_pData->iWidth = m_iWidth;
m_pData->iHeight = m_iHeight;
}
m_pData->iHSpace = m_iHSpace;
m_pData->iVSpace = m_iVSpace;
if( m_bDefaultBorder )
m_pData->iBorder = -1;
else
m_pData->iBorder = m_iBorder;
m_pData->bWidthPercent = m_iWidthPixOrPercent;
m_pData->bHeightPercent = m_iHeightPixOrPercent;
// Data specific to Image:
CleanupString(m_csAltText);
if ( m_pData->pSrc )
XP_FREE(m_pData->pSrc);
m_pData->pSrc = XP_STRDUP(m_csImage);
if ( m_pData->pLowSrc ){
XP_FREE(m_pData->pLowSrc);
m_pData->pLowSrc = NULL;
}
// Note: deleting Alt text in editbox to remove Alt Text
if ( m_pData->pAlt )
{
XP_FREE(m_pData->pAlt);
m_pData->pAlt = NULL;
}
if ( !m_csAltText.IsEmpty() )
{
m_pData->pAlt = XP_STRDUP(m_csAltText);
}
m_pData->bNoSave = m_bNoSave;
if ( m_bInsert )
{
EDT_InsertImage(m_pMWContext, m_pData, !m_bNoSave);
// We insert just ONE image (on 1st "Apply" usage)
// Thus other Apply or OK will modify newly-inserted image
m_bInsert = FALSE;
}
else
{
EDT_SetImageData(m_pMWContext, m_pData, !m_bNoSave);
}
//Note: ImageData and HrefData should be freed by caller
}
OkToClose();
//EDT_EndBatchChanges(m_pMWContext);
CPropertyPage::OnOK();
}
// Get and validate the Image name
// so it is up to date if we switch to the Link dialog page
BOOL CImagePage::OnKillActive()
{
if( !UpdateData(TRUE) )
return FALSE;
if ( m_bImageChanged && !m_bValidImage )
wfe_ValidateImage( m_pMWContext, m_csImage );
CleanupString(m_csAltText);
CleanupString(m_csImage);
if( m_csImage.IsEmpty() || (!m_bSetAsBackground && m_csAltText.IsEmpty()) )
{
// Notify user they must have both image URL and alt text filled in
MessageBox(szLoadString(IDS_MISSING_IMAGE),
szLoadString(IDS_IMAGE_PROPS_CAPTION),
MB_ICONEXCLAMATION | MB_OK);
// Put focus in the offending control
// And select all text, just like DDV functions
CEdit *pEdit = (CEdit*)GetDlgItem(m_csImage.IsEmpty() ? IDC_IMAGE_URL : IDC_IMAGE_ALT_TEXT);
pEdit->SetFocus();
pEdit->SetSel(0, -1, TRUE);
return FALSE;
}
XP_FREEIF(m_pData->pSrc);
m_pData->pSrc = XP_STRDUP(m_csImage);
// Contrary to MFC help, this does NOT call our OnOK
return CPropertyPage::OnKillActive();
}
// Called from the View after saving file to disk -- has new image
// in a URL form relative to current document
void CImagePage::SetImageFileSaved(char * pImageURL, int iImageNumber )
{
UpdateData(TRUE);
if( iImageNumber == 1 )
m_csImage = pImageURL;
UpdateData(FALSE);
}
void CImagePage::OnImageFile()
{
UpdateData(TRUE);
char * szFilename = wfe_GetExistingImageFileName(this->m_hWnd,
szLoadString(IDS_SELECT_IMAGE), TRUE);
if ( szFilename != NULL )
{
m_csImage = szFilename;
// Note that we don't tell user if file is "bad" since
// it is difficult to validate in all cases
wfe_ValidateImage( m_pMWContext, m_csImage );
XP_FREE( szFilename );
SetModified(TRUE);
// Supply a default AltText = image filename
AutoFillAltText();
UpdateData(FALSE);
m_bValidImage = TRUE;
m_csLastValidImage = m_csImage;
SetOKEnable();
}
}
void CImagePage::OnChangeImageURL()
{
m_bImageChanged = TRUE;
m_bValidImage = FALSE;
SetModified(TRUE);
// Disable Edit button if no image name
GetDlgItem(IDC_IMAGE_URL)->GetWindowText(m_csImage);
m_csImage.TrimLeft();
m_csImage.TrimRight();
GetDlgItem(IDC_EDIT_IMAGE)->EnableWindow(!m_csImage.IsEmpty());
SetOKEnable();
}
void CImagePage::OnKillfocusImage()
{
if( m_bImageChanged &&
UpdateData(TRUE) )
{
wfe_ValidateImage( m_pMWContext, m_csImage );
m_bValidImage = TRUE;
AutoFillAltText();
UpdateData(FALSE);
}
}
// Automatically fill in the ALT text string if none currently
void CImagePage::AutoFillAltText()
{
CleanupString(m_csAltText);
if( m_csAltText.IsEmpty() )
{
char *pName = EDT_GetFilename(CHAR_STR(m_csImage), FALSE);
if( pName )
{
m_csAltText = XP_STRDUP(pName);
XP_FREE(pName);
}
SetOKEnable();
}
}
void CImagePage::OnEditImage()
{
UpdateData(TRUE);
// Get our view from the context and call edit method
((CNetscapeEditView*)WINCX(m_pMWContext)->GetView())->EditImage((char*)LPCSTR(m_csImage));
}
void CImagePage::SetLockAspectEnable()
{
GetDlgItem(IDC_LOCK_ASPECT)->EnableWindow(!m_bSetAsBackground && !m_iHeightPixOrPercent && !m_iWidthPixOrPercent);
}
void CImagePage::OnSetAsBackground()
{
m_bSetAsBackground = ((CButton*)GetDlgItem(IDC_MAKE_IMAGE_BACKGROUND))->GetCheck();
// Enable or Disable all other controls - irrelevant when simply setting background
GetDlgItem(IDC_EDAL_T)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_EDAL_C)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_EDALCB)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_EDAL_A)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_EDAL_B)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_EDAL_L)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_EDAL_R)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_IMAGE_HEIGHT)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_HEIGHT_PIX_OR_PERCENT)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_IMAGE_WIDTH)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_WIDTH_PIX_OR_PERCENT)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_IMAGE_ORIGINAL_SIZE)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_IMAGE_SPACE_HORIZ)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_IMAGE_SPACE_VERT)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_IMAGE_BORDER)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_EXTRA_HTML)->EnableWindow(!m_bSetAsBackground);
GetDlgItem(IDC_REMOVE_ISMAP)->EnableWindow(!m_bSetAsBackground && m_pData->bIsMap);
GetDlgItem(IDC_IMAGE_ALT_TEXT)->EnableWindow(!m_bSetAsBackground);
SetLockAspectEnable();
SetOKEnable();
SetModified(TRUE);
}
void CImagePage::OnChangeAltText()
{
// Get the alt text
UpdateData(TRUE);
CleanupString(m_csAltText);
SetOKEnable();
SetModified(TRUE);
}
void CImagePage::OnNoSave()
{
SetModified(TRUE);
}
void CImagePage::OnRemoveIsmap()
{
m_pData->bIsMap = FALSE;
// Once removed, we can't add it back
(GetDlgItem(IDC_REMOVE_ISMAP))->EnableWindow(FALSE);
SetModified(TRUE);
}
// Align/Size controls:
void CImagePage::OnAlignBaseline()
{
m_AlignControls.OnAlignButtonClick(IDC_EDAL_A);
}
void CImagePage::OnAlignBottom()
{
m_AlignControls.OnAlignButtonClick(IDC_EDAL_B);
}
void CImagePage::OnAlignCenter()
{
m_AlignControls.OnAlignButtonClick(IDC_EDAL_C);
}
void CImagePage::OnAlignLeft()
{
m_AlignControls.OnAlignButtonClick(IDC_EDAL_L);
}
void CImagePage::OnAlignRight()
{
m_AlignControls.OnAlignButtonClick(IDC_EDAL_R);
}
void CImagePage::OnAlignTop()
{
m_AlignControls.OnAlignButtonClick(IDC_EDAL_T);
}
void CImagePage::OnAlignCenterBaseline()
{
m_AlignControls.OnAlignButtonClick(IDC_EDALCB);
}
void CImagePage::OnImageOriginalSize()
{
// Set flag so we're sure user wants this later
m_bOriginalButtonPressed = TRUE;
UpdateData(TRUE);
m_iWidth = CASTINT(m_iOriginalWidth);
m_iHeight = CASTINT(m_iOriginalHeight);
// We must be in pixel mode, not % mode
m_iHeightPixOrPercent = 0;
m_iWidthPixOrPercent = 0;
UpdateData(FALSE);
SetModified(TRUE);
}
void CImagePage::OnChangeHeight()
{
if( m_bLockAspect && ((CButton*)GetDlgItem(IDC_LOCK_ASPECT))->IsWindowEnabled() )
{
// Get value just enterred and set the opposite
// to a value that keeps aspect ratio of original
CWnd *pHeightEdit = GetDlgItem(IDC_IMAGE_HEIGHT);
CWnd *pWidthEdit = GetDlgItem(IDC_IMAGE_WIDTH);
char pValue[16];
char* pEnd;
pHeightEdit->GetWindowText(pValue, 10);
int32 iHeight = (int)strtol( pValue, &pEnd, 10 );
// Bad conversion if end pointer isn't at terminal null;
if( *pEnd == '\0' )
{
m_iHeight = iHeight;
// Add 0.5 to round off when converting back to int
m_iWidth = (int)((iHeight * m_iOriginalWidth) / m_iOriginalHeight);
wsprintf(pValue, "%d", m_iWidth);
// Avoid bouncing back and forth (and killing stack!)
// SetWindowText triggers OnChangeWidth
m_bLockAspect = FALSE;
pWidthEdit->SetWindowText(pValue);
m_bLockAspect = TRUE;
}
}
if( m_iHeight != m_iOriginalHeight)
m_bOriginalButtonPressed = FALSE;
SetModified(TRUE);
}
void CImagePage::OnChangeWidth()
{
if( m_bLockAspect && ((CButton*)GetDlgItem(IDC_LOCK_ASPECT))->IsWindowEnabled() )
{
// Get value just enterred and set the opposite
// to a value that keeps aspect ratio of original
CWnd *pWidthEdit = GetDlgItem(IDC_IMAGE_WIDTH);
CWnd *pHeightEdit = GetDlgItem(IDC_IMAGE_HEIGHT);
char pValue[16];
char* pEnd;
pWidthEdit->GetWindowText(pValue, 10);
int32 iWidth = (int32)strtol( pValue, &pEnd, 10 );
if( *pEnd == '\0' )
{
m_iWidth = iWidth;
m_iHeight = (int)((iWidth * m_iOriginalHeight) / m_iOriginalWidth);
wsprintf(pValue, "%d", m_iHeight);
// Avoid bouncing back and forth (and killing stack!)
// SetWindowText triggers OnChangeHeight
m_bLockAspect = FALSE;
pHeightEdit->SetWindowText(pValue);
m_bLockAspect = TRUE;
}
}
if( m_iWidth != m_iOriginalWidth)
m_bOriginalButtonPressed = FALSE;
SetModified(TRUE);
}
void CImagePage::OnSelchangeHeightPixOrPercent()
{
UpdateData();
SetLockAspectEnable();
//TODO: do number conversion if switching state?
SetModified(TRUE);
}
void CImagePage::OnSelchangeWidthPixOrPercent()
{
UpdateData();
SetLockAspectEnable();
//TODO: do number conversion if switching state?
SetModified(TRUE);
}
void CImagePage::OnChangeSpaceHoriz()
{
SetModified(TRUE);
}
void CImagePage::OnChangeSpaceVert()
{
SetModified(TRUE);
}
void CImagePage::OnChangeBorder()
{
SetModified(TRUE);
// If user changed the border,
// then use that number instead
// of the default -1
m_bDefaultBorder = FALSE;
}
void CImagePage::OnExtraHTML()
{
CExtraHTMLDlg dlg(this, &m_pData->pExtra, IDS_IMG_TAG);
if( dlg.DoModal() && dlg.m_bDataChanged )
SetModified(TRUE);
}
void CImagePage::OnLockAspect()
{
m_bLockAspect = ((CButton*)GetDlgItem(IDC_LOCK_ASPECT))->GetCheck();
}
/////////////////////////////////////////////////////////////////////////////
// CExtraHTMLDlg dialog (modal popup over CImagePage or CLinkPage for Extra HTML
CExtraHTMLDlg::CExtraHTMLDlg(CWnd *pParent, char **ppExtraHTML, UINT nIDTagType)
: CDialog(CExtraHTMLDlg::IDD, pParent),
m_ppExtraHTML(ppExtraHTML),
m_bDataChanged(FALSE),
m_nIDTagType(nIDTagType)
{
ASSERT( ppExtraHTML );
//{{AFX_DATA_INIT(CExtraHTMLDlg)
m_csExtraHTML = *ppExtraHTML;
//}}AFX_DATA_INIT
}
CExtraHTMLDlg::~CExtraHTMLDlg()
{
}
void CExtraHTMLDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CExtraHTMLDlg)
DDX_Text(pDX, IDC_EXTRA_HTML_TEXT, m_csExtraHTML);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CExtraHTMLDlg, CDialog)
//{{AFX_MSG_MAP(CExtraHTMLDlg)
ON_BN_CLICKED(ID_HELP, OnHelp)
//}}AFX_MSG_MAP
#ifdef XP_WIN32
ON_WM_HELPINFO()
#endif //XP_WIN32
END_MESSAGE_MAP()
BOOL CExtraHTMLDlg::OnInitDialog()
{
// Switch back to NETSCAPE.EXE for resource hInstance
m_ResourceSwitcher.Reset();
CDialog::OnInitDialog();
// Insert the text describing the tag type into the message and display
CString csMsg;
AfxFormatString1( csMsg, IDS_EXTRA_HTML_MSG, szLoadString(m_nIDTagType) );
GetDlgItem(IDC_EXTRA_HTML_MSG)->SetWindowText(LPCSTR(csMsg));
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CExtraHTMLDlg::OnHelp()
{
NetHelp(HELP_EXTRA_HTML);
}
#ifdef XP_WIN32
BOOL CExtraHTMLDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
{
OnHelp();
return TRUE;
}
#endif//XP_WIN32
void CExtraHTMLDlg::OnOK()
{
CDialog::OnOK();
// Strip off leading and ending spaces
m_csExtraHTML.TrimLeft();
m_csExtraHTML.TrimRight();
// Did we already have some data?
BOOL bHadExtra = 0 != *m_ppExtraHTML;
if( !bHadExtra && m_csExtraHTML.IsEmpty() ){
// We didn't have any before and none now, so we're done
return;
}
if( bHadExtra && 0 == XP_STRCMP(*m_ppExtraHTML, LPCSTR(m_csExtraHTML)) ){
// We had data before and it didn't change so we're done
return;
}
// If here, new data must be different than previous text
m_bDataChanged = TRUE;
if( bHadExtra ) XP_FREE(*m_ppExtraHTML);
if(m_csExtraHTML.IsEmpty() ){
// No new text
*m_ppExtraHTML = NULL;
} else {
// Copy new text
*m_ppExtraHTML = XP_STRDUP(LPCSTR(m_csExtraHTML));
}
}
///////////////////////////////////////////////////////////////
// Links dialog page.
// Note that we must supply Href data since we may be sharing
// it with Image data. If link is an image, *ppImage has name.
// Thus we need a flag to tell us to insert new link.
/////////////////////////////////////////////////////////////////////
CLinkPage::CLinkPage(CWnd* pParent, MWContext * pMWContext,
CEditorResourceSwitcher * pResourceSwitcher,
EDT_HREFData *pData, BOOL bInsert,
BOOL bMayHaveOtherLinks, char **ppImage)
: CNetscapePropertyPage(CLinkPage::IDD),
m_bActivated(0),
m_bInsert(bInsert),
m_pMWContext(pMWContext),
m_pResourceSwitcher(pResourceSwitcher),
m_bMayHaveOtherLinks(bMayHaveOtherLinks),
m_ppImage(ppImage),
m_pData(pData),
m_iTargetCount(0),
m_bValidHref(0),
m_bHrefChanged(0),
m_iCaretMovedBack(0)
{
//}}AFX_DATA_INIT
ASSERT(pMWContext);
ASSERT(pData);
m_szBaseDocument = NULL;
// Base URL is the address of current document
History_entry * hist_ent = SHIST_GetCurrent(&(m_pMWContext->hist));
if ( hist_ent ){
m_szBaseDocument = hist_ent->address;
}
// We will use some helper functions from our view
m_pView = (CNetscapeView*)WINCX(pMWContext)->GetView();
//{{AFX_DATA_INIT(CLinkPage)
m_csHref = _T("");
m_csAnchorEdit = _T("");
m_csAnchor = _T("");
//}}AFX_DATA_INIT
m_csLastValidHref = _T("");
#ifdef XP_WIN32
// Set the hInstance so we get template from editor's resource DLL
m_psp.hInstance = AfxGetResourceHandle();
#endif
}
CLinkPage::~CLinkPage()
{
// Reposition the caret to where it was
// when new link text was inserted
while( m_iCaretMovedBack ){
EDT_NextChar(m_pMWContext, FALSE);
m_iCaretMovedBack--;
}
}
void CLinkPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CLinkPage)
// NOTE: the ClassWizard will add DDX and DDV calls here
DDX_Text(pDX, IDC_HREF_URL, m_csHref);
DDX_Text(pDX, IDC_ANCHOR_EDIT, m_csAnchorEdit);
DDX_Text(pDX, IDC_ANCHOR, m_csAnchor);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CLinkPage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CLinkPage)
ON_BN_CLICKED(IDC_HREF_FILE, OnHrefFile)
ON_BN_CLICKED(IDC_HREF_UNLINK, OnHrefUnlink)
ON_LBN_SELCHANGE(IDC_TARGET_LIST, OnSelchangeTargetList)
ON_EN_CHANGE(IDC_HREF_URL, OnChangeHrefUrl)
ON_EN_KILLFOCUS(IDC_HREF_URL, OnKillfocusHrefUrl)
ON_BN_CLICKED(IDC_TARGETS_IN_CURRENT_DOC, OnTargetsInCurrentDoc)
ON_BN_CLICKED(IDC_TARGETS_IN_FILE, OnTargetsInFile)
ON_BN_CLICKED(IDC_EXTRA_HTML, OnExtraHTML)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CLinkPage::OnSetActive()
{
if(m_pResourceSwitcher && !m_bActivated){
// We must be sure we have switched
// the first time here - before dialog creation
m_pResourceSwitcher->switchResources();
}
if(!CPropertyPage::OnSetActive())
return(FALSE);
BOOL bImageAnchor = FALSE;
// Always check the Imagename that might
// be changed in the Image property page
if( m_ppImage && *m_ppImage ){
m_csAnchor = *m_ppImage;
if(!m_csAnchor.IsEmpty()){
((CEdit*)GetDlgItem(IDC_ANCHOR))->SetWindowText(m_csAnchor);
bImageAnchor = TRUE;
}
}
if(m_bActivated)
return(TRUE);
// Switch back to EXE's resources
if( m_pResourceSwitcher ){
m_pResourceSwitcher->Reset();
}
m_bActivated = TRUE;
// Get the current URL
m_csHref = m_pData->pURL;
//TODO: GET CURRENT CHARACTER STATE OR PASS IN?
// Fill the "Display text" editbox
// with selected text
UINT nIDLabel = 0;
BOOL bSelected = EDT_IsSelected(m_pMWContext);
if (bImageAnchor){
// Change label for image
// (Note: We set Image filename string above)
nIDLabel = IDS_ANCHOR_IMAGE;
} else {
if(m_bInsert && !bSelected ){
// We will create/insert a new Anchor + Href at caret location
// Use editbox instead of text control
((CEdit*)GetDlgItem(IDC_ANCHOR))->ShowWindow(SW_HIDE);
nIDLabel = IDS_NEW_ANCHOR_TEXT;
}
else if( EDT_CanSetHREF(m_pMWContext) ) {
// We have a text link or selected text
if ( bSelected ) {
m_csAnchor = (char*)LO_GetSelectionText(ABSTRACTCX(m_pMWContext)->GetDocumentContext());
} else {
// We are not selected, but are within a text anchor
char * pText = EDT_GetHREFText(m_pMWContext);
m_csAnchor = pText;
XP_FREE(pText);
}
// Replace CR/LF with spaces to avoid ugly break in static display
for( int i=0; i < m_csAnchor.GetLength(); i++ ){
if( m_csAnchor.GetAt(i) == '\r' || m_csAnchor.GetAt(i) == '\n' ){
m_csAnchor.SetAt(i, ' ');
}
}
}
}
if( nIDLabel ) {
// Set label above image name or new text editbox
GetDlgItem(IDC_ANCHOR_LABEL)->SetWindowText(szLoadString(nIDLabel));
}
if( nIDLabel != IDS_NEW_ANCHOR_TEXT ) {
// Make the existing Anchor Text or Image Filename BOLD by using System Font
// if( INTL_CharSetType(m_pMWContext->doc_csid) == SINGLEBYTE*/) {
// This should be OK even in foreign systems
CFont* pfontBold = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FONT));
((CEdit*)GetDlgItem(IDC_ANCHOR))->SetFont(pfontBold);
// }
// No editable anchor, so hide editbox
(GetDlgItem(IDC_ANCHOR_EDIT))->ShowWindow(SW_HIDE);
}
// Save initial HREF to restore string
// if user changes to something invalid
m_csLastValidHref = m_csHref;
// Init unlink button state. Note that button shows
// if we may have other links within selection that we can remove
(GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(!m_csHref.IsEmpty() || m_bMayHaveOtherLinks);
// Get the list of Targets (named anchors) in current doc
m_pTargetList = EDT_GetAllDocumentTargets(m_pMWContext);
if( m_pTargetList == NULL ){
// No targets in current doc, so disable button
((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->EnableWindow(FALSE);
}
// Try to generate a Targets list for current HREF (if local file),
// if none found, show the local list if it exists
if ( 0 == GetTargetsInFile() && m_pTargetList ){
if ( 0 == GetTargetsInDoc() ){
(GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_NO_TARGETS));
}
}
if( m_bMayHaveOtherLinks ){
(GetDlgItem(IDC_HREF_UNLINK))->SetWindowText(szLoadString(IDS_REMOVE_LINKS));
}
// Send data to controls
UpdateData(FALSE);
// Allow Apply button to be active if we are inserting a new object
SetModified(m_bInsert);
return TRUE;
}
// Set the HREF data
// It will be used by Image property page
// to set HREF to an image
BOOL CLinkPage::OnKillActive()
{
if( !UpdateData() ){
return FALSE;
}
if ( !m_bValidHref ){
ValidateHref();
}
return CPropertyPage::OnKillActive();
}
int nTargetIndex = -1;
int CLinkPage::GetTargetsInDoc()
{
m_iTargetCount = 0;
CListBox * pListBox = (CListBox*)GetDlgItem(IDC_TARGET_LIST);
pListBox->ResetContent();
if( m_pTargetList ){
char * pString = m_pTargetList;
int iLen;
while( (iLen = XP_STRLEN(pString)) > 0 ) {
// add to the end of the list
pListBox->AddString(pString);
pString += iLen+1;
m_iTargetCount++;
}
((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->SetCheck(1/*m_iTargetCount ? 1 : 0*/);
((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck(0);
if( m_iTargetCount ){
(GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_TARGETS_IN_CURRENT_DOC));
}
}
return m_iTargetCount;
}
// File read from HTML to get list of anchors
int CLinkPage::GetTargetsInFile()
{
if( m_csHref.IsEmpty() ){
return 0;
}
m_iTargetCount = 0;
// Build list from file
char * pTargetList = EDT_GetAllDocumentTargetsInFile(
m_pMWContext, (char*)LPCSTR(m_csHref));
if( pTargetList ){
CListBox * pListBox = (CListBox*)GetDlgItem(IDC_TARGET_LIST);
pListBox->ResetContent();
char * pString = pTargetList;
int iLen;
while( (iLen = XP_STRLEN(pString)) > 0 ) {
// add to the end of the list
pListBox->AddString(pString);
pString += iLen+1;
m_iTargetCount++;
}
XP_FREE(pTargetList);
// Save filename so we can avoid rereading file needlessly
m_csTargetFile = m_csHref;
} else {
// HREF wasn't a file or
// was same as current document
((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->SetCheck(1);
((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck(0);
return 0;
}
((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->SetCheck(0);
((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck( m_iTargetCount ? 1 : 0);
// Set appropriate message above targets list
if ( m_iTargetCount ){
(GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_TARGETS_IN_FILE));
} else {
(GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_NO_TARGETS));
}
return m_iTargetCount;
}
void CLinkPage::OnTargetsInCurrentDoc()
{
if( m_pTargetList ){
GetTargetsInDoc();
}
}
void CLinkPage::OnTargetsInFile()
{
UpdateData();
GetTargetsInFile();
}
void CLinkPage::OnSelchangeTargetList()
{
UpdateData(TRUE);
SetModified(TRUE);
m_bValidHref = FALSE;
// Copy selection text
int nSel = ((CListBox*)GetDlgItem(IDC_TARGET_LIST))->GetCurSel();
nTargetIndex = nSel;
if( ((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->GetCheck() ){
// For current doc, we need just the target
m_csHref = '#';
} else {
// For file, append target to current HREF,
// but strip off existing target first
int iHash = m_csHref.Find('#');
if( iHash>=0 ){
m_csHref = m_csHref.Left(iHash+1);
} else {
m_csHref += '#';
}
}
CString csTarget;
((CListBox*)GetDlgItem(IDC_TARGET_LIST))->GetText(nSel, csTarget);
m_csHref += csTarget;
(GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(TRUE);
UpdateData(FALSE);
}
void CLinkPage::OnHrefFile()
{
// Get data from dialog
if ( !UpdateData(TRUE) ){
return;
}
// Note that the file filter is set to *.html,
// but all other file types are also available
CString csFile = wfe_GetExistingFileName(this->m_hWnd,
szLoadString(IDS_LINK_TO_FILE), HTM, TRUE);
if( !csFile.IsEmpty() ) {
WFE_ConvertFile2Url(m_csHref, csFile);
// Convert to a relative URL and validate
ValidateHref();
UpdateData(FALSE);
SetModified(TRUE);
// Try to get list of targets from local file
OnTargetsInFile();
}
}
void CLinkPage::OnHrefUnlink()
{
SetModified(TRUE);
// Clear link from our member variable and
// the passed-in data, and the edit box
m_csHref = "";
if(m_pData->pURL){
XP_FREE(m_pData->pURL);
m_pData->pURL = NULL;
}
((CEdit *)GetDlgItem(IDC_HREF_URL))->SetWindowText("");
ED_ElementType type = EDT_GetCurrentElementType(m_pMWContext);
if( (m_bMayHaveOtherLinks && type == ED_ELEMENT_SELECTION /*||
(type == ED_ELEMENT_SELECTION && EDT_CanSetHREF(m_pMWContext)) */) &&
IDYES == MessageBox(szLoadString(IDS_REMOVE_OTHER_LINKS),
szLoadString(IDS_REMOVE_LINKS_CAPTION),
MB_ICONQUESTION | MB_YESNO) ){
// Remove just the HREF immediately using masked bits
EDT_CharacterData *pCharData = EDT_NewCharacterData();
if( pCharData ){
pCharData->mask = TF_HREF;
// "New" should set all values = 0;
EDT_SetCharacterData(m_pMWContext, pCharData);
EDT_FreeCharacterData(pCharData);
// We now have no links to remove
m_bMayHaveOtherLinks = FALSE;
// and our action is similar to Apply button
// in that we commited an action
OkToClose();
(GetDlgItem(IDC_HREF_UNLINK))->SetWindowText(szLoadString(IDS_REMOVE_LINK));
}
}
(GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(FALSE);
}
void CLinkPage::OnChangeHrefUrl()
{
SetModified(TRUE);
m_bHrefChanged = TRUE;
m_bValidHref = FALSE;
// We only need HREF, so don't bother with UpdateData()
CString csHREF;
GetDlgItem(IDC_HREF_URL)->GetWindowText(csHREF);
CleanupString(csHREF);
if( csHREF.IsEmpty() ){
// No URL, seems safe to redisplay the current list
GetTargetsInDoc();
} else if( (m_iTargetCount &&
((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->GetCheck()) ||
(((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->GetCheck() &&
m_csHref.Find(LPCSTR(m_csTargetFile)) == -1) ){
// We had a current target list, or URL was changed
// so it isn't the same as the last target file used.
// To remove uncertainty of what the target list refers to, remove it
m_iTargetCount = 0;
m_csTargetFile.Empty();
((CListBox*)GetDlgItem(IDC_TARGET_LIST))->ResetContent();
((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->SetCheck(0);
((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck(0);
}
(GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(!csHREF.IsEmpty() || m_bMayHaveOtherLinks);
// Update the common data structure with new HREF
// Can't use SetHrefData() cause we can't change m_csHREF
if(m_pData->pURL){
XP_FREE(m_pData->pURL);
m_pData->pURL = NULL;
}
if(!csHREF.IsEmpty()){
m_pData->pURL = XP_STRDUP(csHREF);
}
}
// Validate only after user leaves edit box
void CLinkPage::OnKillfocusHrefUrl()
{
if(m_bHrefChanged && UpdateData(TRUE)){
ValidateHref();
}
}
// Check for valid Href - convert to relative URL
// NOTE: Data must be read from control via DDX first
// This logic assumes that base document is local file,
// (We force saving a remote document before changing links)
void CLinkPage::ValidateHref()
{
m_bValidHref = TRUE;
CleanupString(m_csHref);
// Empty is OK - this is how we remove links
if ( m_csHref.IsEmpty() ){
m_csLastValidHref.Empty();
return;
}
// Strip off "#named_anchor" part and place in
// separate string???
XP_Bool bKeepLinks;
PREF_GetBoolPref("editor.publish_keep_links",&bKeepLinks);
if ( FE_ResolveLinkURL(m_pMWContext, m_csHref,bKeepLinks) ) {
// Save this as a valid reference
m_csLastValidHref = m_csHref;
} else {
// Error or user rejected the Href,
// restore to previous value
m_csHref = m_csLastValidHref;
SetModified(TRUE);
UpdateData(FALSE);
}
// We must always set the HREF data immediately
// because it will be accessed by
// CImagePage::OnOK before CLinkPage::OnOK
SetHrefData();
}
void CLinkPage::SetHrefData()
{
if(m_pData->pURL){
XP_FREE(m_pData->pURL);
m_pData->pURL = NULL;
}
if(!m_csHref.IsEmpty()){
m_pData->pURL = XP_STRDUP(m_csHref);
}
//TODO: Set pTarget and pMocha strings
#if 0
// Use this if we supply UI to change target frame
// For now, just pass through what's there?
if(m_pData->pTarget){
XP_FREE(m_pData->pTarget);
m_pData->pTarget = NULL;
}
if(!m_csTarget.IsEmpty()){
m_pData->pTarget = XP_STRDUP(m_csTarget);
}
#endif
}
void CLinkPage::OnExtraHTML()
{
CExtraHTMLDlg dlg(this, &m_pData->pExtra, IDS_HREF_TAG);
if( dlg.DoModal() && dlg.m_bDataChanged ){
SetModified(TRUE);
}
}
void CLinkPage::OnHelp()
{
NetHelp(HELP_PROPS_LINK);
}
void CLinkPage::OnOK()
{
CPropertyPage::OnOK();
// never visited this page or no change -- don't bother
if(!m_bActivated ||
!IS_APPLY_ENABLED(this)){
return;
}
GetDlgItem(IDC_HREF_URL)->GetWindowText(m_csHref);
CleanupString(m_csHref);
//EDT_BeginBatchChanges(m_pMWContext);
CleanupString(m_csAnchorEdit);
int nResult = 0;
// TODO: Test nResult for valid URL and add messages to user
// when there are problems
if ( m_iTargetCount ) {
nTargetIndex = ((CListBox*)GetDlgItem(IDC_TARGET_LIST))->GetCurSel();
//TODO: Append the "#named_anchor" to the m_csHref;
}
// If we have an image Anchor, the image property page
// will set HREF data.
if( ! (m_ppImage && *m_ppImage && **m_ppImage != '\0') ){
if ( EDT_CanSetHREF(m_pMWContext) ) {
// Associate a URL with selected text
// or existing link (text or image anchor)
// TODO: LLOYD: return error: nResult =
// EDT_SetHREF( m_pMWContext, szURL );
EDT_SetHREFData(m_pMWContext, m_pData);
// Note: This will remove a link if m_pData->pURL is NULL
}
else /* if(m_pData->pURL) */{
// We created a new link -
// Anchor text should have been typed
char * szAnchor;
if ( m_csAnchorEdit.IsEmpty() ) {
// No anchor text supplied, use URL
szAnchor = m_pData->pURL;
} else {
// Can't do cast of LPCSTR() directly! Gives syntax error!
const char * szStupidCompiler = LPCSTR(m_csAnchorEdit);
szAnchor = (char*)szStupidCompiler; // (char*)(LPCSTR(m_csAnchorEdit));
}
if( m_bInsert && m_pData->pURL ) {
// Insert both Anchor text and Href
// TODO: LLOYD: return error: nResult =
EDT_PasteHREF( m_pMWContext, &m_pData->pURL, &szAnchor, 1 );
// Set flag so future Apply actions will not insert another link
m_bInsert = FALSE;
// Move back one character so subsequent attributes Applied
// don't include following text.
EDT_PreviousChar( m_pMWContext, FALSE );
m_iCaretMovedBack++;
// Get the text just inserted
char * pNewText = EDT_GetHREFText(m_pMWContext);
if( pNewText == NULL ){
// If we insert a space after text, then
// the link text will be empty.
// We need to move back another character
// so current text element is the text, not the space,
// else subsequent calls to EDT_SetHREFData will
// attach URL to space and following text, not the
// newly-inserted text
EDT_PreviousChar( m_pMWContext, FALSE );
m_iCaretMovedBack++;
} else {
XP_FREE(pNewText);
}
// and set flag so we move forward upon exiting
// It would be a pain to allow replacing inserted anchor text,
// so disable control after 1st insert
(GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(FALSE);
} else {
EDT_SetHREFData(m_pMWContext, m_pData);
}
}
}
OkToClose();
//EDT_EndBatchChanges(m_pMWContext);
}
////////////////////////////////////////////////////////////////
/*
// **** TEMPLATE for property pages
/////////////////////////////////////////////////////////////////////
CPage::CPage(CWnd* pParent, MWContext * pMWContext,
EDT_<Data> * pData) // EDT data for this property
: CNetscapePropertyPage(CPage::IDD)
{
//{{AFX_DATA_INIT(CPage)
//}}AFX_DATA_INIT
ASSERT(pMWContext);
// ASSERT(pData);
m_bActivated = FALSE;
m_pMWContext = pMWContext;
EDT_<Data> * m_pData; // EDT data for this property
}
void CPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPage)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPage, CNetscapePropertyPage)
//{{AFX_MSG_MAP(CPage)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CPage::OnSetActive()
{
if(!CPropertyPage::OnSetActive())
return(FALSE);
if(m_bActivated)
return(TRUE);
// TODO - Fill in controls here
m_bActivated = TRUE;
// Send data to controls
UpdateData(FALSE);
return(TRUE);
}
void CPage::OnOK()
{
CPropertyPage::OnOK();
// never visited this page so don't bother
if(!m_bActivated)
return;
// TODO - Get control data back into pData here
}
*/
#endif // EDITOR