mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
477 lines
13 KiB
C++
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, ¶m);
|
|
|
|
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
|