]> git.lyx.org Git - features.git/blobdiff - src/insets/InsetERT.cpp
DocBook, InsetFloat: avoid a potential nullptr dereference when detecting the type...
[features.git] / src / insets / InsetERT.cpp
index 87abc632b8e510469b9e88a7886ba4b6e1a5abfc..b3e73ffdede35656a53a29c8412594edf631521b 100644 (file)
 #include "support/gettext.h"
 #include "support/lstrings.h"
 #include "support/TempFile.h"
+#include "Encoding.h"
 
 #include <sstream>
-
+#include <regex>
 #include <iostream>
 
 using namespace std;
@@ -131,26 +132,77 @@ void InsetERT::docbook(XMLStream & xs, OutputParams const & runparams) const
 //             auto lay = getLayout();
 //     }
 
-       // Output the ERT as a comment with the appropriate escaping if the command is not recognised.
-       if (trim(os.str()) == from_ascii("\\textquotesingle")) {
-               xs << "'";
-       } else if (trim(os.str()) == from_ascii("\\TeX") || trim(os.str()) == from_ascii("\\TeX{}")) {
-           xs << "TeX";
-       } else if (trim(os.str()) == from_ascii("\\LaTeX") || trim(os.str()) == from_ascii("\\LaTeX{}")) {
-           xs << "LaTeX";
-       } else if (trim(os.str()) == from_ascii("\\LaTeXe") || trim(os.str()) == from_ascii("\\LaTeXe{}")) {
-           xs << "LaTeX2&#x03b5;";
-       } else if (trim(os.str()) == from_ascii("\\LyX") || trim(os.str()) == from_ascii("\\LyX{}")) {
-           xs << "LyX";
-       } else if (trim(os.str()) == from_ascii("\\oe") || trim(os.str()) == from_ascii("\\oe{}")) {
-           xs << "&#339;";
-       } else if (trim(os.str()) == from_ascii("\\OE") || trim(os.str()) == from_ascii("\\OE{}")) {
-           xs << "&#338;";
-       } else {
-        xs << XMLStream::ESCAPE_NONE << "<!-- ";
-        xs << XMLStream::ESCAPE_COMMENTS << os.str();
-        xs << XMLStream::ESCAPE_NONE << " -->";
-    }
+       // Try to recognise some commands to have a nicer DocBook output.
+       bool output_as_comment = true;
+
+       // First step: some commands have a direct mapping to DocBook, mostly because the mapping is simply text or
+       // an XML entity.
+       // Logic is similar to that of convertLaTeXCommands in BiblioInfo.cpp.
+       // TODO: make the code even more similar by looping over the string and applying all conversions. (What is not
+       //  recognised should simply be put in comments: have a list of elements that are either already recognised or are
+       //  not yet recognised? Global transformations like \string should then come first.)
+       {
+               docstring os_trimmed = trim(os.str());
+
+               // Rewrite \"u to \"{u}.
+               static regex const regNoBraces(R"(^\\\W\w)");
+               if (regex_search(to_utf8(os_trimmed), regNoBraces)) {
+                       os_trimmed.insert(3, from_ascii("}"));
+                       os_trimmed.insert(2, from_ascii("{"));
+               }
+
+               // Rewrite \" u to \"{u}.
+               static regex const regSpace(R"(^\\\W \w)");
+               if (regex_search(to_utf8(os_trimmed), regSpace)) {
+                       os_trimmed[2] = '{';
+                       os_trimmed.insert(4, from_ascii("}"));
+               }
+
+               std::cout << to_utf8(os_trimmed) << std::endl;
+
+               // Look into the global table of Unicode characters if there is a match.
+               bool termination;
+               docstring rem;
+               docstring const converted = Encodings::fromLaTeXCommand(os_trimmed,
+                                                                       Encodings::TEXT_CMD, termination, rem);
+               if (!converted.empty()) {
+                       // Don't output the characters directly, even if the document should be encoded in UTF-8, for editors that
+                       // do not support all these funky characters.
+                       for (const char_type& character : converted) {
+                               xs << XMLStream::ESCAPE_NONE << from_ascii("&#" + std::to_string(character) + ';');
+                       }
+                       output_as_comment = false;
+               }
+       }
+
+       // Second step: the command \string can be ignored. If that's the only command in the ERT, then done.
+       // There may be several occurrences. (\string is 7 characters long.)
+       if (os.str().length() >= 7) {
+               docstring os_str = os.str();
+
+               while (os_str.length() >= 7) {
+                       auto os_text = os_str.find(from_ascii("\\string"));
+
+                       if (os_text != lyx::docstring::npos && !std::isalpha(static_cast<int>(os_str[os_text + 7]))) {
+                               os_str = os_str.substr(0, os_text) + os_str.substr(os_text + 7, os_str.length());
+
+                               if (os_str.find('\\') == std::string::npos) {
+                                       xs << os_str;
+                                       output_as_comment = false;
+                                       break;
+                               }
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       // Otherwise, output the ERT as a comment with the appropriate escaping if the command is not recognised.
+       if (output_as_comment) {
+               xs << XMLStream::ESCAPE_NONE << "<!-- ";
+               xs << XMLStream::ESCAPE_COMMENTS << os.str();
+               xs << XMLStream::ESCAPE_NONE << " -->";
+       }
 }