picodrive/platform/uiq3/CSimpleTextParser.cpp
notaz cc68a136aa initial import
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@2 be3aeb3a-fb24-0410-a615-afba39da0efa
2006-12-19 20:53:21 +00:00

477 lines
13 KiB
C++

/*******************************************************************
*
* File: CSimpleTextParser.cpp
*
* Author: Peter van Sebille (peter@yipton.net)
*
* (c) Copyright 2002, Peter van Sebille
* All Rights Reserved
*
*******************************************************************/
#include "CSimpleTextParser.h"
enum
{
EBadTag,
EBadZeroLengthTag,
EBadIntegerParam,
EBadAlignmentParam,
EBadRgbColorParam
};
void Panic(TInt aPanic)
{
User::Panic(_L("STP"), aPanic);
}
CSimpleTextFormatParser* CSimpleTextFormatParser::NewLC()
{
CSimpleTextFormatParser* self = new(ELeave)CSimpleTextFormatParser;
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CSimpleTextFormatParser::~CSimpleTextFormatParser()
{
delete iParaFormat;
}
void CSimpleTextFormatParser::ConstructL()
{
iParaFormat = CParaFormat::NewL();
}
void CSimpleTextFormatParser::SetBold(TBool aEnable)
{
iCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(aEnable ? EStrokeWeightBold : EStrokeWeightNormal);
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttFontStrokeWeight);
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
}
void CSimpleTextFormatParser::SetItalic(TBool aEnable)
{
iCharFormat.iFontSpec.iFontStyle.SetPosture(aEnable ? EPostureItalic : EPostureUpright);
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttFontPosture);
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
}
void CSimpleTextFormatParser::SetUnderLine(TBool aEnable)
{
iCharFormat.iFontPresentation.iUnderline = aEnable ? EUnderlineOn : EUnderlineOff;
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttFontUnderline);
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
}
void CSimpleTextFormatParser::SetHiddenText(TBool aEnable)
{
iCharFormat.iFontPresentation.iHiddenText = aEnable;
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttFontHiddenText);
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
}
TRgb CSimpleTextFormatParser::ForegroundColor()
{
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttColor);
iRichText->GetCharFormat(iCharFormat, iCharMask, TextPos(), 0);
return iCharFormat.iFontPresentation.iTextColor;
}
void CSimpleTextFormatParser::SetForegroundColor(const TRgb& aColor)
{
iCharFormat.iFontPresentation.iTextColor = aColor;
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttColor);
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
}
void CSimpleTextFormatParser::SetBackgroundColor(const TRgb& aColor)
{
iParaFormat->iFillColor = aColor;
iParaMask.ClearAll();
iParaMask.SetAttrib(EAttFillColor);
iRichText->ApplyParaFormatL(iParaFormat, iParaMask, ParaPos(), 0);
}
void CSimpleTextFormatParser::NewParagraph()
{
iCurrentPara++;
iRichText->AppendParagraphL();
AppendTextL(_L(""));
}
void CSimpleTextFormatParser::SetAlignment(CParaFormat::TAlignment aAlignment)
{
iParaFormat->iHorizontalAlignment = aAlignment;
iParaMask.ClearAll();
iParaMask.SetAttrib(EAttAlignment);
iRichText->ApplyParaFormatL(iParaFormat, iParaMask, ParaPos(), 0);
}
void CSimpleTextFormatParser::SetFontHeight(TInt aHeight)
{
iCharFormat.iFontSpec.iHeight = (aHeight * KTwipsPerInch)/KPointsPerInch;
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttFontHeight);
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
}
void CSimpleTextFormatParser::SetFontName(const TDesC& aName)
{
iCharFormat.iFontSpec.iTypeface.iName = aName;
iCharFormat.iFontSpec.iTypeface.SetAttributes(0);
iCharFormat.iFontSpec.iTypeface.SetIsProportional(ETrue);
iCharMask.ClearAll();
iCharMask.SetAttrib(EAttFontTypeface);
iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
}
/*
* Character formatting:
* <b> Bold on
* </b> Bold of
* <i> Italic on
* </i> Italic off
* <u> Underline on
* </u> Underline off
* <h> Hidden text on **doesn't work**
* </h> Hidden text off **doesn't work**
* <f=name> Fontname: name (type: string)
* <s=size> Fontsize: size (type: integer)
* <fg=color> Foreground color: color (type: color)
* </fg> Restore foreground color
*
* Paragraph formatting:
* <p> New paragraph - will reset both character & paragraph formatting to defaults
* <a=align> Alignment: aling (type: alignement)
* <bg=color> Background color: color (type: color) **doesn't work**
*
* Special characters:
* </<> The character: <
*
* Types:
* - string:
* - integer: Either decimal or hexidecimal value
* - color: Either integer specifing rgb value, or (r,g,b) in which r, g and b are of type integer
* - align: element of enumeration {center, left, right}
*
* Comments:
* The syntax/parser is fairly simplistic. The parser is not trying to match a tag like
* <tag> </tag> as XML/HTML do. Basically, when it encounters a tag (e.g., <b>) it will
* simply instruct the the editor to apply the formatting from the current position as
* specified by the tag (e.g., enable bold). For example, <b><b>Hello</b>World</b> results
* in Hello displayed in a Bold font and World in a normal font.
*
* The only case where state is maintained is when using <fg=color> and </fg>. The current
* fg color is stored when parsing <fg=color> and restored when doing </fg>. Again, <fg> and
* </fg> don't have the XML/HTML <tag> </tag> behavior. For example:
* <fg=red>Peter<fg=blue>was</fg></fg>here
* results in "Peter" displayed in red, "was" displayed in blue and "here" displayed in red.
* It literally goes like this:
* 1) <fg=red> --> apply editor text color red, previous color = whatever the editor's text color is now
* 2) <fg=blue> --> apply editor text color blue, previous color = whatever the editor's text color
* is now --> red
* 3) </fg> --> apply editor text to previous color --> red
* 4) </fg> --> apply editor text to previous color --> red
*
* What you probably wanted was:
* <fg=red>Peter</fg><fg=blue>was</fg>here
* Now "Peter" is displayed in red, "was" in blue and "here" in the default editor's color
*/
static TUint32 ParseInteger(const TDesC& aString)
{
TUint32 val = 0;
TBool parsed = EFalse;
if (aString.Length() > 2)
{
if ((aString[0] == '0') && ((aString[0] == 'x') || (aString[0] == 'X')))
{
TLex lex(aString.Right(aString.Length()-2));
if (lex.Val(val, EHex) != KErrNone)
{
__ASSERT_DEBUG(ETrue, Panic(EBadIntegerParam));
}
parsed = ETrue;
}
}
if (!parsed)
{
TLex lex(aString);
if (lex.Val(val, EDecimal) != KErrNone)
{
__ASSERT_DEBUG(ETrue, Panic(EBadIntegerParam));
}
}
return val;
}
static TRgb ParseColor(const TDesC& aString)
{
if (aString.Length() > 0)
{
if (aString[0] == 'R')
{
if (aString.Compare(_L("RgbBlack")) == 0)
return KRgbBlack;
else if (aString.Compare(_L("RgbDarkGray")) == 0)
return KRgbDarkGray;
else if (aString.Compare(_L("RgbDarkRed")) == 0)
return KRgbDarkRed;
else if (aString.Compare(_L("RgbDarkGreen")) == 0)
return KRgbDarkGreen;
else if (aString.Compare(_L("RgbDarkYellow")) == 0)
return KRgbDarkYellow;
else if (aString.Compare(_L("RgbDarkBlue")) == 0)
return KRgbDarkBlue;
else if (aString.Compare(_L("RgbDarkMagenta")) == 0)
return KRgbDarkMagenta;
else if (aString.Compare(_L("RgbDarkCyan")) == 0)
return KRgbDarkCyan;
else if (aString.Compare(_L("RgbRed")) == 0)
return KRgbRed;
else if (aString.Compare(_L("RgbGreen")) == 0)
return KRgbGreen;
else if (aString.Compare(_L("RgbYellow")) == 0)
return KRgbYellow;
else if (aString.Compare(_L("RgbBlue")) == 0)
return KRgbBlue;
else if (aString.Compare(_L("RgbMagenta")) == 0)
return KRgbMagenta;
else if (aString.Compare(_L("RgbCyan")) == 0)
return KRgbCyan;
else if (aString.Compare(_L("RgbGray")) == 0)
return KRgbGray;
else if (aString.Compare(_L("RgbWhite")) == 0)
return KRgbWhite;
else
{
__ASSERT_DEBUG(ETrue, Panic(EBadRgbColorParam));
}
}
return ParseInteger(aString);
}
__ASSERT_DEBUG(ETrue, Panic(EBadRgbColorParam));
return KRgbBlack;
}
static CParaFormat::TAlignment ParseAlignment(const TDesC& aString)
{
if (aString.Compare(_L("center")) == 0)
{
return CParaFormat::ECenterAlign;
}
else if (aString.Compare(_L("left")) == 0)
{
return CParaFormat::ELeftAlign;
}
else if (aString.Compare(_L("right")) == 0)
{
return CParaFormat::ERightAlign;
}
__ASSERT_DEBUG(ETrue, Panic(EBadAlignmentParam));
return CParaFormat::ECenterAlign;
}
void CSimpleTextFormatParser::ParseTagL(const TDesC& aTag)
{
TInt tagLength = aTag.Length();
if (tagLength == 0)
{
__ASSERT_DEBUG(ETrue, Panic(EBadZeroLengthTag));
return;
}
TPtrC param(_L(""));
TInt pos = aTag.Find(_L("="));
if (pos>0)
{
param.Set(aTag.Right(aTag.Length()-pos-1));
tagLength = pos;
}
TPtrC tag = aTag.Left(tagLength);
// RDebug::Print(_L("tag=%S, param=%S"), &tag, &param);
switch (tagLength)
{
case 1:
{
if (tag.Compare(_L("a")) == 0)
SetAlignment(ParseAlignment(param));
else if (tag.Compare(_L("b")) == 0)
SetBold();
else if (tag.Compare(_L("f")) == 0)
SetFontName(param);
else if (tag.Compare(_L("h")) == 0)
SetHiddenText();
else if (tag.Compare(_L("i")) == 0)
SetItalic();
else if (tag.Compare(_L("p")) == 0)
NewParagraph();
else if (tag.Compare(_L("s")) == 0)
SetFontHeight(ParseInteger(param));
else if (tag.Compare(_L("u")) == 0)
SetUnderLine();
else
{
__ASSERT_DEBUG(ETrue, Panic(EBadTag));
}
break;
}
case 2:
{
if (tag.Compare(_L("/b")) == 0)
SetBold(EFalse);
if (tag.Compare(_L("bg")) == 0)
SetBackgroundColor(ParseColor(param));
if (tag.Compare(_L("fg")) == 0)
{
iPrevFgColor = ForegroundColor();
SetForegroundColor(ParseColor(param));
}
else if (tag.Compare(_L("/h")) == 0)
SetHiddenText(EFalse);
else if (tag.Compare(_L("/i")) == 0)
SetItalic(EFalse);
else if (tag.Compare(_L("/u")) == 0)
SetUnderLine(EFalse);
else if (tag.Compare(_L("/<")) == 0)
AppendTextL(_L("<"));
break;
}
case 3:
{
if (tag.Compare(_L("/fg")) == 0)
SetForegroundColor(iPrevFgColor);
break;
}
default:
;
}
}
void CSimpleTextFormatParser::ParseL(const TDesC& aSimpleText, CRichText& aRichText)
{
iRichText = &aRichText;
iCurrentPara = 0;
TBool done = EFalse;
TPtrC simpleText(aSimpleText);
do
{
TInt pos = simpleText.Locate('<');
if (pos > 0)
{
AppendTextL(simpleText.Left(pos));
simpleText.Set(simpleText.Right(simpleText.Length() - pos));
}
else if (pos == 0)
{
pos = simpleText.Locate('>');
if (pos<=0)
User::Leave(KErrArgument);
ParseTagL(simpleText.Mid(1, pos-1));
simpleText.Set(simpleText.Right(simpleText.Length() - pos - 1));
}
else
{
AppendTextL(simpleText);
done = ETrue;
}
} while (!done);
}
TInt CSimpleTextFormatParser::TextPos()
{
return iRichText->DocumentLength();
#if 0
TInt pos, length;
pos = iRichText->CharPosOfParagraph(length, iCurrentPara);
return pos+length-1;
#endif
}
TInt CSimpleTextFormatParser::ParaPos()
{
return TextPos();
#if 0
TInt pos, length;
pos = iRichText->CharPosOfParagraph(length, iCurrentPara);
return pos+length-1;
#endif
}
void CSimpleTextFormatParser::AppendTextL(const TDesC& aText)
{
// RDebug::Print(_L("text=%S"), &aText);
iRichText->InsertL(TextPos(), aText);
}
#if 0
void CTestDialog::ShowTextL(CRichText& aRichText)
{
aRichText.Reset();
TCharFormat charFormat;
TCharFormatMask charMask;
aRichText.GetCharFormat(charFormat, charMask, 0, 0);
TInt para = 0;
AppendTextL(_L("http://www.yipton.net"), aRichText);
para++;
aRichText.AppendParagraphL();
CParaFormat* paraFormat = CParaFormat::NewLC();
TParaFormatMask paraMask;
aRichText.GetParaFormatL(paraFormat, paraMask, ParaPos(aRichText, para), 0);
paraFormat->iHorizontalAlignment = CParaFormat::ECenterAlign;
paraMask.ClearAll();
paraMask.SetAttrib(EAttAlignment);
aRichText.ApplyParaFormatL(paraFormat, paraMask, ParaPos(aRichText, para), 0);
charFormat.iFontPresentation.iUnderline = EUnderlineOn;
charFormat.iFontSpec.iFontStyle.SetPosture(EPostureItalic);
charMask.ClearAll();
charMask.SetAttrib(EAttFontPosture);
charMask.SetAttrib(EAttFontUnderline);
aRichText.ApplyCharFormatL(charFormat, charMask, TextPos(aRichText, para));
AppendTextL(_L("mailto:Peter is here"), aRichText, para);
para++;
aRichText.AppendParagraphL();
TFontSpec fontSpec(_L("edmunds"), 20 * KPointsPerInch);
// CFont* font = NULL;
// iCoeEnv->ScreenDevice()->GetNearestFontInTwips(font, fontSpec);
charFormat.iFontSpec = fontSpec;
charMask.ClearAll();
charMask.SetAttrib(EAttFontHeight);
charMask.SetAttrib(EAttFontTypeface);
aRichText.ApplyCharFormatL(charFormat, charMask, TextPos(aRichText, para));
AppendTextL(_L("mailto:Peter is here"), aRichText, para);
CleanupStack::PopAndDestroy();
}
#endif