mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
7782 lines
245 KiB
C++
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
|
|
// TODO: How can we know if current URL is same as HREF?
|
|
((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
|