4#include "Stroika/Frameworks/StroikaPreComp.h"
12#include "Stroika/Foundation/Characters/LineEndings.h"
13#include "Stroika/Frameworks/Led/Config.h"
14#include "Stroika/Frameworks/Led/StyledTextEmbeddedObjects.h"
16#include "StyledTextIO_HTML.h"
21using namespace Stroika::Frameworks;
22using namespace Stroika::Frameworks::Led;
23using namespace Stroika::Frameworks::Led::StyledTextIO;
27 bool ParseStringToInt_ (
const string& s,
int* t)
31 l = strtol (s.c_str (), &e, 10);
32 if (s.c_str () == e) {
41 inline bool IsASCIISpace_ (Led_tChar c)
43 return isascii (c) and isspace (c);
46 constexpr pair<string_view, string_view> kColorNameTable_[] = {
47 {
"black",
"000000"}, {
"silver",
"C0C0C0"}, {
"gray",
"808080"}, {
"white",
"FFFFFF"}, {
"maroon",
"800000"}, {
"red",
"FF0000"},
48 {
"purple",
"800080"}, {
"fuchsia",
"FF00FF"}, {
"green",
"008000"}, {
"lime",
"00FF00"}, {
"olive",
"808000"}, {
"yellow",
"FFFF00"},
49 {
"navy",
"000080"}, {
"blue",
"0000FF"}, {
"teal",
"008080"}, {
"aqua",
"00FFFF"},
52 inline char NumToHexChar_ (
unsigned i)
56 return static_cast<char> (i +
'0');
59 return static_cast<char> (i - 10 +
'a');
62 inline unsigned short HexCharToNum_ (
char c)
64 if (c >=
'0' and c <=
'9') {
67 else if (c >=
'a' and c <=
'f') {
70 else if (c >=
'A' and c <=
'F') {
77 inline bool ParseColorString_ (
string colorStr,
Color* color)
79 for (
size_t i = 0; i < Memory::NEltsOf (kColorNameTable_); ++i) {
80 if (Led_CasedStringsEqual (colorStr, kColorNameTable_[i].first)) {
81 colorStr = kColorNameTable_[i].second;
86 if (colorStr.length () == 6) {
87 unsigned short red = HexCharToNum_ (colorStr[0]) * 16 + HexCharToNum_ (colorStr[1]);
88 unsigned short green = HexCharToNum_ (colorStr[2]) * 16 + HexCharToNum_ (colorStr[3]);
89 unsigned short blue = HexCharToNum_ (colorStr[4]) * 16 + HexCharToNum_ (colorStr[5]);
90 *color =
Color (red == 255 ? 0xffff : red << 8, green == 255 ? 0xffff : green << 8, blue == 255 ? 0xffff : blue << 8);
102HTMLInfo::EntityRefMapEntry HTMLInfo::sDefaultEntityRefMapTable[] = {
104 EntityRefMapEntry{
"euro", 0x20ac},
109 EntityRefMapEntry{
"nbsp", 0x00a0},
110 EntityRefMapEntry{
"iexcl", 0x00a1},
111 EntityRefMapEntry{
"cent", 0x00a2},
112 EntityRefMapEntry{
"pound", 0x00a3},
113 EntityRefMapEntry{
"curren", 0x00a4},
114 EntityRefMapEntry{
"yen", 0x00a5},
115 EntityRefMapEntry{
"brvbar", 0x00a6},
116 EntityRefMapEntry{
"sect", 0x00a7},
117 EntityRefMapEntry{
"uml", 0x00a8},
118 EntityRefMapEntry{
"copy", 0x00a9},
119 EntityRefMapEntry{
"ordf", 0x00aa},
120 EntityRefMapEntry{
"laquo", 0x00ab},
121 EntityRefMapEntry{
"not", 0x00ac},
122 EntityRefMapEntry{
"shy", 0x00ad},
123 EntityRefMapEntry{
"reg", 0x00ae},
124 EntityRefMapEntry{
"macr", 0x00af},
125 EntityRefMapEntry{
"deg", 0x00b0},
126 EntityRefMapEntry{
"plusmn", 0x00b1},
127 EntityRefMapEntry{
"sup2", 0x00b2},
128 EntityRefMapEntry{
"sup3", 0x00b3},
129 EntityRefMapEntry{
"acute", 0x00b4},
130 EntityRefMapEntry{
"micro", 0x00b5},
131 EntityRefMapEntry{
"para", 0x00b6},
132 EntityRefMapEntry{
"middot", 0x00b7},
133 EntityRefMapEntry{
"cedil", 0x00b8},
134 EntityRefMapEntry{
"sup1", 0x00b9},
135 EntityRefMapEntry{
"ordm", 0x00ba},
136 EntityRefMapEntry{
"raquo", 0x00bb},
137 EntityRefMapEntry{
"frac14", 0x00bc},
138 EntityRefMapEntry{
"frac12", 0x00bd},
139 EntityRefMapEntry{
"frac34", 0x00be},
140 EntityRefMapEntry{
"iquest", 0x00bf},
141 EntityRefMapEntry{
"Agrave", 0x00c0},
142 EntityRefMapEntry{
"Aacute", 0x00c1},
143 EntityRefMapEntry{
"Acirc", 0x00c2},
144 EntityRefMapEntry{
"Atilde", 0x00c3},
145 EntityRefMapEntry{
"Auml", 0x00c4},
146 EntityRefMapEntry{
"Aring", 0x00c5},
147 EntityRefMapEntry{
"AElig", 0x00c6},
148 EntityRefMapEntry{
"Ccedil", 0x00c7},
149 EntityRefMapEntry{
"Egrave", 0x00c8},
150 EntityRefMapEntry{
"Eacute", 0x00c9},
151 EntityRefMapEntry{
"Ecirc", 0x00ca},
152 EntityRefMapEntry{
"Euml", 0x00cb},
153 EntityRefMapEntry{
"Igrave", 0x00cc},
154 EntityRefMapEntry{
"Iacute", 0x00cd},
155 EntityRefMapEntry{
"Icirc", 0x00ce},
156 EntityRefMapEntry{
"Iuml", 0x00cf},
157 EntityRefMapEntry{
"ETH", 0x00d0},
158 EntityRefMapEntry{
"Ntilde", 0x00d1},
159 EntityRefMapEntry{
"Ograve", 0x00d2},
160 EntityRefMapEntry{
"Oacute", 0x00d3},
161 EntityRefMapEntry{
"Ocirc", 0x00d4},
162 EntityRefMapEntry{
"Otilde", 0x00d5},
163 EntityRefMapEntry{
"Ouml", 0x00d6},
164 EntityRefMapEntry{
"times", 0x00d7},
165 EntityRefMapEntry{
"Oslash", 0x00d8},
166 EntityRefMapEntry{
"Ugrave", 0x00d9},
167 EntityRefMapEntry{
"Uacute", 0x00da},
168 EntityRefMapEntry{
"Ucirc", 0x00db},
169 EntityRefMapEntry{
"Uuml", 0x00dc},
170 EntityRefMapEntry{
"Yacute", 0x00dd},
171 EntityRefMapEntry{
"THORN", 0x00de},
172 EntityRefMapEntry{
"szlig", 0x00df},
173 EntityRefMapEntry{
"agrave", 0x00e0},
174 EntityRefMapEntry{
"aacute", 0x00e1},
175 EntityRefMapEntry{
"acirc", 0x00e2},
176 EntityRefMapEntry{
"atilde", 0x00e3},
177 EntityRefMapEntry{
"auml", 0x00e4},
178 EntityRefMapEntry{
"aring", 0x00e5},
179 EntityRefMapEntry{
"aelig", 0x00e6},
180 EntityRefMapEntry{
"ccedil", 0x00e7},
181 EntityRefMapEntry{
"egrave", 0x00e8},
182 EntityRefMapEntry{
"eacute", 0x00e9},
183 EntityRefMapEntry{
"ecirc", 0x00ea},
184 EntityRefMapEntry{
"euml", 0x00eb},
185 EntityRefMapEntry{
"igrave", 0x00ec},
186 EntityRefMapEntry{
"iacute", 0x00ed},
187 EntityRefMapEntry{
"icirc", 0x00ee},
188 EntityRefMapEntry{
"iuml", 0x00ef},
189 EntityRefMapEntry{
"eth", 0x00f0},
190 EntityRefMapEntry{
"ntilde", 0x00f1},
191 EntityRefMapEntry{
"ograve", 0x00f2},
192 EntityRefMapEntry{
"oacute", 0x00f3},
193 EntityRefMapEntry{
"ocirc", 0x00f4},
194 EntityRefMapEntry{
"otilde", 0x00f5},
195 EntityRefMapEntry{
"ouml", 0x00f6},
196 EntityRefMapEntry{
"divide", 0x00f7},
197 EntityRefMapEntry{
"oslash", 0x00f8},
198 EntityRefMapEntry{
"ugrave", 0x00f9},
199 EntityRefMapEntry{
"uacute", 0x00fa},
200 EntityRefMapEntry{
"ucirc", 0x00fb},
201 EntityRefMapEntry{
"uuml", 0x00fc},
202 EntityRefMapEntry{
"yacute", 0x00fd},
203 EntityRefMapEntry{
"thorn", 0x00fe},
204 EntityRefMapEntry{
"yuml", 0x00ff},
210 EntityRefMapEntry{
"fnof", 0x0192},
213 EntityRefMapEntry{
"Alpha", 0x391},
214 EntityRefMapEntry{
"Beta", 0x392},
215 EntityRefMapEntry{
"Gamma", 0x393},
216 EntityRefMapEntry{
"Delta", 0x394},
217 EntityRefMapEntry{
"Epsilon", 0x395},
218 EntityRefMapEntry{
"Zeta", 0x396},
219 EntityRefMapEntry{
"Eta", 0x397},
220 EntityRefMapEntry{
"Theta", 0x398},
221 EntityRefMapEntry{
"Iota", 0x399},
222 EntityRefMapEntry{
"Kappa", 0x39a},
223 EntityRefMapEntry{
"Lambda", 0x39b},
224 EntityRefMapEntry{
"Mu", 0x39c},
225 EntityRefMapEntry{
"Nu", 0x39d},
226 EntityRefMapEntry{
"Xi", 0x39e},
227 EntityRefMapEntry{
"Omicron", 0x39f},
228 EntityRefMapEntry{
"Pi", 0x3a0},
229 EntityRefMapEntry{
"Rho", 0x3a1},
230 EntityRefMapEntry{
"Sigma", 0x3a3},
231 EntityRefMapEntry{
"Tau", 0x3a4},
232 EntityRefMapEntry{
"Upsilon", 0x3a5},
233 EntityRefMapEntry{
"Phi", 0x3a6},
234 EntityRefMapEntry{
"Chi", 0x3a7},
235 EntityRefMapEntry{
"Psi", 0x3a8},
236 EntityRefMapEntry{
"Omega", 0x3a9},
237 EntityRefMapEntry{
"alpha", 0x03b1},
238 EntityRefMapEntry{
"beta", 0x03b2},
239 EntityRefMapEntry{
"gamma", 0x03b3},
240 EntityRefMapEntry{
"delta", 0x03b4},
241 EntityRefMapEntry{
"epsilon", 0x03b5},
242 EntityRefMapEntry{
"zeta", 0x03b6},
243 EntityRefMapEntry{
"eta", 0x03b7},
244 EntityRefMapEntry{
"theta", 0x03b8},
245 EntityRefMapEntry{
"iota", 0x03b9},
246 EntityRefMapEntry{
"kappa", 0x03ba},
247 EntityRefMapEntry{
"lambda", 0x03bb},
248 EntityRefMapEntry{
"mu", 0x03bc},
249 EntityRefMapEntry{
"nu", 0x03bd},
250 EntityRefMapEntry{
"xi", 0x03be},
251 EntityRefMapEntry{
"omicron", 0x03bf},
252 EntityRefMapEntry{
"pi", 0x03c0},
253 EntityRefMapEntry{
"rho", 0x03c1},
254 EntityRefMapEntry{
"sigmaf", 0x03c2},
255 EntityRefMapEntry{
"sigma", 0x03c3},
256 EntityRefMapEntry{
"tau", 0x03c4},
257 EntityRefMapEntry{
"upsilon", 0x03c5},
258 EntityRefMapEntry{
"phi", 0x03c6},
259 EntityRefMapEntry{
"chi", 0x03c7},
260 EntityRefMapEntry{
"psi", 0x03c8},
261 EntityRefMapEntry{
"omega", 0x03c9},
262 EntityRefMapEntry{
"thetasym", 0x03d1},
263 EntityRefMapEntry{
"upsih", 0x03d2},
264 EntityRefMapEntry{
"piv", 0x03d6},
267 EntityRefMapEntry{
"bull", 0x2022},
268 EntityRefMapEntry{
"hellip", 0x2026},
269 EntityRefMapEntry{
"prime", 0x2032},
270 EntityRefMapEntry{
"Prime", 0x2033},
271 EntityRefMapEntry{
"oline", 0x203e},
272 EntityRefMapEntry{
"frasl", 0x2044},
275 EntityRefMapEntry{
"weierp", 0x2118},
276 EntityRefMapEntry{
"image", 0x2111},
277 EntityRefMapEntry{
"real", 0x211c},
278 EntityRefMapEntry{
"trade", 0x2122},
279 EntityRefMapEntry{
"alefsym", 0x2135},
282 EntityRefMapEntry{
"larr", 0x2190},
283 EntityRefMapEntry{
"uarr", 0x2191},
284 EntityRefMapEntry{
"rarr", 0x2192},
285 EntityRefMapEntry{
"darr", 0x2193},
286 EntityRefMapEntry{
"harr", 0x2194},
287 EntityRefMapEntry{
"crarr", 0x21b5},
288 EntityRefMapEntry{
"lArr", 0x21d0},
289 EntityRefMapEntry{
"uArr", 0x21d1},
290 EntityRefMapEntry{
"rArr", 0x21d2},
291 EntityRefMapEntry{
"dArr", 0x21d3},
292 EntityRefMapEntry{
"hArr", 0x21d4},
296 EntityRefMapEntry{
"forall", 8704},
297 EntityRefMapEntry{
"part", 8706},
298 EntityRefMapEntry{
"exist", 8707},
299 EntityRefMapEntry{
"empty", 8709},
300 EntityRefMapEntry{
"nabla", 8711},
301 EntityRefMapEntry{
"isin", 8712},
302 EntityRefMapEntry{
"notin", 8713},
303 EntityRefMapEntry{
"ni", 8715},
304 EntityRefMapEntry{
"prod", 8719},
305 EntityRefMapEntry{
"sum", 8721},
306 EntityRefMapEntry{
"minus", 8722},
307 EntityRefMapEntry{
"lowast", 8727},
308 EntityRefMapEntry{
"radic", 8730},
309 EntityRefMapEntry{
"prop", 8733},
310 EntityRefMapEntry{
"infin", 8734},
311 EntityRefMapEntry{
"ang", 8736},
312 EntityRefMapEntry{
"and", 8869},
313 EntityRefMapEntry{
"or", 8870},
314 EntityRefMapEntry{
"cap", 8745},
315 EntityRefMapEntry{
"cup", 8746},
316 EntityRefMapEntry{
"int", 8747},
317 EntityRefMapEntry{
"there4", 8756},
318 EntityRefMapEntry{
"sim", 8764},
319 EntityRefMapEntry{
"cong", 8773},
320 EntityRefMapEntry{
"asymp", 8776},
321 EntityRefMapEntry{
"ne", 8800},
322 EntityRefMapEntry{
"equiv", 8801},
323 EntityRefMapEntry{
"le", 8804},
324 EntityRefMapEntry{
"ge", 8805},
325 EntityRefMapEntry{
"sub", 8834},
326 EntityRefMapEntry{
"sup", 8835},
327 EntityRefMapEntry{
"nsub", 8836},
328 EntityRefMapEntry{
"sube", 8838},
329 EntityRefMapEntry{
"supe", 8839},
330 EntityRefMapEntry{
"oplus", 8853},
331 EntityRefMapEntry{
"otimes", 8855},
332 EntityRefMapEntry{
"perp", 8869},
333 EntityRefMapEntry{
"sdot", 8901},
337 EntityRefMapEntry{
"lceil", 8968},
338 EntityRefMapEntry{
"rceil", 8969},
339 EntityRefMapEntry{
"lfloor", 8970},
340 EntityRefMapEntry{
"rfloor", 8971},
341 EntityRefMapEntry{
"lang", 9001},
342 EntityRefMapEntry{
"rang", 9002},
346 EntityRefMapEntry{
"loz", 9674},
350 EntityRefMapEntry{
"spades", 9824},
351 EntityRefMapEntry{
"clubs", 9827},
352 EntityRefMapEntry{
"hearts", 9829},
353 EntityRefMapEntry{
"diams", 9830},
360 EntityRefMapEntry{
"quot", 0x0022},
361 EntityRefMapEntry{
"amp", 0x0026},
362 EntityRefMapEntry{
"lt", 0x003c},
363 EntityRefMapEntry{
"gt", 0x003e},
366 EntityRefMapEntry{
"OElig", 0x0152},
367 EntityRefMapEntry{
"oelig", 0x0153},
368 EntityRefMapEntry{
"Scaron", 0x0160},
369 EntityRefMapEntry{
"scaron", 0x0161},
370 EntityRefMapEntry{
"Yuml", 0x0178},
373 EntityRefMapEntry{
"circ", 0x2c6},
374 EntityRefMapEntry{
"tilde", 0x2dc},
377 EntityRefMapEntry{
"ensp", 8194},
378 EntityRefMapEntry{
"emsp", 8195},
379 EntityRefMapEntry{
"thinsp", 8201},
380 EntityRefMapEntry{
"zwnj", 8204},
381 EntityRefMapEntry{
"zwj", 8205},
382 EntityRefMapEntry{
"lrm", 8206},
383 EntityRefMapEntry{
"rlm", 8207},
384 EntityRefMapEntry{
"ndash", 0x2013},
385 EntityRefMapEntry{
"mdash", 0x2014},
386 EntityRefMapEntry{
"lsquo", 0x2018},
387 EntityRefMapEntry{
"rsquo", 0x2019},
388 EntityRefMapEntry{
"sbquo", 0x201a},
389 EntityRefMapEntry{
"ldquo", 0x201c},
390 EntityRefMapEntry{
"rdquo", 0x201d},
391 EntityRefMapEntry{
"bdquo", 0x201e},
392 EntityRefMapEntry{
"dagger", 0x2020},
393 EntityRefMapEntry{
"Dagger", 0x2021},
394 EntityRefMapEntry{
"permil", 0x2030},
395 EntityRefMapEntry{
"lsaquo", 0x2039},
396 EntityRefMapEntry{
"rsaquo", 0x203a},
398const size_t HTMLInfo::kDefaultEntityRefMapTable_Count = Memory::NEltsOf (HTMLInfo::sDefaultEntityRefMapTable);
400FontSpecification::FontSize HTMLInfo::HTMLFontSizeToRealFontSize (
int size)
402 size = min (size, 7);
403 size = max (size, 1);
426int HTMLInfo::RealFontSizeToHTMLFontSize (FontSpecification::FontSize size)
431 else if (size <= 9) {
434 else if (size <= 10) {
437 else if (size <= 12) {
440 else if (size <= 14) {
443 else if (size <= 18) {
456StyledTextIOReader_HTML::StyledTextIOReader_HTML (SrcStream* srcStream, SinkStream* sinkStream, HTMLInfo* saveHTMLInfoInto)
457 : StyledTextIOReader{srcStream, sinkStream}
458 , fSaveHTMLInfoInto{saveHTMLInfoInto}
460 if (fSaveHTMLInfoInto !=
nullptr) {
461 *fSaveHTMLInfoInto = HTMLInfo ();
463 fFontStack.push_back (GetStaticDefaultFont ());
466void StyledTextIOReader_HTML::Read ()
469 size_t lastWroteBefore = GetSrcStream ().current_offset ();
470 switch (ScanTilNextHTMLThingy ()) {
472 EmitText (MapInputTextToTString (GrabString (lastWroteBefore)));
473 size_t curPos = GetSrcStream ().current_offset ();
474 ScanTilAfterHTMLThingy (eEntityRef);
475 HandleHTMLThingy (eEntityRef, GrabString (curPos));
479 EmitText (MapInputTextToTString (GrabString (lastWroteBefore)));
480 size_t curPos = GetSrcStream ().current_offset ();
481 ScanTilAfterHTMLThingy (eTag);
482 HandleHTMLThingy (eTag, GrabString (curPos));
486 ScanTilAfterHTMLThingy (eBangComment);
490 EmitText (MapInputTextToTString (GrabString (lastWroteBefore)));
491 GetSinkStream ().EndOfBuffer ();
502bool StyledTextIOReader_HTML::QuickLookAppearsToBeRightFormat ()
504 SrcStreamSeekSaver savePos{GetSrcStream ()};
507 if (GetSrcStream ().current_offset () >= 1024) {
510 switch (ScanTilNextHTMLThingy ()) {
512 ScanTilAfterHTMLThingy (eEntityRef);
519 if (GetSrcStream ().current_offset () < 1024) {
520 size_t curPos = GetSrcStream ().current_offset ();
521 ScanTilAfterHTMLThingy (eTag);
522 string tmp = GrabString (curPos);
524 bool isStartTag =
true;
525 ExtractHTMLTagIntoTagNameBuf (tmp.c_str (), tmp.length (), tagBuf, sizeof (tagBuf), &isStartTag);
526 if (isStartTag and (::strcmp (tagBuf,
"html") == 0 or ::strcmp (tagBuf,
"!doctype") == 0 or
527 ::strcmp (tagBuf,
"title") == 0 or ::strcmp (tagBuf,
"head") == 0 or ::strcmp (tagBuf,
"body") == 0)) {
558const vector<StyledTextIOReader_HTML::EntityRefMapEntry>& StyledTextIOReader_HTML::GetEntityRefMapTable ()
const
560 using ELTV = vector<StyledTextIOReader_HTML::EntityRefMapEntry>;
561 static bool sFirstTime =
true;
565 sResult = ELTV{HTMLInfo::sDefaultEntityRefMapTable, HTMLInfo::sDefaultEntityRefMapTable + HTMLInfo::kDefaultEntityRefMapTable_Count};
570StyledTextIOReader_HTML::ThingyType StyledTextIOReader_HTML::ScanTilNextHTMLThingy ()
574 for (
char c = PeekNextChar ();; c = PeekNextChar ()) {
581 if (LookingAt (
"<!--")) {
596 catch (ReadEOFException& ) {
603void StyledTextIOReader_HTML::ScanTilAfterHTMLThingy (ThingyType thingy)
605 Require (thingy != eEOF);
614 while (isalnum (c = PeekNextChar ()) or c ==
'#') {
621 catch (ReadEOFException& ) {
629 while ((c = GetNextChar ()) !=
'>')
635 if (LookingAt (
"-->")) {
653bool StyledTextIOReader_HTML::LookingAt (
const char* text)
const
656 const char* p = text;
657 for (; *p !=
'\0';) {
658 if (PeekNextChar () == *p) {
676Led_tString StyledTextIOReader_HTML::MapInputTextToTString (
const string& text)
681void StyledTextIOReader_HTML::EmitText (
const Led_tChar* text,
size_t nBytes,
bool skipNLCheck)
683 if (fComingTextIsTitle) {
684 if (fSaveHTMLInfoInto !=
nullptr) {
685 fSaveHTMLInfoInto->fTitle += Led_tString{text, nBytes};
689 if (fHiddenTextMode) {
690 fHiddenTextAccumulation += Led_tString{text, nBytes};
694 if (fULNestingCount > 0 and not fLIOpen) {
700 nBytes = Characters::NormalizeTextToNL<Led_tChar> (text, nBytes, outBuf.data (), nBytes);
702 if (not skipNLCheck and fNormalizeInputWhitespace) {
703 Assert (fNormalizeInputWhitespace);
704 Assert (not skipNLCheck);
707 Led_tChar* out = outBuf.data ();
708 for (
size_t i = 0; i < nBytes; ++i) {
709 Led_tChar c = outBuf[i];
710 bool thisCharSpace = IsASCIISpace_ (c);
712 if (not fLastCharSpace) {
721 fLastCharSpace = thisCharSpace;
723 size_t newNBytes = out -
static_cast<Led_tChar*
> (outBuf);
724 Assert (newNBytes <= nBytes);
730 GetSinkStream ().AppendText (outBuf.data (), nBytes, &fFontStack.back ());
734void StyledTextIOReader_HTML::HandleHTMLThingy (StyledTextIOReader_HTML::ThingyType thingy,
const char* text,
size_t nBytes)
738 HandleHTMLThingy_EntityReference (text, nBytes);
741 HandleHTMLThingy_Tag (text, nBytes);
750void StyledTextIOReader_HTML::HandleHTMLThingy_EntityReference (
const char* text,
size_t nBytes)
753 Require (nBytes >= 1);
756 string refName =
string{&text[1], nBytes - 1};
757 if (refName.length () > 0) {
758 if (refName[refName.length () - 1] ==
';') {
759 refName.erase (refName.length () - 1);
762 if (refName.length () > 0) {
763 if (refName[0] ==
'#') {
764 wchar_t result =
static_cast<wchar_t> (::atoi (refName.c_str () + 1));
765 EmitText (&result, 1);
769 const vector<StyledTextIOReader_HTML::EntityRefMapEntry>& entityRefs = GetEntityRefMapTable ();
770 for (
auto i = entityRefs.begin (); i != entityRefs.end (); ++i) {
771 if (refName == (*i).fEntityRefName) {
772 EmitText (&(*i).fCharValue, 1);
780 EmitText (MapInputTextToTString (
string{text, nBytes}));
783void StyledTextIOReader_HTML::HandleHTMLThingy_Tag (
const char* text,
size_t nBytes)
788 bool isStartTag =
true;
790 ExtractHTMLTagIntoTagNameBuf (text, nBytes, tagBuf,
sizeof (tagBuf), &isStartTag);
794 else if (::strcmp (tagBuf,
"!doctype") == 0) {
795 HandleHTMLThingyTag_BANG_doctype (isStartTag, text, nBytes);
797 else if (::strcmp (tagBuf,
"a") == 0) {
798 HandleHTMLThingyTag_a (isStartTag, text, nBytes);
800 else if (::strcmp (tagBuf,
"b") == 0) {
801 HandleHTMLThingyTag_b (isStartTag, text, nBytes);
803 else if (::strcmp (tagBuf,
"basefont") == 0) {
804 HandleHTMLThingyTag_basefont (isStartTag, text, nBytes);
806 else if (::strcmp (tagBuf,
"blockquote") == 0) {
807 HandleHTMLThingyTag_blockquote (isStartTag, text, nBytes);
809 else if (::strcmp (tagBuf,
"br") == 0) {
810 HandleHTMLThingyTag_br (isStartTag, text, nBytes);
812 else if (::strcmp (tagBuf,
"body") == 0) {
813 HandleHTMLThingyTag_body (isStartTag, text, nBytes);
815 else if (::strcmp (tagBuf,
"code") == 0) {
816 HandleHTMLThingyTag_code (isStartTag, text, nBytes);
818 else if (::strcmp (tagBuf,
"comment") == 0) {
819 HandleHTMLThingyTag_comment (isStartTag, text, nBytes);
821 else if (::strcmp (tagBuf,
"dir") == 0) {
822 HandleHTMLThingyTag_dir (isStartTag, text, nBytes);
824 else if (::strcmp (tagBuf,
"div") == 0) {
825 HandleHTMLThingyTag_div (isStartTag, text, nBytes);
827 else if (::strcmp (tagBuf,
"em") == 0) {
828 HandleHTMLThingyTag_em (isStartTag, text, nBytes);
830 else if (::strcmp (tagBuf,
"font") == 0) {
831 HandleHTMLThingyTag_font (isStartTag, text, nBytes);
833 else if (::strcmp (tagBuf,
"head") == 0) {
834 HandleHTMLThingyTag_head (isStartTag, text, nBytes);
836 else if (::strcmp (tagBuf,
"html") == 0) {
837 HandleHTMLThingyTag_html (isStartTag, text, nBytes);
839 else if (::strcmp (tagBuf,
"hr") == 0) {
840 HandleHTMLThingyTag_hr (isStartTag, text, nBytes);
842 else if (::strcmp (tagBuf,
"h1") == 0) {
843 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
845 else if (::strcmp (tagBuf,
"h2") == 0) {
846 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
848 else if (::strcmp (tagBuf,
"h3") == 0) {
849 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
851 else if (::strcmp (tagBuf,
"h4") == 0) {
852 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
854 else if (::strcmp (tagBuf,
"h5") == 0) {
855 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
857 else if (::strcmp (tagBuf,
"h6") == 0) {
858 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
860 else if (::strcmp (tagBuf,
"h7") == 0) {
861 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
863 else if (::strcmp (tagBuf,
"h8") == 0) {
864 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
866 else if (::strcmp (tagBuf,
"h9") == 0) {
867 HandleHTMLThingyTag_hN (isStartTag, text, nBytes);
869 else if (::strcmp (tagBuf,
"i") == 0) {
870 HandleHTMLThingyTag_i (isStartTag, text, nBytes);
872 else if (::strcmp (tagBuf,
"img") == 0) {
873 HandleHTMLThingyTag_img (isStartTag, text, nBytes);
875 else if (::strcmp (tagBuf,
"li") == 0) {
876 HandleHTMLThingyTag_li (isStartTag, text, nBytes);
878 else if (::strcmp (tagBuf,
"listing") == 0) {
879 HandleHTMLThingyTag_listing (isStartTag, text, nBytes);
881 else if (::strcmp (tagBuf,
"ol") == 0) {
882 HandleHTMLThingyTag_ol (isStartTag, text, nBytes);
884 else if (::strcmp (tagBuf,
"p") == 0) {
885 HandleHTMLThingyTag_p (isStartTag, text, nBytes);
887 else if (::strcmp (tagBuf,
"plaintext") == 0) {
888 HandleHTMLThingyTag_plaintext (isStartTag, text, nBytes);
890 else if (::strcmp (tagBuf,
"pre") == 0) {
891 HandleHTMLThingyTag_pre (isStartTag, text, nBytes);
893 else if (::strcmp (tagBuf,
"s") == 0) {
894 HandleHTMLThingyTag_s (isStartTag, text, nBytes);
896 else if (::strcmp (tagBuf,
"samp") == 0) {
897 HandleHTMLThingyTag_samp (isStartTag, text, nBytes);
899 else if (::strcmp (tagBuf,
"small") == 0) {
900 HandleHTMLThingyTag_small (isStartTag, text, nBytes);
902 else if (::strcmp (tagBuf,
"span") == 0) {
903 HandleHTMLThingyTag_span (isStartTag, text, nBytes);
905 else if (::strcmp (tagBuf,
"strike") == 0) {
906 HandleHTMLThingyTag_strike (isStartTag, text, nBytes);
908 else if (::strcmp (tagBuf,
"strong") == 0) {
909 HandleHTMLThingyTag_strong (isStartTag, text, nBytes);
911 else if (::strcmp (tagBuf,
"sub") == 0) {
912 HandleHTMLThingyTag_sub (isStartTag, text, nBytes);
914 else if (::strcmp (tagBuf,
"sup") == 0) {
915 HandleHTMLThingyTag_sup (isStartTag, text, nBytes);
917 else if (::strcmp (tagBuf,
"table") == 0) {
918 HandleHTMLThingyTag_table (isStartTag, text, nBytes);
920 else if (::strcmp (tagBuf,
"td") == 0) {
921 HandleHTMLThingyTag_td (isStartTag, text, nBytes);
923 else if (::strcmp (tagBuf,
"th") == 0) {
924 HandleHTMLThingyTag_th (isStartTag, text, nBytes);
926 else if (::strcmp (tagBuf,
"title") == 0) {
927 HandleHTMLThingyTag_title (isStartTag, text, nBytes);
929 else if (::strcmp (tagBuf,
"tr") == 0) {
930 HandleHTMLThingyTag_tr (isStartTag, text, nBytes);
932 else if (::strcmp (tagBuf,
"tt") == 0) {
933 HandleHTMLThingyTag_tt (isStartTag, text, nBytes);
935 else if (::strcmp (tagBuf,
"u") == 0) {
936 HandleHTMLThingyTag_u (isStartTag, text, nBytes);
938 else if (::strcmp (tagBuf,
"ul") == 0) {
939 HandleHTMLThingyTag_ul (isStartTag, text, nBytes);
941 else if (::strcmp (tagBuf,
"var") == 0) {
942 HandleHTMLThingyTag_var (isStartTag, text, nBytes);
944 else if (::strcmp (tagBuf,
"xmp") == 0) {
945 HandleHTMLThingyTag_xmp (isStartTag, text, nBytes);
948 HandleHTMLThingyTagUnknown (isStartTag, text, nBytes);
952void StyledTextIOReader_HTML::ExtractHTMLTagIntoTagNameBuf (
const char* text,
size_t nBytes,
char* tagBuf,
size_t tagBufSize,
bool* isStartTag)
959 const char* in = &text[0];
960 const char* in_end = in + nBytes;
961 char* out = &tagBuf[0];
967 for (; in < in_end; ++in) {
969 if (isalnum (c) or (c ==
'!') or (c ==
'_') or (c ==
'-')) {
971 c =
static_cast<char> (tolower (c));
980 if (
size_t (out - tagBuf) >= tagBufSize - 2) {
988IncrementalFontSpecification StyledTextIOReader_HTML::ExtractFontSpecFromCSSStyleAttribute (
const char* text,
size_t nBytes)
990 IncrementalFontSpecification f;
991 string fullCSSString (text, text + nBytes);
993 if (ParseCSSTagArgOut (fullCSSString,
"font-family", &itemValue)) {
996 size_t comma = itemValue.find (
'.');
997 if (comma != string::npos) {
998 itemValue = itemValue.substr (0, comma);
1000 f.SetFontName (String::FromNarrowSDKString (itemValue).AsSDKString ());
1002 if (ParseCSSTagArgOut (fullCSSString,
"font-size", &itemValue)) {
1003 if (itemValue.length () >= 3 and Led_CasedStringsEqual (itemValue.substr (itemValue.length () - 2, 2),
"pt"sv)) {
1005 if (ParseStringToInt_ (itemValue.substr (0, itemValue.length () - 2), &sizeVal) and sizeVal >= 2 and sizeVal <= 128) {
1006 f.SetPointSize (
static_cast<uint8_t
> (sizeVal));
1010 if (ParseCSSTagArgOut (fullCSSString,
"font-style", &itemValue)) {
1011 if (Led_CasedStringsEqual (itemValue,
"italic"sv)) {
1012 f.SetStyle_Italic (
true);
1014 else if (Led_CasedStringsEqual (itemValue,
"normal"sv)) {
1015 f.SetStyle_Italic (
false);
1018 if (ParseCSSTagArgOut (fullCSSString,
"font-weight", &itemValue)) {
1020 if (Led_CasedStringsEqual (itemValue,
"bold"sv) or Led_CasedStringsEqual (itemValue,
"bolder"sv) or
1021 (itemValue.length () > 0 and isdigit (itemValue[0]) and ParseStringToInt_ (itemValue, &bv) and bv >= 400)) {
1022 f.SetStyle_Bold (
true);
1025 f.SetStyle_Bold (
false);
1028 if (ParseCSSTagArgOut (fullCSSString,
"color", &itemValue)) {
1029 Color clr = Color::kBlack;
1030 if (ParseColorString_ (itemValue, &clr)) {
1031 f.SetTextColor (clr);
1037void StyledTextIOReader_HTML::ApplyCSSStyleAttributeToCurrentFontStack (
const char* text,
size_t nBytes)
1039 fFontStack.back ().MergeIn (ExtractFontSpecFromCSSStyleAttribute (text, nBytes));
1042void StyledTextIOReader_HTML::GrabAndApplyCSSStyleFromTagText (
const char* text,
size_t nBytes)
1045 string tagText (text, nBytes);
1047 if (ParseHTMLTagArgOut (tagText,
"style", &tagValue)) {
1048 ApplyCSSStyleAttributeToCurrentFontStack (tagValue.c_str (), tagValue.length ());
1053void StyledTextIOReader_HTML::HandleHTMLThingyTag_BANG_doctype (
bool ,
const char* text,
size_t nBytes)
1055 if (fSaveHTMLInfoInto !=
nullptr) {
1056 fSaveHTMLInfoInto->fDocTypeTag =
string{text, nBytes};
1060void StyledTextIOReader_HTML::HandleHTMLThingyTag_a (
bool start,
const char* text,
size_t nBytes)
1062#if qThrowAwayMostUnknownHTMLTags
1064 string tagText (text, nBytes);
1066 fCurAHRefStart = GetSrcStream ().current_offset ();
1067 fCurAHRefText = tagText;
1068 fHiddenTextMode =
true;
1069 fHiddenTextAccumulation = Led_tString{};
1072 if (fCurAHRefStart !=
size_t (-1)) {
1074 (void)ParseHTMLTagArgOut (fCurAHRefText,
"href", &tagValue);
1075#if qStroika_Frameworks_Led_SupportGDI
1076 EmbeddedObjectCreatorRegistry::Assoc assoc;
1077 if (EmbeddedObjectCreatorRegistry::Get ().Lookup (StandardURLStyleMarker::kEmbeddingTag, &assoc)) {
1080 Led_URLD{tagValue.c_str (),
1082 GetSinkStream ().AppendEmbedding (
1083 (assoc.fReadFromMemory) (StandardURLStyleMarker::kEmbeddingTag, urld.PeekAtURLD (), urld.GetURLDLength ()));
1087 fCurAHRefStart = size_t (-1);
1088 fCurAHRefText =
string{};
1089 fHiddenTextMode =
false;
1090 fHiddenTextAccumulation = Led_tString{};
1091 fLastCharSpace =
false;
1094 HandleHTMLThingyTagUnknown (start, text, nBytes);
1098void StyledTextIOReader_HTML::HandleHTMLThingyTag_b (
bool start,
const char* ,
size_t )
1100 BasicFontStackOperation (start);
1103 fsp.SetStyle_Bold (
true);
1104 fFontStack.back () = fsp;
1108void StyledTextIOReader_HTML::HandleHTMLThingyTag_basefont (
bool start,
const char* text,
size_t nBytes)
1112 string tagText (text, nBytes);
1114 if (ParseHTMLTagArgOut (tagText,
"size", &tagValue)) {
1115 if (tagValue.length () > 0) {
1116 int tagNum = Led_DigitCharToNumber (tagValue[0]);
1117 if (tagNum >= 1 and tagNum <= 7) {
1118 fHTMLBaseFontSize = tagNum;
1125void StyledTextIOReader_HTML::HandleHTMLThingyTag_body (
bool start,
const char* text,
size_t nBytes)
1127 if (start and fSaveHTMLInfoInto !=
nullptr) {
1128 fSaveHTMLInfoInto->fStartBodyTag =
string{text, nBytes};
1130 fReadingBody =
true;
1132 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1136void StyledTextIOReader_HTML::HandleHTMLThingyTag_big (
bool start,
const char* ,
size_t )
1138 BasicFontStackOperation (start);
1140 SetHTMLFontSize (fHTMLFontSize + 1);
1144void StyledTextIOReader_HTML::HandleHTMLThingyTag_blockquote (
bool start,
const char* text,
size_t nBytes)
1149 EmitForcedLineBreak ();
1152 StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (start, text, nBytes);
1156 fNormalizeInputWhitespace = not start;
1159void StyledTextIOReader_HTML::HandleHTMLThingyTag_br (
bool start,
const char* ,
size_t )
1163 if (fComingTextIsTitle or fHiddenTextMode) {
1167 GetSinkStream ().AppendSoftLineBreak ();
1172void StyledTextIOReader_HTML::HandleHTMLThingyTag_code (
bool start,
const char* text,
size_t nBytes)
1176 StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (start, text, nBytes);
1179void StyledTextIOReader_HTML::HandleHTMLThingyTag_comment (
bool start,
const char* text,
size_t nBytes)
1181 HandleHTMLThingyTagUnknown (start, text, nBytes);
1185 fNormalizeInputWhitespace = not start;
1188void StyledTextIOReader_HTML::HandleHTMLThingyTag_dir (
bool start,
const char* text,
size_t nBytes)
1192 HandleHTMLThingyTag_ul (start, text, nBytes);
1195void StyledTextIOReader_HTML::HandleHTMLThingyTag_div (
bool start,
const char* text,
size_t nBytes)
1198 BasicFontStackOperation (start);
1200 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1201 string tagText (text, nBytes);
1205 if (tagText.find (
"left") != -1) {
1206 GetSinkStream ().SetJustification (eLeftJustify);
1208 else if (tagText.find (
"center") != -1) {
1209 GetSinkStream ().SetJustification (eCenterJustify);
1211 else if (tagText.find (
"right") != -1) {
1212 GetSinkStream ().SetJustification (eRightJustify);
1216 EmitForcedLineBreak ();
1220 GetSinkStream ().SetJustification (eLeftJustify);
1224void StyledTextIOReader_HTML::HandleHTMLThingyTag_em (
bool start,
const char* text,
size_t nBytes)
1227 StyledTextIOReader_HTML::HandleHTMLThingyTag_i (start, text, nBytes);
1230void StyledTextIOReader_HTML::HandleHTMLThingyTag_font (
bool start,
const char* text,
size_t nBytes)
1232 BasicFontStackOperation (start);
1235 string tagText (text, nBytes);
1237 if (ParseHTMLTagArgOut (tagText,
"face", &tagValue)) {
1239 if (tagValue.find (
',') != string::npos) {
1240 tagValue = tagValue.substr (0, tagValue.find (
','));
1242 fsp.SetFontName (String::FromNarrowSDKString (tagValue).AsSDKString ());
1243 fFontStack.back () = fsp;
1245 if (ParseHTMLTagArgOut (tagText,
"color", &tagValue)) {
1246 Color newColor = Color::kBlack;
1247 if (ParseColorString_ (tagValue, &newColor)) {
1249 fsp.SetTextColor (newColor);
1250 fFontStack.back () = fsp;
1253 if (ParseHTMLTagArgOut (tagText,
"size", &tagValue)) {
1254 if (tagValue.length () > 0) {
1255 switch (tagValue[0]) {
1257 if (tagValue.length () >= 2) {
1258 int tagNum = tagValue[1] -
'0';
1259 if (tagNum >= -7 and tagNum <= 7) {
1260 SetHTMLFontSize (fHTMLBaseFontSize - tagNum);
1265 if (tagValue.length () >= 2) {
1266 int tagNum = tagValue[1] -
'0';
1267 if (tagNum >= -7 and tagNum <= 7) {
1268 SetHTMLFontSize (fHTMLBaseFontSize + tagNum);
1273 if (isdigit (tagValue[0])) {
1274 int tagNum = Led_DigitCharToNumber (tagValue[0]);
1275 if (tagNum >= 1 and tagNum <= 7) {
1276 SetHTMLFontSize (tagNum);
1286void StyledTextIOReader_HTML::HandleHTMLThingyTag_head (
bool start,
const char* text,
size_t nBytes)
1288 if (start and fSaveHTMLInfoInto !=
nullptr) {
1289 fSaveHTMLInfoInto->fHeadTag =
string{text, nBytes};
1293void StyledTextIOReader_HTML::HandleHTMLThingyTag_html (
bool start,
const char* text,
size_t nBytes)
1295 if (start and fSaveHTMLInfoInto !=
nullptr) {
1296 fSaveHTMLInfoInto->fHTMLTag =
string{text, nBytes};
1300void StyledTextIOReader_HTML::HandleHTMLThingyTag_hr ([[maybe_unused]]
bool start, [[maybe_unused]]
const char* text, [[maybe_unused]]
size_t nBytes)
1305#if qThrowAwayMostUnknownHTMLTags
1306 const Led_tChar kSeparator[] = LED_TCHAR_OF (
"----------------------------------------------------------------");
1307 EmitText (kSeparator, Led_tStrlen (kSeparator));
1309 HandleHTMLThingyTagUnknown (start, text, nBytes);
1311 EmitForcedLineBreak ();
1314void StyledTextIOReader_HTML::HandleHTMLThingyTag_hN (
bool start,
const char* text,
size_t nBytes)
1318 EmitForcedLineBreak ();
1320#if qThrowAwayMostUnknownHTMLTags
1321 BasicFontStackOperation (start);
1324 fsp.SetStyle_Bold (
true);
1325 fFontStack.back () = fsp;
1326 if (nBytes > 3 and isdigit (text[2])) {
1327 int headingLevel = Led_DigitCharToNumber (text[2]);
1328 switch (headingLevel) {
1330 SetHTMLFontSize (7);
1333 SetHTMLFontSize (6);
1336 SetHTMLFontSize (5);
1339 SetHTMLFontSize (4);
1342 SetHTMLFontSize (3);
1352 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1356 HandleHTMLThingyTagUnknown (start, text, nBytes);
1358 EmitForcedLineBreak ();
1362void StyledTextIOReader_HTML::HandleHTMLThingyTag_i (
bool start,
const char* ,
size_t )
1364 BasicFontStackOperation (start);
1367 fsp.SetStyle_Italic (
true);
1368 fFontStack.back () = fsp;
1372void StyledTextIOReader_HTML::HandleHTMLThingyTag_img (
bool start,
const char* text,
size_t nBytes)
1374 HandleHTMLThingyTagUnknown (start, text, nBytes);
1377void StyledTextIOReader_HTML::HandleHTMLThingyTag_li (
bool start,
const char* text,
size_t nBytes)
1380 BasicFontStackOperation (start);
1382 fLastCharSpace =
true;
1383 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1386 EmitForcedLineBreak ();
1391void StyledTextIOReader_HTML::HandleHTMLThingyTag_listing (
bool start,
const char* text,
size_t nBytes)
1395 StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (start, text, nBytes);
1398void StyledTextIOReader_HTML::HandleHTMLThingyTag_ol (
bool start,
const char* text,
size_t nBytes)
1403 HandleHTMLThingyTagUnknown (start, text, nBytes);
1404 EmitForcedLineBreak ();
1407void StyledTextIOReader_HTML::HandleHTMLThingyTag_p (
bool start,
const char* text,
size_t nBytes)
1412 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1415 string tagTxt (text, nBytes);
1417 if (tagTxt.find (
"left") != -1) {
1418 GetSinkStream ().SetJustification (eLeftJustify);
1420 else if (tagTxt.find (
"center") != -1) {
1421 GetSinkStream ().SetJustification (eCenterJustify);
1423 else if (tagTxt.find (
"right") != -1) {
1424 GetSinkStream ().SetJustification (eRightJustify);
1428 GetSinkStream ().SetJustification (eLeftJustify);
1437void StyledTextIOReader_HTML::HandleHTMLThingyTag_plaintext (
bool start,
const char* text,
size_t nBytes)
1441 StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (start, text, nBytes);
1445 fNormalizeInputWhitespace = not start;
1450void StyledTextIOReader_HTML::HandleHTMLThingyTag_pre (
bool start,
const char* text,
size_t nBytes)
1454 StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (start, text, nBytes);
1458 fNormalizeInputWhitespace = not start;
1461void StyledTextIOReader_HTML::HandleHTMLThingyTag_s (
bool start,
const char* text,
size_t nBytes)
1463 HandleHTMLThingyTag_strike (start, text, nBytes);
1466void StyledTextIOReader_HTML::HandleHTMLThingyTag_samp (
bool start,
const char* ,
size_t )
1468 BasicFontStackOperation (start);
1470 SetHTMLFontSize (2);
1474void StyledTextIOReader_HTML::HandleHTMLThingyTag_small (
bool start,
const char* ,
size_t )
1476 BasicFontStackOperation (start);
1478 SetHTMLFontSize (fHTMLFontSize - 1);
1482void StyledTextIOReader_HTML::HandleHTMLThingyTag_span (
bool start,
const char* text,
size_t nBytes)
1484 BasicFontStackOperation (start);
1486 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1490void StyledTextIOReader_HTML::HandleHTMLThingyTag_strike ([[maybe_unused]]
bool start, [[maybe_unused]]
const char* text, [[maybe_unused]]
size_t nBytes)
1492#if qStroika_Foundation_Common_Platform_Windows
1493 BasicFontStackOperation (start);
1496 fsp.SetStyle_Strikeout (
true);
1497 fFontStack.back () = fsp;
1502void StyledTextIOReader_HTML::HandleHTMLThingyTag_strong (
bool start,
const char* text,
size_t nBytes)
1505 StyledTextIOReader_HTML::HandleHTMLThingyTag_b (start, text, nBytes);
1508void StyledTextIOReader_HTML::HandleHTMLThingyTag_sub (
bool start,
const char* ,
size_t )
1510 BasicFontStackOperation (start);
1513 fsp.SetStyle_SubOrSuperScript (FontSpecification::eSubscript);
1514 fFontStack.back () = fsp;
1518void StyledTextIOReader_HTML::HandleHTMLThingyTag_sup (
bool start,
const char* ,
size_t )
1520 BasicFontStackOperation (start);
1523 fsp.SetStyle_SubOrSuperScript (FontSpecification::eSuperscript);
1524 fFontStack.back () = fsp;
1528void StyledTextIOReader_HTML::HandleHTMLThingyTag_table (
bool start,
const char* ,
size_t )
1530 GetSinkStream ().Flush ();
1531 fLastCharSpace =
true;
1543 GetSinkStream ().StartTable ();
1545 fTableRowOpen =
false;
1546 fTableCellOpen =
false;
1549 if (fTableOpenCount > 0) {
1550 if (fTableCellOpen) {
1552 GetSinkStream ().EndTableCell ();
1553 fTableCellOpen =
false;
1554 BasicFontStackOperation (fTableCellOpen);
1556 if (fTableRowOpen) {
1558 GetSinkStream ().EndTableRow ();
1559 fTableRowOpen =
false;
1561 GetSinkStream ().EndTable ();
1565 fTableRowOpen =
true;
1566 fTableCellOpen =
true;
1571void StyledTextIOReader_HTML::HandleHTMLThingyTag_td (
bool start,
const char* text,
size_t nBytes)
1574 if (fTableOpenCount > 0 and fTableRowOpen) {
1575 GetSinkStream ().Flush ();
1577 if (fTableCellOpen) {
1579 GetSinkStream ().EndTableCell ();
1580 fTableCellOpen =
false;
1581 BasicFontStackOperation (fTableCellOpen);
1583 GetSinkStream ().StartTableCell (1);
1584 fTableCellOpen =
true;
1585 BasicFontStackOperation (fTableCellOpen);
1586 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1590 if (fTableCellOpen) {
1591 GetSinkStream ().EndTableCell ();
1592 fTableCellOpen =
false;
1593 BasicFontStackOperation (fTableCellOpen);
1599void StyledTextIOReader_HTML::HandleHTMLThingyTag_th (
bool start,
const char* text,
size_t nBytes)
1602 HandleHTMLThingyTag_td (start, text, nBytes);
1604 fFontStack.back ().SetStyle_Bold (
true);
1605 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1609void StyledTextIOReader_HTML::HandleHTMLThingyTag_title (
bool start,
const char* ,
size_t )
1611 fComingTextIsTitle = start;
1614void StyledTextIOReader_HTML::HandleHTMLThingyTag_tr (
bool start,
const char* ,
size_t )
1617 if (fTableOpenCount > 0) {
1618 GetSinkStream ().Flush ();
1620 if (fTableCellOpen) {
1622 GetSinkStream ().EndTableCell ();
1623 fTableCellOpen =
false;
1624 BasicFontStackOperation (fTableCellOpen);
1626 if (fTableRowOpen) {
1628 GetSinkStream ().EndTableRow ();
1629 fTableRowOpen =
false;
1633 GetSinkStream ().StartTableRow ();
1634 fTableRowOpen =
true;
1643void StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (
bool start,
const char* text,
size_t nBytes)
1645 BasicFontStackOperation (start);
1648 fsp.SetFontName (Led_SDK_TCHAROF (
"courier"));
1649 fFontStack.back () = fsp;
1650 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1654void StyledTextIOReader_HTML::HandleHTMLThingyTag_u (
bool start,
const char* ,
size_t )
1656 BasicFontStackOperation (start);
1659 fsp.SetStyle_Underline (
true);
1660 fFontStack.back () = fsp;
1664void StyledTextIOReader_HTML::HandleHTMLThingyTag_ul (
bool start,
const char* text,
size_t nBytes)
1669 EmitForcedLineBreak ();
1670 ListStyle listStyle = eListStyle_Bullet;
1671 GetSinkStream ().SetListStyle (listStyle);
1672 GrabAndApplyCSSStyleFromTagText (text, nBytes);
1676 if (fULNestingCount == 0) {
1677 EmitForcedLineBreak ();
1678 ListStyle listStyle = eListStyle_None;
1679 GetSinkStream ().SetListStyle (listStyle);
1684void StyledTextIOReader_HTML::HandleHTMLThingyTag_var (
bool start,
const char* text,
size_t nBytes)
1687 StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (start, text, nBytes);
1690void StyledTextIOReader_HTML::HandleHTMLThingyTag_xmp (
bool start,
const char* text,
size_t nBytes)
1693 StyledTextIOReader_HTML::HandleHTMLThingyTag_tt (start, text, nBytes);
1696void StyledTextIOReader_HTML::HandleHTMLThingyTagUnknown ([[maybe_unused]]
bool start, [[maybe_unused]]
const char* text, [[maybe_unused]]
size_t nBytes)
1698#if !qThrowAwayMostUnknownHTMLTags
1699 EmitText (text, nBytes);
1703void StyledTextIOReader_HTML::EmitForcedLineBreak ()
1705 EmitText (LED_TCHAR_OF (
"\n"), 1,
true);
1708void StyledTextIOReader_HTML::BasicFontStackOperation (
bool start)
1711 fFontStack.push_back (fFontStack.back ());
1716 if (fFontStack.size () > 1) {
1717 fFontStack.pop_back ();
1722bool StyledTextIOReader_HTML::ParseHTMLTagArgOut (
const string& tagText,
const string& attrName,
string* attrValue)
1729 size_t len = tagText.length ();
1733 if (i == 0 and tagText[i] ==
'<') {
1736 while (i < len and isspace (tagText[i])) {
1742 size_t startOfArgName = i;
1743 while (isalpha (tagText[i])) {
1749 tagName =
string{tagText.c_str () + startOfArgName, (i - startOfArgName)};
1753 for (; i < len; i++) {
1754 while (i < len and isspace (tagText[i])) {
1758 size_t startOfArgName = i;
1759 while (isalpha (tagText[i])) {
1765 string argName (tagText.c_str () + startOfArgName, (i - startOfArgName));
1767 while (i < len and isspace (tagText[i])) {
1772 if (i < len and tagText[i] ==
'=') {
1779 while (i < len and isspace (tagText[i])) {
1783 bool gotStartQuote =
false;
1784 char startQuote =
'\0';
1786 if (tagText[i] ==
'\'' or tagText[i] ==
'\"') {
1787 gotStartQuote =
true;
1788 startQuote = tagText[i];
1793 size_t startOfArgValue = i;
1794 while ((not isspace (tagText[i]) or gotStartQuote) and tagText[i] != startQuote and tagText[i] !=
'>') {
1800 string argValue (tagText.c_str () + startOfArgValue, (i - startOfArgValue));
1801 if (Led_CasedStringsEqual (attrName, argName)) {
1802 *attrValue = argValue;
1810bool StyledTextIOReader_HTML::ParseCSSTagArgOut (
const string& text,
const string& attrName,
string* attrValue)
1812 size_t len = text.length ();
1814 for (
size_t i = 0; i < len; i++) {
1815 while (i < len and (isspace (text[i]) or (text[i] ==
';'))) {
1821 size_t startOfArgName = i;
1822 while (isalpha (text[i]) or text[i] ==
'-') {
1828 argName =
string{text.c_str () + startOfArgName, (i - startOfArgName)};
1831 while (i < len and isspace (text[i])) {
1836 if (i < len and text[i] ==
':') {
1843 while (i < len and isspace (text[i])) {
1847 char startQuote =
'\0';
1849 if (text[i] ==
'\'' or text[i] ==
'\"') {
1850 startQuote = text[i];
1856 size_t startOfArgValue = i;
1857 while (text[i] !=
';') {
1858 if (text[i] == startQuote) {
1866 string argValue (text.c_str () + startOfArgValue, (i - startOfArgValue));
1867 if (Led_CasedStringsEqual (attrName, argName)) {
1868 *attrValue = argValue;
1876void StyledTextIOReader_HTML::StartPara ()
1879 Assert (not fInAPara);
1883void StyledTextIOReader_HTML::EndParaIfOpen ()
1886 EmitForcedLineBreak ();
1888 fLastCharSpace =
true;
1889 GetSinkStream ().SetJustification (eLeftJustify);
1891 Ensure (not fInAPara);
1894void StyledTextIOReader_HTML::SetHTMLFontSize (
int to)
1896 fHTMLFontSize = min (to, 7);
1897 fHTMLFontSize = max (fHTMLFontSize, 1);
1899 fsp.SetPointSize (HTMLInfo::HTMLFontSizeToRealFontSize (fHTMLFontSize));
1900 fFontStack.back () = fsp;
1909size_t StyledTextIOWriter_HTML::WriterContext::GetCurSrcOffset ()
const
1911 return GetSrcStream ().current_offset ();
1914#if qStroika_Frameworks_Led_SupportGDI
1915SimpleEmbeddedObjectStyleMarker* StyledTextIOWriter_HTML::WriterContext::GetCurSimpleEmbeddedObjectStyleMarker ()
const
1917 size_t offset = GetCurSrcOffset ();
1918 vector<SimpleEmbeddedObjectStyleMarker*> embeddingsList = GetSrcStream ().CollectAllEmbeddingMarkersInRange (offset - 1, offset);
1919 Assert (embeddingsList.size () <= 1);
1922 if (embeddingsList.empty ()) {
1926 return embeddingsList[0];
1936StyledTextIOWriter_HTML::StyledTextIOWriter_HTML (SrcStream* srcStream, SinkStream* sinkStream,
const HTMLInfo* getHTMLInfoFrom)
1937 : StyledTextIOWriter (srcStream, sinkStream)
1938 , fGetHTMLInfoFrom (getHTMLInfoFrom)
1939 , fStyleRunSummary ()
1940 , fSoftLineBreakChar (srcStream->GetSoftLineBreakCharacter ())
1944StyledTextIOWriter_HTML::~StyledTextIOWriter_HTML ()
1956const vector<StyledTextIOWriter_HTML::EntityRefMapEntry>& StyledTextIOWriter_HTML::GetEntityRefMapTable ()
const
1958 static bool sFirstTime =
true;
1959 static vector<StyledTextIOReader_HTML::EntityRefMapEntry> sResult;
1962 for (
size_t i = 0; i < HTMLInfo::kDefaultEntityRefMapTable_Count; ++i) {
1963#if !qWriteOutMostHTMLEntitiesByName
1965 if (HTMLInfo::sDefaultEntityRefMapTable[i].fEntityRefName !=
"amp" and HTMLInfo::sDefaultEntityRefMapTable[i].fEntityRefName !=
"gt" and
1966 HTMLInfo::sDefaultEntityRefMapTable[i].fEntityRefName !=
"lt" and HTMLInfo::sDefaultEntityRefMapTable[i].fEntityRefName !=
"quot"
1972 sResult.push_back (HTMLInfo::sDefaultEntityRefMapTable[i]);
1978void StyledTextIOWriter_HTML::Write ()
1980 WriterContext writerContext (*
this);
1981 WriteHeader (writerContext);
1982 WriteBody (writerContext);
1983 WriteCloseTag (writerContext,
"html");
1987void StyledTextIOWriter_HTML::WriteHeader (WriterContext& writerContext)
1989 if (fGetHTMLInfoFrom !=
nullptr and fGetHTMLInfoFrom->fDocTypeTag.length () != 0) {
1990 write (fGetHTMLInfoFrom->fDocTypeTag);
1993 if (fGetHTMLInfoFrom ==
nullptr or fGetHTMLInfoFrom->fHTMLTag.length () == 0) {
1994 WriteOpenTag (writerContext,
"html");
1997 WriteOpenTagSpecial (writerContext,
"html", fGetHTMLInfoFrom->fHTMLTag);
2001 if (fGetHTMLInfoFrom ==
nullptr or fGetHTMLInfoFrom->fHeadTag.length () == 0) {
2002 WriteOpenTag (writerContext,
"head");
2005 WriteOpenTagSpecial (writerContext,
"head", fGetHTMLInfoFrom->fHeadTag);
2009 if (fGetHTMLInfoFrom !=
nullptr) {
2010 for (
size_t i = 0; i < fGetHTMLInfoFrom->fUnknownHeaderTags.size (); i++) {
2011 write (fGetHTMLInfoFrom->fUnknownHeaderTags[i]);
2015 if (fGetHTMLInfoFrom !=
nullptr and fGetHTMLInfoFrom->fTitle.length () != 0) {
2016 WriteOpenTag (writerContext,
"title");
2017 write (MapOutputTextFromTString (fGetHTMLInfoFrom->fTitle));
2018 WriteCloseTag (writerContext,
"title");
2022 WriteCloseTag (writerContext,
"head");
2026void StyledTextIOWriter_HTML::WriteBody (WriterContext& writerContext)
2028 AssureStyleRunSummaryBuilt (writerContext);
2030 if (fGetHTMLInfoFrom ==
nullptr or fGetHTMLInfoFrom->fStartBodyTag.length () == 0) {
2031 WriteOpenTag (writerContext,
"body");
2034 WriteOpenTagSpecial (writerContext,
"body", fGetHTMLInfoFrom->fStartBodyTag);
2036 WriteInnerBody (writerContext);
2038 WriteCloseTag (writerContext,
"body");
2042void StyledTextIOWriter_HTML::WriteInnerBody (WriterContext& writerContext)
2044 AssureStyleRunSummaryBuilt (writerContext);
2053 writerContext.fLastEmittedISR = StyledInfoSummaryRecord (IncrementalFontSpecification (), 0);
2054 writerContext.fLastStyleChangeAt = 0;
2055 writerContext.fIthStyleRun = 0;
2057 while (writerContext.GetSrcStream ().readNTChars (&c, 1) != 0) {
2058 WriteBodyCharacter (writerContext, c);
2063void StyledTextIOWriter_HTML::WriteBodyCharacter (WriterContext& writerContext, Led_tChar c)
2065 ListStyle listStyle = eListStyle_None;
2066 unsigned char indentLevel = 0;
2067 writerContext.GetSrcStream ().GetListStyleInfo (&listStyle, &indentLevel);
2069 bool justOpenedList =
false;
2070 if (listStyle == eListStyle_None) {
2071 if (writerContext.fEmittingListItem) {
2072 WriteCloseTag (writerContext,
"li");
2074 writerContext.fEmittingListItem =
false;
2076 if (writerContext.fEmittingList) {
2077 WriteCloseTag (writerContext,
"ul");
2079 writerContext.fEmittingList =
false;
2083 if (writerContext.fEmittedStartOfPara) {
2084 WriteCloseTag (writerContext,
"p");
2086 writerContext.fEmittedStartOfPara =
false;
2088 if (not writerContext.fEmittingList) {
2089 WriteOpenTag (writerContext,
"ul");
2091 writerContext.fEmittingList =
true;
2093 if (not writerContext.fEmittingListItem) {
2094 WriteOpenTag (writerContext,
"li");
2095 writerContext.fEmittingListItem =
true;
2096 justOpenedList =
true;
2100 if (not writerContext.fEmittedStartOfPara and (not writerContext.fEmittingListItem) and (not writerContext.fInTableCell)) {
2103 switch (writerContext.GetSrcStream ().GetJustification ()) {
2105 WriteOpenTag (writerContext,
"p",
"align=\"left\"");
2107 case eCenterJustify:
2108 WriteOpenTag (writerContext,
"p",
"align=\"center\"");
2111 WriteOpenTag (writerContext,
"p",
"align=\"right\"");
2114 WriteOpenTag (writerContext,
"p",
"align=\"justify\"");
2119 writerContext.fEmittedStartOfPara =
true;
2123 if (writerContext.GetSrcStream ().current_offset () - 1 == 0) {
2124 EmitBodyFontInfoChange (writerContext, fStyleRunSummary[writerContext.fIthStyleRun],
false);
2126 if (writerContext.GetSrcStream ().current_offset () - 1 == writerContext.fLastStyleChangeAt + writerContext.fLastEmittedISR.fLength) {
2127 writerContext.fLastStyleChangeAt = writerContext.GetSrcStream ().current_offset () - 1;
2128 writerContext.fIthStyleRun++;
2132 EmitBodyFontInfoChange (writerContext, fStyleRunSummary[writerContext.fIthStyleRun], c ==
'\n');
2136 if (writerContext.fEmittingListItem) {
2137 if (not justOpenedList) {
2138 WriteCloseTag (writerContext,
"li");
2139 writerContext.fEmittingListItem =
false;
2143 else if (writerContext.fInTableCell) {
2144 WriteOpenCloseTag (writerContext,
"br");
2147 else if (writerContext.fEmittedStartOfPara) {
2148 WriteCloseTag (writerContext,
"p");
2150 writerContext.fEmittedStartOfPara =
false;
2154#if qStroika_Frameworks_Led_SupportGDI
2155 case kEmbeddingSentinelChar: {
2156 unique_ptr<Table> table (writerContext.GetSrcStream ().GetTableAt (writerContext.GetCurSrcOffset () - 1));
2157 if (table.get () !=
nullptr) {
2158 WriteTable (writerContext, table.get ());
2159 [[maybe_unused]]
size_t x = table->GetOffsetEnd ();
2165 SimpleEmbeddedObjectStyleMarker* embedding = writerContext.GetCurSimpleEmbeddedObjectStyleMarker ();
2166 if (StandardURLStyleMarker* aHRef =
dynamic_cast<StandardURLStyleMarker*
> (embedding)) {
2167 Led_URLD urld = aHRef->GetURLData ();
2168 WriteOpenTag (writerContext,
"a",
"href=\"" + urld.GetURL () +
"\"");
2169 write (urld.GetTitle ().c_str ());
2170 WriteCloseTag (writerContext,
"a");
2176 if (c == fSoftLineBreakChar) {
2177 WriteOpenCloseTag (writerContext,
"br");
2180 wchar_t unicodeC = c;
2184 const vector<StyledTextIOReader_HTML::EntityRefMapEntry>& entityRefs = GetEntityRefMapTable ();
2185 vector<EntityRefMapEntry>::const_iterator i = entityRefs.begin ();
2186 for (; i != entityRefs.end (); ++i) {
2187 if (unicodeC == (*i).fCharValue) {
2189 write ((*i).fEntityRefName);
2194 if (i == entityRefs.end ()) {
2195 write (MapOutputTextFromWString (wstring{&unicodeC, 1}));
2200 if (IsASCIISpace_ (c) and writerContext.GetSrcStream ().current_offset () - writerContext.fLastForcedNLAt > 80) {
2202 writerContext.fLastForcedNLAt = writerContext.GetSrcStream ().current_offset ();
2213void StyledTextIOWriter_HTML::WriteTable (WriterContext& writerContext, Table* table)
2218 using CellInfo = Table::CellInfo;
2220 WriteOpenTag (writerContext,
"table");
2222 size_t rows = table->GetRows ();
2223 for (
size_t r = 0; r < rows; ++r) {
2224 WriteOpenTag (writerContext,
"tr");
2225 vector<CellInfo> cellInfos;
2226 table->GetRowInfo (r, &cellInfos);
2227 size_t columns = cellInfos.size ();
2228 for (
size_t c = 0; c < columns; c++) {
2229 WriteOpenTag (writerContext,
"td");
2230 unique_ptr<SrcStream> srcStream = unique_ptr<SrcStream> (table->MakeCellSubSrcStream (r, c));
2231 if (srcStream.get () !=
nullptr) {
2232 WriterContext wc (writerContext, *srcStream.get ());
2233 vector<StyledInfoSummaryRecord> x = fStyleRunSummary;
2234 fStyleRunSummary.clear ();
2235 AssureStyleRunSummaryBuilt (wc);
2236 WriteInnerBody (wc);
2239 for (vector<string>::reverse_iterator i = wc.fTagStack.rbegin (); i != wc.fTagStack.rend (); ++i) {
2240 string thisTag = *i;
2241 write (
"</" + thisTag +
">");
2244 fStyleRunSummary = x;
2246 WriteCloseTag (writerContext,
"td");
2248 WriteCloseTag (writerContext,
"tr");
2251 WriteCloseTag (writerContext,
"table");
2261void StyledTextIOWriter_HTML::WriteOpenTag (WriterContext& writerContext,
const string& tagName,
const string& tagExtras)
2263 Require (not tagName.empty ());
2264 Require (tagName[0] !=
'<');
2265 Require (tagName[0] !=
'/');
2266 writerContext.fTagStack.push_back (tagName);
2267 write (
"<" + tagName);
2268 string te = tagExtras;
2269 if (not te.empty () and te[0] !=
' ') {
2272 write (te.c_str ());
2282void StyledTextIOWriter_HTML::WriteOpenTagSpecial (WriterContext& writerContext,
const string& tagName,
const string& tagFullText)
2284 Require (not tagName.empty ());
2285 Require (tagName[0] !=
'<');
2286 Require (tagName[0] !=
'/');
2287 writerContext.fTagStack.push_back (tagName);
2288 write (tagFullText);
2297void StyledTextIOWriter_HTML::WriteCloseTag (WriterContext& writerContext,
const string& tagName)
2300 size_t countToPop = 0;
2301 for (vector<string>::reverse_iterator i = writerContext.fTagStack.rbegin (); i != writerContext.fTagStack.rend (); ++i) {
2302 string thisTag = *i;
2303 write (
"</" + thisTag +
">");
2305 if (thisTag == tagName) {
2309 writerContext.fTagStack.erase (writerContext.fTagStack.end () - countToPop, writerContext.fTagStack.end ());
2318void StyledTextIOWriter_HTML::WriteOpenCloseTag (WriterContext& , [[maybe_unused]]
const string& tagName,
const string& tagExtras)
2320 Require (not tagName.empty ());
2321 Require (tagName[0] !=
'<');
2322 Require (tagName[0] !=
'/');
2325 string te = tagExtras;
2326 if (not te.empty () and te[0] !=
' ') {
2329 write (te.c_str ());
2338bool StyledTextIOWriter_HTML::IsTagOnStack (WriterContext& writerContext,
const string& tagName)
2340 for (
auto i = writerContext.fTagStack.begin (); i != writerContext.fTagStack.end (); ++i) {
2341 if (*i == tagName) {
2348static inline string PrintColorString (
Color color)
2350 unsigned short red = color.GetRed () >> 8;
2351 unsigned short greeen = color.GetGreen () >> 8;
2352 unsigned short blue = color.GetBlue () >> 8;
2355 buf[1] = NumToHexChar_ (red >> 4);
2356 buf[2] = NumToHexChar_ (red % 16);
2357 buf[3] = NumToHexChar_ (greeen >> 4);
2358 buf[4] = NumToHexChar_ (greeen % 16);
2359 buf[5] = NumToHexChar_ (blue >> 4);
2360 buf[6] = NumToHexChar_ (blue % 16);
2363 string result =
string{buf};
2364 for (
size_t i = 0; i < Memory::NEltsOf (kColorNameTable_); ++i) {
2365 if (Led_CasedStringsEqual (buf,
string{
"\""sv} +
string{kColorNameTable_[i].second} +
string{
"\""sv})) {
2367 result = kColorNameTable_[i].first;
2374void StyledTextIOWriter_HTML::EmitBodyFontInfoChange (WriterContext& writerContext,
const FontSpecification& newOne,
bool skipDoingOpenTags)
2377 bool fontTagChanged = newOne.GetFontName () != writerContext.fLastEmittedISR.GetFontName () or
2378 newOne.GetPointSize () != writerContext.fLastEmittedISR.GetPointSize () or
2379 newOne.GetTextColor () != writerContext.fLastEmittedISR.GetTextColor ();
2380 if (fontTagChanged and IsTagOnStack (writerContext,
"span")) {
2381 WriteCloseTag (writerContext,
"span");
2383 if (not newOne.GetStyle_Bold () and IsTagOnStack (writerContext,
"b")) {
2384 WriteCloseTag (writerContext,
"b");
2386 if (not newOne.GetStyle_Italic () and IsTagOnStack (writerContext,
"i")) {
2387 WriteCloseTag (writerContext,
"i");
2389 if (not newOne.GetStyle_Underline () and IsTagOnStack (writerContext,
"u")) {
2390 WriteCloseTag (writerContext,
"u");
2392 if (newOne.GetStyle_SubOrSuperScript () != FontSpecification::eSubscript and IsTagOnStack (writerContext,
"sub")) {
2393 WriteCloseTag (writerContext,
"sub");
2395 if (newOne.GetStyle_SubOrSuperScript () != FontSpecification::eSuperscript and IsTagOnStack (writerContext,
"sup")) {
2396 WriteCloseTag (writerContext,
"sup");
2398#if qStroika_Foundation_Common_Platform_Windows
2399 if (not newOne.GetStyle_Strikeout () and IsTagOnStack (writerContext,
"strike")) {
2400 WriteCloseTag (writerContext,
"strike");
2405 if (skipDoingOpenTags) {
2407 writerContext.fLastEmittedISR =
2408 StyledInfoSummaryRecord (IncrementalFontSpecification (), fStyleRunSummary[writerContext.fIthStyleRun].fLength);
2411 if (not IsTagOnStack (writerContext,
"span")) {
2412 char sprintfBuffer[1024];
2413 string cssInfo =
"style=\"";
2414 cssInfo +=
"font-family: '" + String::FromSDKString (newOne.GetFontName ()).AsNarrowSDKString () +
"'; ";
2415 cssInfo += (snprintf (sprintfBuffer, Memory::NEltsOf (sprintfBuffer),
"font-size: %dpt; ", newOne.GetPointSize ()), sprintfBuffer);
2416 cssInfo +=
"color: " + PrintColorString (newOne.GetTextColor ());
2418 WriteOpenTag (writerContext,
"span",
2422 "face=\"" + SDKString2NarrowSDK (newOne.GetFontName ()) +
"\" size=\"" +
2423 Led_NumberToDigitChar (HTMLInfo::RealFontSizeToHTMLFontSize (newOne.GetPointSize ())) +
2424 "\" color=" + PrintColorString (newOne.GetTextColor ())
2428 if (newOne.GetStyle_Bold () and not IsTagOnStack (writerContext,
"b")) {
2429 WriteOpenTag (writerContext,
"b");
2431 if (newOne.GetStyle_Italic () and not IsTagOnStack (writerContext,
"i")) {
2432 WriteOpenTag (writerContext,
"i");
2434 if (newOne.GetStyle_Underline () and not IsTagOnStack (writerContext,
"u")) {
2435 WriteOpenTag (writerContext,
"u");
2438 switch (newOne.GetStyle_SubOrSuperScript ()) {
2439 case FontSpecification::eSubscript: {
2440 if (not IsTagOnStack (writerContext,
"sub")) {
2441 WriteOpenTag (writerContext,
"sub");
2444 case FontSpecification::eSuperscript: {
2445 if (not IsTagOnStack (writerContext,
"sup")) {
2446 WriteOpenTag (writerContext,
"sup");
2450#if qStroika_Foundation_Common_Platform_Windows
2451 if (newOne.GetStyle_Strikeout () and not IsTagOnStack (writerContext,
"strike")) {
2452 WriteOpenTag (writerContext,
"strike");
2455 writerContext.fLastEmittedISR = fStyleRunSummary[writerContext.fIthStyleRun];
2459void StyledTextIOWriter_HTML::AssureStyleRunSummaryBuilt (WriterContext& writerContext)
2461 if (fStyleRunSummary.empty ()) {
2462 size_t totalTextLength = writerContext.GetSrcStream ().GetTotalTextLength ();
2463 fStyleRunSummary = vector<StyledInfoSummaryRecord> (writerContext.GetSrcStream ().GetStyleInfo (0, totalTextLength));
2467string StyledTextIOWriter_HTML::MapOutputTextFromWString (
const wstring& text)
2472 result.reserve (text.length ());
2473 for (
auto i = text.begin (); i != text.end (); ++i) {
2474 if (
static_cast<unsigned int> (*i) <= 127) {
2475 char c =
static_cast<char> (*i);
2476 result.append (&c, 1);
2480 (void)snprintf (buf, Memory::NEltsOf (buf),
"&#%d;",
static_cast<unsigned int> (*i));
2487string StyledTextIOWriter_HTML::MapOutputTextFromTString (
const Led_tString& text)
2489 return MapOutputTextFromWString (text);
#define RequireNotNull(p)
CodeCvt unifies byte <-> unicode conversions, vaguely inspired by (and wraps) std::codecvt,...
nonvirtual STRINGISH Bytes2String(span< const byte > from) const
nonvirtual BLOBISH String2Bytes(span< const CHAR_T > from) const
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...