19 #include <QRegularExpression>
20 #include <QRegularExpressionMatch>
22 #include <QStringList>
24 #include "../../util/btassert.h"
25 #include "../drivers/cswordmoduleinfo.h"
26 #include "../managers/cswordbackend.h"
30 #include <swbasicfilter.h>
38 setEscapeStringCaseSensitive(
true);
39 setPassThruUnknownEscapeString(
true);
41 removeTokenSubstitute(
"Rf");
44 addTokenSubstitute(
"FI",
"<span class=\"italic\">");
45 addTokenSubstitute(
"Fi",
"</span>");
47 addTokenSubstitute(
"FB",
"<span class=\"bold\">");
48 addTokenSubstitute(
"Fb",
"</span>");
50 addTokenSubstitute(
"FR",
"<span class=\"jesuswords\">");
51 addTokenSubstitute(
"Fr",
"</span>");
53 addTokenSubstitute(
"FU",
"<u>");
54 addTokenSubstitute(
"Fu",
"</u>");
56 addTokenSubstitute(
"FO",
"<span class=\"quotation\">");
57 addTokenSubstitute(
"Fo",
"</span>");
60 addTokenSubstitute(
"FS",
"<span class=\"sup\">");
61 addTokenSubstitute(
"Fs",
"</span>");
63 addTokenSubstitute(
"FV",
"<span class=\"sub\">");
64 addTokenSubstitute(
"Fv",
"</span>");
66 addTokenSubstitute(
"TT",
"<div class=\"booktitle\">");
67 addTokenSubstitute(
"Tt",
"</div>");
69 addTokenSubstitute(
"TS",
"<div class=\"sectiontitle\">");
70 addTokenSubstitute(
"Ts",
"</div>");
76 addTokenSubstitute(
"Fn",
"</font>");
77 addTokenSubstitute(
"CL",
"<br/>");
78 addTokenSubstitute(
"CM",
"<br/>");
80 addTokenSubstitute(
"CG",
">");
81 addTokenSubstitute(
"CT",
"<");
83 addTokenSubstitute(
"JR",
"<span class=\"right\">");
84 addTokenSubstitute(
"JC",
"<span class=\"center\">");
85 addTokenSubstitute(
"JL",
"</span>");
90 GBFHTML::processText(buf, key, module);
92 if (!module->isProcessEntryAttributes()) {
113 auto t = QString::fromUtf8(buf.c_str());
115 static QRegularExpression
const tag(
116 QStringLiteral(R
"PCRE(([.,;:]?<W[HGT][^>]*?>\s*)+)PCRE"));
118 QRegularExpressionMatch match;
119 auto pos = t.indexOf(tag, 0, &match);
123 auto const partLength = pos + match.capturedLength();
124 list.append(t.left(partLength));
125 t.remove(0, partLength);
126 pos = t.indexOf(tag, 0, &match);
132 list.append(std::move(t));
138 static QRegularExpression
const tag(
139 QStringLiteral(R
"PCRE(<W([HGT])([^>]*?)>)PCRE"));
142 for (
auto & e : list) {
151 static QRegularExpression
const re(
152 QStringLiteral(R
"PCRE([.,;:])PCRE"));
153 if (e.trimmed().remove(re).left(2) == QStringLiteral(
"<W")) {
159 bool insertedTag =
false;
160 bool hasLemmaAttr =
false;
161 bool hasMorphAttr =
false;
163 int tagAttributeStart = -1;
167 QRegularExpressionMatch match;
168 for (
auto pos = e.indexOf(tag, 0, &match);
170 pos = e.indexOf(tag, pos, &match))
172 auto const isMorph = match.captured(1) == QStringLiteral(
"T");
176 : match.captured(2).prepend(match.captured(1));
178 if (value.isEmpty()) {
184 e.replace(pos, match.capturedLength(), QStringLiteral(
"</span>"));
189 QStringLiteral(
"<span %1=\"%2\">")
191 ? QStringLiteral(
"morph")
192 : QStringLiteral(
"lemma"),
195 hasMorphAttr = isMorph;
196 hasLemmaAttr = !isMorph;
199 QChar c = e[startPos];
201 while ((startPos < pos) && (c.isSpace() || c.isPunct())) {
207 tagAttributeStart = startPos + 6;
209 e.insert(startPos, std::move(rep));
212 e.remove(pos, match.capturedLength());
214 if (tagAttributeStart == -1) {
218 if ((!isMorph && hasLemmaAttr) || (isMorph && hasMorphAttr)) {
220 auto const & attrRegExp =
223 static QRegularExpression
const re(
224 QStringLiteral(
"morph=\".+?(?=\")"));
227 static QRegularExpression
const re(
228 QStringLiteral(
"lemma=\".+?(?=\")"));
232 QRegularExpressionMatch match;
234 e.indexOf(attrRegExp, tagAttributeStart, &match);
236 if (foundPos != -1) {
237 e.insert(foundPos + match.capturedLength(),
238 QStringLiteral(
"|") + value);
239 pos += value.length() + 1;
241 hasLemmaAttr = !isMorph;
242 hasMorphAttr = isMorph;
246 hasMorphAttr = isMorph;
247 hasLemmaAttr = !isMorph;
249 auto attr = QStringLiteral(
"%1=\"%2\" ")
251 ? QStringLiteral(
"morph")
252 : QStringLiteral(
"lemma"),
255 e.insert(tagAttributeStart, std::move(attr));
268 buf = result.toUtf8().constData();
276 case '0':
case '1':
case '2':
case '3':
case '4':
277 case '5':
case '6':
case '7':
case '8':
case '9':
279 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
280 return hex -
'a' + 10;
281 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
282 return hex -
'A' + 10;
284 BT_ASSERT(
false &&
"Invalid hex code in GBF");
296 if (!substituteToken(buf, token)) {
297 size_t const tokenLength = std::strlen(token);
302 sword::SWModule
const *
const myModule =
303 const_cast<sword::SWModule *
>(myUserData->module);
308 if (!std::strncmp(token,
"WG", 2u)
309 || !std::strncmp(token,
"WH", 2u)
310 || !std::strncmp(token,
"WT", 2u))
312 buf.append(
'<').append(token).append(
'>');
313 }
else if (!std::strncmp(token,
"RB", 2u)) {
314 myUserData->hasFootnotePreTag =
true;
315 buf.append(
"<span class=\"footnotepre\">");
316 }
else if (!std::strncmp(token,
"RF", 2u)) {
317 if (myUserData->hasFootnotePreTag) {
319 buf.append(
"</span>");
320 myUserData->hasFootnotePreTag =
false;
323 buf.append(
" <span class=\"footnote\" note=\"")
324 .append(myModule->getName())
326 .append(myUserData->key->getShortText())
328 .append(QString::number(myUserData->
swordFootnote).toUtf8().constData())
331 userData->suspendTextPassThru =
true;
332 }
else if (!std::strncmp(token,
"Rf", 2u)) {
333 userData->suspendTextPassThru =
false;
334 }
else if (!std::strncmp(token,
"FN", 2u)) {
336 buf.append(
"<font face=\"");
337 for (
size_t i = 2u; i < tokenLength; i++)
338 if (token[i] !=
'\"')
339 buf.append(token[i]);
341 }
else if (!std::strncmp(token,
"CA", 2u)) {
343 buf.append(
static_cast<char>(
hexToChar(token + 2u)));
345 return GBFHTML::handleToken(buf, token, userData);
static CSwordBackend & instance() noexcept
static FilterOption const strongNumbers
static FilterOption const morphTags
static FilterOption const lemmas
short unsigned int swordFootnote
bool handleToken(sword::SWBuf &buf, const char *token, sword::BasicFilterUserData *userData) override
char processText(sword::SWBuf &buf, const sword::SWKey *key, const sword::SWModule *module=nullptr) override
int hexDigitValue(char const hex)
char hexToChar(char const *const hex)
result append(std::move(e))