CSimpleTextParser.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*******************************************************************
  2. *
  3. * File: CSimpleTextParser.cpp
  4. *
  5. * Author: Peter van Sebille (peter@yipton.net)
  6. *
  7. * (c) Copyright 2002, Peter van Sebille
  8. * All Rights Reserved
  9. *
  10. *******************************************************************/
  11. #include "CSimpleTextParser.h"
  12. enum
  13. {
  14. EBadTag,
  15. EBadZeroLengthTag,
  16. EBadIntegerParam,
  17. EBadAlignmentParam,
  18. EBadRgbColorParam
  19. };
  20. void Panic(TInt aPanic)
  21. {
  22. User::Panic(_L("STP"), aPanic);
  23. }
  24. CSimpleTextFormatParser* CSimpleTextFormatParser::NewLC()
  25. {
  26. CSimpleTextFormatParser* self = new(ELeave)CSimpleTextFormatParser;
  27. CleanupStack::PushL(self);
  28. self->ConstructL();
  29. return self;
  30. }
  31. CSimpleTextFormatParser::~CSimpleTextFormatParser()
  32. {
  33. delete iParaFormat;
  34. }
  35. void CSimpleTextFormatParser::ConstructL()
  36. {
  37. iParaFormat = CParaFormat::NewL();
  38. }
  39. void CSimpleTextFormatParser::SetBold(TBool aEnable)
  40. {
  41. iCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(aEnable ? EStrokeWeightBold : EStrokeWeightNormal);
  42. iCharMask.ClearAll();
  43. iCharMask.SetAttrib(EAttFontStrokeWeight);
  44. iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
  45. }
  46. void CSimpleTextFormatParser::SetItalic(TBool aEnable)
  47. {
  48. iCharFormat.iFontSpec.iFontStyle.SetPosture(aEnable ? EPostureItalic : EPostureUpright);
  49. iCharMask.ClearAll();
  50. iCharMask.SetAttrib(EAttFontPosture);
  51. iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
  52. }
  53. void CSimpleTextFormatParser::SetUnderLine(TBool aEnable)
  54. {
  55. iCharFormat.iFontPresentation.iUnderline = aEnable ? EUnderlineOn : EUnderlineOff;
  56. iCharMask.ClearAll();
  57. iCharMask.SetAttrib(EAttFontUnderline);
  58. iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
  59. }
  60. void CSimpleTextFormatParser::SetHiddenText(TBool aEnable)
  61. {
  62. iCharFormat.iFontPresentation.iHiddenText = aEnable;
  63. iCharMask.ClearAll();
  64. iCharMask.SetAttrib(EAttFontHiddenText);
  65. iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
  66. }
  67. TRgb CSimpleTextFormatParser::ForegroundColor()
  68. {
  69. iCharMask.ClearAll();
  70. iCharMask.SetAttrib(EAttColor);
  71. iRichText->GetCharFormat(iCharFormat, iCharMask, TextPos(), 0);
  72. return iCharFormat.iFontPresentation.iTextColor;
  73. }
  74. void CSimpleTextFormatParser::SetForegroundColor(const TRgb& aColor)
  75. {
  76. iCharFormat.iFontPresentation.iTextColor = aColor;
  77. iCharMask.ClearAll();
  78. iCharMask.SetAttrib(EAttColor);
  79. iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
  80. }
  81. void CSimpleTextFormatParser::SetBackgroundColor(const TRgb& aColor)
  82. {
  83. iParaFormat->iFillColor = aColor;
  84. iParaMask.ClearAll();
  85. iParaMask.SetAttrib(EAttFillColor);
  86. iRichText->ApplyParaFormatL(iParaFormat, iParaMask, ParaPos(), 0);
  87. }
  88. void CSimpleTextFormatParser::NewParagraph()
  89. {
  90. iCurrentPara++;
  91. iRichText->AppendParagraphL();
  92. AppendTextL(_L(""));
  93. }
  94. void CSimpleTextFormatParser::SetAlignment(CParaFormat::TAlignment aAlignment)
  95. {
  96. iParaFormat->iHorizontalAlignment = aAlignment;
  97. iParaMask.ClearAll();
  98. iParaMask.SetAttrib(EAttAlignment);
  99. iRichText->ApplyParaFormatL(iParaFormat, iParaMask, ParaPos(), 0);
  100. }
  101. void CSimpleTextFormatParser::SetFontHeight(TInt aHeight)
  102. {
  103. iCharFormat.iFontSpec.iHeight = (aHeight * KTwipsPerInch)/KPointsPerInch;
  104. iCharMask.ClearAll();
  105. iCharMask.SetAttrib(EAttFontHeight);
  106. iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
  107. }
  108. void CSimpleTextFormatParser::SetFontName(const TDesC& aName)
  109. {
  110. iCharFormat.iFontSpec.iTypeface.iName = aName;
  111. iCharFormat.iFontSpec.iTypeface.SetAttributes(0);
  112. iCharFormat.iFontSpec.iTypeface.SetIsProportional(ETrue);
  113. iCharMask.ClearAll();
  114. iCharMask.SetAttrib(EAttFontTypeface);
  115. iRichText->ApplyCharFormatL(iCharFormat, iCharMask, TextPos(), 0);
  116. }
  117. /*
  118. * Character formatting:
  119. * <b> Bold on
  120. * </b> Bold of
  121. * <i> Italic on
  122. * </i> Italic off
  123. * <u> Underline on
  124. * </u> Underline off
  125. * <h> Hidden text on **doesn't work**
  126. * </h> Hidden text off **doesn't work**
  127. * <f=name> Fontname: name (type: string)
  128. * <s=size> Fontsize: size (type: integer)
  129. * <fg=color> Foreground color: color (type: color)
  130. * </fg> Restore foreground color
  131. *
  132. * Paragraph formatting:
  133. * <p> New paragraph - will reset both character & paragraph formatting to defaults
  134. * <a=align> Alignment: aling (type: alignement)
  135. * <bg=color> Background color: color (type: color) **doesn't work**
  136. *
  137. * Special characters:
  138. * </<> The character: <
  139. *
  140. * Types:
  141. * - string:
  142. * - integer: Either decimal or hexidecimal value
  143. * - color: Either integer specifing rgb value, or (r,g,b) in which r, g and b are of type integer
  144. * - align: element of enumeration {center, left, right}
  145. *
  146. * Comments:
  147. * The syntax/parser is fairly simplistic. The parser is not trying to match a tag like
  148. * <tag> </tag> as XML/HTML do. Basically, when it encounters a tag (e.g., <b>) it will
  149. * simply instruct the the editor to apply the formatting from the current position as
  150. * specified by the tag (e.g., enable bold). For example, <b><b>Hello</b>World</b> results
  151. * in Hello displayed in a Bold font and World in a normal font.
  152. *
  153. * The only case where state is maintained is when using <fg=color> and </fg>. The current
  154. * fg color is stored when parsing <fg=color> and restored when doing </fg>. Again, <fg> and
  155. * </fg> don't have the XML/HTML <tag> </tag> behavior. For example:
  156. * <fg=red>Peter<fg=blue>was</fg></fg>here
  157. * results in "Peter" displayed in red, "was" displayed in blue and "here" displayed in red.
  158. * It literally goes like this:
  159. * 1) <fg=red> --> apply editor text color red, previous color = whatever the editor's text color is now
  160. * 2) <fg=blue> --> apply editor text color blue, previous color = whatever the editor's text color
  161. * is now --> red
  162. * 3) </fg> --> apply editor text to previous color --> red
  163. * 4) </fg> --> apply editor text to previous color --> red
  164. *
  165. * What you probably wanted was:
  166. * <fg=red>Peter</fg><fg=blue>was</fg>here
  167. * Now "Peter" is displayed in red, "was" in blue and "here" in the default editor's color
  168. */
  169. static TUint32 ParseInteger(const TDesC& aString)
  170. {
  171. TUint32 val = 0;
  172. TBool parsed = EFalse;
  173. if (aString.Length() > 2)
  174. {
  175. if ((aString[0] == '0') && ((aString[0] == 'x') || (aString[0] == 'X')))
  176. {
  177. TLex lex(aString.Right(aString.Length()-2));
  178. if (lex.Val(val, EHex) != KErrNone)
  179. {
  180. __ASSERT_DEBUG(ETrue, Panic(EBadIntegerParam));
  181. }
  182. parsed = ETrue;
  183. }
  184. }
  185. if (!parsed)
  186. {
  187. TLex lex(aString);
  188. if (lex.Val(val, EDecimal) != KErrNone)
  189. {
  190. __ASSERT_DEBUG(ETrue, Panic(EBadIntegerParam));
  191. }
  192. }
  193. return val;
  194. }
  195. static TRgb ParseColor(const TDesC& aString)
  196. {
  197. if (aString.Length() > 0)
  198. {
  199. if (aString[0] == 'R')
  200. {
  201. if (aString.Compare(_L("RgbBlack")) == 0)
  202. return KRgbBlack;
  203. else if (aString.Compare(_L("RgbDarkGray")) == 0)
  204. return KRgbDarkGray;
  205. else if (aString.Compare(_L("RgbDarkRed")) == 0)
  206. return KRgbDarkRed;
  207. else if (aString.Compare(_L("RgbDarkGreen")) == 0)
  208. return KRgbDarkGreen;
  209. else if (aString.Compare(_L("RgbDarkYellow")) == 0)
  210. return KRgbDarkYellow;
  211. else if (aString.Compare(_L("RgbDarkBlue")) == 0)
  212. return KRgbDarkBlue;
  213. else if (aString.Compare(_L("RgbDarkMagenta")) == 0)
  214. return KRgbDarkMagenta;
  215. else if (aString.Compare(_L("RgbDarkCyan")) == 0)
  216. return KRgbDarkCyan;
  217. else if (aString.Compare(_L("RgbRed")) == 0)
  218. return KRgbRed;
  219. else if (aString.Compare(_L("RgbGreen")) == 0)
  220. return KRgbGreen;
  221. else if (aString.Compare(_L("RgbYellow")) == 0)
  222. return KRgbYellow;
  223. else if (aString.Compare(_L("RgbBlue")) == 0)
  224. return KRgbBlue;
  225. else if (aString.Compare(_L("RgbMagenta")) == 0)
  226. return KRgbMagenta;
  227. else if (aString.Compare(_L("RgbCyan")) == 0)
  228. return KRgbCyan;
  229. else if (aString.Compare(_L("RgbGray")) == 0)
  230. return KRgbGray;
  231. else if (aString.Compare(_L("RgbWhite")) == 0)
  232. return KRgbWhite;
  233. else
  234. {
  235. __ASSERT_DEBUG(ETrue, Panic(EBadRgbColorParam));
  236. }
  237. }
  238. return ParseInteger(aString);
  239. }
  240. __ASSERT_DEBUG(ETrue, Panic(EBadRgbColorParam));
  241. return KRgbBlack;
  242. }
  243. static CParaFormat::TAlignment ParseAlignment(const TDesC& aString)
  244. {
  245. if (aString.Compare(_L("center")) == 0)
  246. {
  247. return CParaFormat::ECenterAlign;
  248. }
  249. else if (aString.Compare(_L("left")) == 0)
  250. {
  251. return CParaFormat::ELeftAlign;
  252. }
  253. else if (aString.Compare(_L("right")) == 0)
  254. {
  255. return CParaFormat::ERightAlign;
  256. }
  257. __ASSERT_DEBUG(ETrue, Panic(EBadAlignmentParam));
  258. return CParaFormat::ECenterAlign;
  259. }
  260. void CSimpleTextFormatParser::ParseTagL(const TDesC& aTag)
  261. {
  262. TInt tagLength = aTag.Length();
  263. if (tagLength == 0)
  264. {
  265. __ASSERT_DEBUG(ETrue, Panic(EBadZeroLengthTag));
  266. return;
  267. }
  268. TPtrC param(_L(""));
  269. TInt pos = aTag.Find(_L("="));
  270. if (pos>0)
  271. {
  272. param.Set(aTag.Right(aTag.Length()-pos-1));
  273. tagLength = pos;
  274. }
  275. TPtrC tag = aTag.Left(tagLength);
  276. // RDebug::Print(_L("tag=%S, param=%S"), &tag, &param);
  277. switch (tagLength)
  278. {
  279. case 1:
  280. {
  281. if (tag.Compare(_L("a")) == 0)
  282. SetAlignment(ParseAlignment(param));
  283. else if (tag.Compare(_L("b")) == 0)
  284. SetBold();
  285. else if (tag.Compare(_L("f")) == 0)
  286. SetFontName(param);
  287. else if (tag.Compare(_L("h")) == 0)
  288. SetHiddenText();
  289. else if (tag.Compare(_L("i")) == 0)
  290. SetItalic();
  291. else if (tag.Compare(_L("p")) == 0)
  292. NewParagraph();
  293. else if (tag.Compare(_L("s")) == 0)
  294. SetFontHeight(ParseInteger(param));
  295. else if (tag.Compare(_L("u")) == 0)
  296. SetUnderLine();
  297. else
  298. {
  299. __ASSERT_DEBUG(ETrue, Panic(EBadTag));
  300. }
  301. break;
  302. }
  303. case 2:
  304. {
  305. if (tag.Compare(_L("/b")) == 0)
  306. SetBold(EFalse);
  307. if (tag.Compare(_L("bg")) == 0)
  308. SetBackgroundColor(ParseColor(param));
  309. if (tag.Compare(_L("fg")) == 0)
  310. {
  311. iPrevFgColor = ForegroundColor();
  312. SetForegroundColor(ParseColor(param));
  313. }
  314. else if (tag.Compare(_L("/h")) == 0)
  315. SetHiddenText(EFalse);
  316. else if (tag.Compare(_L("/i")) == 0)
  317. SetItalic(EFalse);
  318. else if (tag.Compare(_L("/u")) == 0)
  319. SetUnderLine(EFalse);
  320. else if (tag.Compare(_L("/<")) == 0)
  321. AppendTextL(_L("<"));
  322. break;
  323. }
  324. case 3:
  325. {
  326. if (tag.Compare(_L("/fg")) == 0)
  327. SetForegroundColor(iPrevFgColor);
  328. break;
  329. }
  330. default:
  331. ;
  332. }
  333. }
  334. void CSimpleTextFormatParser::ParseL(const TDesC& aSimpleText, CRichText& aRichText)
  335. {
  336. iRichText = &aRichText;
  337. iCurrentPara = 0;
  338. TBool done = EFalse;
  339. TPtrC simpleText(aSimpleText);
  340. do
  341. {
  342. TInt pos = simpleText.Locate('<');
  343. if (pos > 0)
  344. {
  345. AppendTextL(simpleText.Left(pos));
  346. simpleText.Set(simpleText.Right(simpleText.Length() - pos));
  347. }
  348. else if (pos == 0)
  349. {
  350. pos = simpleText.Locate('>');
  351. if (pos<=0)
  352. User::Leave(KErrArgument);
  353. ParseTagL(simpleText.Mid(1, pos-1));
  354. simpleText.Set(simpleText.Right(simpleText.Length() - pos - 1));
  355. }
  356. else
  357. {
  358. AppendTextL(simpleText);
  359. done = ETrue;
  360. }
  361. } while (!done);
  362. }
  363. TInt CSimpleTextFormatParser::TextPos()
  364. {
  365. return iRichText->DocumentLength();
  366. #if 0
  367. TInt pos, length;
  368. pos = iRichText->CharPosOfParagraph(length, iCurrentPara);
  369. return pos+length-1;
  370. #endif
  371. }
  372. TInt CSimpleTextFormatParser::ParaPos()
  373. {
  374. return TextPos();
  375. #if 0
  376. TInt pos, length;
  377. pos = iRichText->CharPosOfParagraph(length, iCurrentPara);
  378. return pos+length-1;
  379. #endif
  380. }
  381. void CSimpleTextFormatParser::AppendTextL(const TDesC& aText)
  382. {
  383. // RDebug::Print(_L("text=%S"), &aText);
  384. iRichText->InsertL(TextPos(), aText);
  385. }
  386. #if 0
  387. void CTestDialog::ShowTextL(CRichText& aRichText)
  388. {
  389. aRichText.Reset();
  390. TCharFormat charFormat;
  391. TCharFormatMask charMask;
  392. aRichText.GetCharFormat(charFormat, charMask, 0, 0);
  393. TInt para = 0;
  394. AppendTextL(_L("http://www.yipton.net"), aRichText);
  395. para++;
  396. aRichText.AppendParagraphL();
  397. CParaFormat* paraFormat = CParaFormat::NewLC();
  398. TParaFormatMask paraMask;
  399. aRichText.GetParaFormatL(paraFormat, paraMask, ParaPos(aRichText, para), 0);
  400. paraFormat->iHorizontalAlignment = CParaFormat::ECenterAlign;
  401. paraMask.ClearAll();
  402. paraMask.SetAttrib(EAttAlignment);
  403. aRichText.ApplyParaFormatL(paraFormat, paraMask, ParaPos(aRichText, para), 0);
  404. charFormat.iFontPresentation.iUnderline = EUnderlineOn;
  405. charFormat.iFontSpec.iFontStyle.SetPosture(EPostureItalic);
  406. charMask.ClearAll();
  407. charMask.SetAttrib(EAttFontPosture);
  408. charMask.SetAttrib(EAttFontUnderline);
  409. aRichText.ApplyCharFormatL(charFormat, charMask, TextPos(aRichText, para));
  410. AppendTextL(_L("mailto:Peter is here"), aRichText, para);
  411. para++;
  412. aRichText.AppendParagraphL();
  413. TFontSpec fontSpec(_L("edmunds"), 20 * KPointsPerInch);
  414. // CFont* font = NULL;
  415. // iCoeEnv->ScreenDevice()->GetNearestFontInTwips(font, fontSpec);
  416. charFormat.iFontSpec = fontSpec;
  417. charMask.ClearAll();
  418. charMask.SetAttrib(EAttFontHeight);
  419. charMask.SetAttrib(EAttFontTypeface);
  420. aRichText.ApplyCharFormatL(charFormat, charMask, TextPos(aRichText, para));
  421. AppendTextL(_L("mailto:Peter is here"), aRichText, para);
  422. CleanupStack::PopAndDestroy();
  423. }
  424. #endif