OpenClonk
C4Markup.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2011-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // markup tags for fonts
17 
18 #include "C4Include.h"
19 #include "lib/C4Markup.h"
21 
22 using namespace std::string_literals;
23 
24 std::string C4MarkupTag::OpeningTag() const
25 {
26  return "<"s + TagName() + ">";
27 }
28 
29 std::string C4MarkupTag::ClosingTag() const
30 {
31  return "</"s + TagName() + ">";
32 }
33 
34 void C4MarkupTagItalic::Apply(C4BltTransform &rBltTrf, bool fDoClr, DWORD &dwClr)
35 {
36  // do sheering
37  rBltTrf.mat[1]-=0.3f;
38 }
39 
40 void C4MarkupTagColor::Apply(C4BltTransform &rBltTrf, bool fDoClr, DWORD &dwClr)
41 {
42  // set color
43  if (fDoClr) dwClr = this->dwClr;
44 }
45 
46 
47 std::string C4MarkupTagColor::OpeningTag() const
48 {
49  return "<c "s + FormatString("%x", dwClr).getData() + ">";
50 }
51 
52 bool C4Markup::Read(const char **ppText, bool fSkip)
53 {
54  char Tag[50]; C4MarkupTag *pNewTag=nullptr; int iTagLen,iParLen;
55  // get tag
56  if (!SCopyEnclosed(*ppText, '<', '>', Tag, 49)) return false;
57  iTagLen=SLen(Tag);
58  // split tag to name and pars
59  char *szPars=nullptr; int iSPos;
60  if ((iSPos=SCharPos(' ', Tag))>-1)
61  {
62  Tag[iSPos]=0;
63  szPars=Tag+iSPos+1;
64  }
65  // closing tag?
66  if (Tag[0]=='/')
67  {
68  // no parameters
69  if (szPars) return false;
70  if (!fSkip)
71  {
72  // is this the tag to be closed?
73  if (!pLast) return false;
74  if (!SEqual(pLast->TagName(), Tag+1)) return false;
75  // close it
76  delete Pop();
77  }
78  }
79  // italic
80  else if (SEqual(Tag, "i"))
81  {
82  // no parameters
83  if (szPars) return false;
84  // create italic tag
85  if (!fSkip) pNewTag=new C4MarkupTagItalic();
86  }
87  // colored
88  else if (SEqual(Tag, "c"))
89  {
90  // no parameters?
91  if (!szPars) return false;
92  if ((iParLen=SLen(szPars))>8) return false;
93  if (!fSkip)
94  {
95  // get color value by parameter
96  DWORD dwClr=0;
97  for (int i=0; i<iParLen; ++i)
98  {
99  BYTE b;
100  if (szPars[i]>='0' && szPars[i]<='9') b=szPars[i]-'0';
101  else if (szPars[i]>='a' && szPars[i]<='f') b=szPars[i]-'a'+10;
102  else return false;
103  dwClr|=(b<<((iParLen-i-1)*4));
104  }
105  // adjust alpha if not given
106  if (iParLen<=6) dwClr|=0xff000000;
107  // create color tag
108  pNewTag=new C4MarkupTagColor(dwClr);
109  }
110  }
111  // unknown tag
112  else return false;
113  // add created tag
114  if (pNewTag) Push(pNewTag);
115  // advance past tag
116  *ppText+=iTagLen+2;
117  // success
118  return true;
119 }
120 
121 
122 
123 bool C4Markup::SkipTags(const char **ppText)
124 {
125  // read tags as long as found
126  while (**ppText=='<') if (!Read(ppText, true)) break;
127  // return whether end is reached
128  return !**ppText;
129 }
130 
131 
132 std::string C4Markup::ClosingTags() const
133 {
134  std::string result;
135  for (auto tag = pLast; tag; tag = tag->pPrev)
136  result += tag->ClosingTag();
137  return result;
138 }
139 
140 std::string C4Markup::OpeningTags() const
141 {
142  std::string result;
143  for (auto tag = pTags; tag; tag = tag->pNext)
144  result += tag->OpeningTag();
145  return result;
146 }
147 
148 bool C4Markup::StripMarkup(char *szText)
149 {
150  // skip any tags and inline-images
151  C4Markup mkup(false);
152  const char *szRead = szText, *szPos2;
153  do
154  {
155  mkup.SkipTags(&szRead);
156  if (szRead[0] == '{' && szRead[1] == '{' && szRead[2] != '{') // skip at {{{, because {{{id}} should be parsed as { {{id}} }.
157  {
158  if ((szPos2 = SSearch(szRead+2, "}}")))
159  // valid {{blub}}-tag
160  szRead = szPos2;
161  else
162  // invalid {{-tag
163  szRead += 2;
164  }
165  else if (szRead[0] == '}' && szRead[1] == '}')
166  // invalid }}-tag
167  szRead += 2;
168  }
169  while ((*szText++ = *szRead++));
170  return szText != szRead;
171 }
172 
174 {
175  // strip any markup codes from given text buffer
176  char *buf = sText->GrabPointer();
177  if (!buf) return false;
178  bool fSuccess = StripMarkup(buf);
179  sText->Take(buf);
180  return fSuccess;
181 }
#define s
#define b
uint8_t BYTE
uint32_t DWORD
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:369
bool SCopyEnclosed(const char *szSource, char cOpen, char cClose, char *sTarget, int iSize)
Definition: Standard.cpp:529
int SCharPos(char cTarget, const char *szInStr, int iIndex)
Definition: Standard.cpp:239
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
size_t SLen(const char *sptr)
Definition: Standard.h:74
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
std::string OpeningTags() const
Definition: C4Markup.cpp:140
std::string ClosingTags() const
Definition: C4Markup.cpp:132
bool SkipTags(const char **ppText)
Definition: C4Markup.cpp:123
static bool StripMarkup(char *szText)
Definition: C4Markup.cpp:148
bool Read(const char **ppText, bool fSkip=false)
Definition: C4Markup.cpp:52
void Apply(C4BltTransform &rBltTrf, bool fDoClr, DWORD &dwClr) override
Definition: C4Markup.cpp:40
std::string OpeningTag() const override
Definition: C4Markup.cpp:47
virtual std::string OpeningTag() const
Definition: C4Markup.cpp:24
virtual std::string ClosingTag() const
Definition: C4Markup.cpp:29
void Apply(C4BltTransform &rBltTrf, bool fDoClr, DWORD &dwClr) override
Definition: C4Markup.cpp:34
const char * getData() const
Definition: StdBuf.h:442
void Take(char *pnData)
Definition: StdBuf.h:457
char * GrabPointer()
Definition: StdBuf.h:459