X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FPDFOptions.cpp;h=dc638f544dafb3638f6ad020fd7cff93c3414fd2;hb=5cb80b867f4a59c3253487652ba74a29ad5b3f0f;hp=dcf4102fc38b0be6f8c484832fb059b12d0d67c0;hpb=d26f4eacea56c2c48e11369a58441975cb0d067c;p=lyx.git diff --git a/src/PDFOptions.cpp b/src/PDFOptions.cpp index dcf4102fc3..dc638f544d 100644 --- a/src/PDFOptions.cpp +++ b/src/PDFOptions.cpp @@ -4,200 +4,304 @@ * Licence details can be found in the file COPYING. * * \author Pavel Sanda + * \author Jürgen Spitzmüller * * Full author contact details are available in file CREDITS. */ - -#include "config.h" +#include #include "PDFOptions.h" -#include -#include +#include "Encoding.h" +#include "LaTeXFeatures.h" +#include "Lexer.h" +#include "OutputParams.h" +#include "texstream.h" + #include "support/convert.h" +#include "support/debug.h" +#include "support/docstream.h" +#include "support/docstring.h" #include "support/lstrings.h" -#include "debug.h" -#include "Lexer.h" +#include +#include +#include -namespace lyx { +using namespace std; +using namespace lyx::support; +namespace lyx { -using std::ostream; -using std::ostringstream; -using std::string; const string PDFOptions::pagemode_fullscreen("FullScreen"); bool PDFOptions::empty() const { - return - author.empty() && - title.empty() && - subject.empty() && - keywords.empty()&& - pagemode.empty()&& - bookmarksopenlevel.empty() && - quoted_options.empty(); + PDFOptions x; //implicit hyperref settings + + return author == x.author + && title == x.title + && subject == x.subject + && keywords == x.keywords + && pagemode == x.pagemode + && quoted_options == x.quoted_options + && bookmarks == x.bookmarks + && bookmarksnumbered == x.bookmarksnumbered + && bookmarksopen == x.bookmarksopen + && bookmarksopenlevel == x.bookmarksopenlevel + && breaklinks == x.breaklinks + && pdfborder == x.pdfborder + && colorlinks == x.colorlinks + && backref == x.backref + && pdfusetitle == x.pdfusetitle; } + void PDFOptions::writeFile(ostream & os) const { - os << "\\use_hyperref " << convert(use_hyperref) << '\n'; - os << "\\pdf_store_options " << convert(store_options) << '\n'; - if (!use_hyperref && !store_options) return; - - if (!title.empty() ) - os << "\\pdf_title \"" << title << "\"\n"; - if (!author.empty()) - os << "\\pdf_author \"" << author << "\"\n"; - if (!subject.empty()) - os << "\\pdf_subject \"" << subject << "\"\n"; - if (!keywords.empty()) - os << "\\pdf_keywords \"" << keywords << "\"\n"; - - - os << "\\pdf_bookmarks " << convert(bookmarks) << '\n'; - os << "\\pdf_bookmarksnumbered " << convert(bookmarksnumbered) << '\n'; - os << "\\pdf_bookmarksopen " << convert(bookmarksopen) << '\n'; - if (bookmarksopenlevel.empty()) - os << "\\pdf_bookmarksopenlevel \"" << bookmarksopenlevel << "\"\n"; - - os << "\\pdf_breaklinks " << convert(breaklinks) << '\n'; - os << "\\pdf_pdfborder " << convert(pdfborder) << '\n'; - os << "\\pdf_colorlinks " << convert(colorlinks) << '\n'; - os << "\\pdf_backref " << convert(backref) << '\n'; - os << "\\pdf_pagebackref " << convert(pagebackref) << '\n'; - - if (!pagemode.empty()) - os << "\\pdf_pagemode " << pagemode << '\n'; - - if (!quoted_options.empty()) - os << "\\pdf_quoted_options \"" << quoted_options << "\"\n"; - + os << "\\use_hyperref " << convert(use_hyperref) << '\n'; + if (!use_hyperref && empty()) + return; + + if (!title.empty() ) + os << "\\pdf_title " << Lexer::quoteString(title) << '\n'; + if (!author.empty()) + os << "\\pdf_author " << Lexer::quoteString(author) << '\n'; + if (!subject.empty()) + os << "\\pdf_subject " << Lexer::quoteString(subject) << '\n'; + if (!keywords.empty()) + os << "\\pdf_keywords " << Lexer::quoteString(keywords) << '\n'; + + + os << "\\pdf_bookmarks " << convert(bookmarks) << '\n'; + os << "\\pdf_bookmarksnumbered " << convert(bookmarksnumbered) << '\n'; + os << "\\pdf_bookmarksopen " << convert(bookmarksopen) << '\n'; + os << "\\pdf_bookmarksopenlevel " << bookmarksopenlevel << '\n'; + + os << "\\pdf_breaklinks " << convert(breaklinks) << '\n'; + os << "\\pdf_pdfborder " << convert(pdfborder) << '\n'; + os << "\\pdf_colorlinks " << convert(colorlinks) << '\n'; + os << "\\pdf_backref " << backref << '\n'; + os << "\\pdf_pdfusetitle " << convert(pdfusetitle) << '\n'; + + if (!pagemode.empty()) + os << "\\pdf_pagemode " << pagemode << '\n'; + + if (!quoted_options.empty()) + os << "\\pdf_quoted_options " << Lexer::quoteString(quoted_options) << '\n'; } -void PDFOptions::writeLaTeX(odocstream &os) const + +void PDFOptions::writeLaTeX(OutputParams & runparams, otexstream & os, + bool hyperref_already_provided) const { - if (!use_hyperref) return ; - - string opt; - - opt = "\\usepackage["; - if (!title.empty()) - opt += "pdftitle={" + title + "},\n"; - if (!author.empty()) - opt += "pdfauthor={" + author + "},\n"; - if (!subject.empty()) - opt += "pdfsubject={" + subject + "},\n"; - if (!keywords.empty()) - opt += "pdfkeywords={" + keywords + "},\n"; - - opt += "bookmarks=" + convert(bookmarks) + ','; - if (bookmarks) { - opt += "bookmarksnumbered=" + - convert(bookmarksnumbered) + ','; - opt += "bookmarksopen=" + - convert(bookmarksopen) + ','; - - if (bookmarksopen && !bookmarksopenlevel.empty()) - opt += "bookmarksopennumbered=" + - bookmarksopenlevel + ','; - } - - opt += "breaklinks=" + convert(breaklinks) + ','; - - opt += "pdfborder={0 0 " ; - opt += (pdfborder ?'1':'0'); - opt += "},\n"; - - opt += "colorlinks=" + convert(colorlinks) + ','; - opt += "backref=" + convert(backref) + ','; - opt += "pagebackref=" + convert(pagebackref) + ','; - - if (!pagemode.empty()) - opt += "pdfpagemode=" + pagemode + ','; - opt += quoted_options_get(); - - opt = support::rtrim(opt,","); - opt += "]{hyperref}\n"; - - // FIXME UNICODE - os << from_utf8(opt); + // FIXME Unicode + string opt; + string hyperset; + + // Driver needed by specific converters + if (!runparams.hyperref_driver.empty()) + opt += runparams.hyperref_driver + ","; + + // Since LyX uses unicode, also set the PDF strings to unicode strings + // with the hyperref option "unicode". This is only needed with pdflatex. + // As of 2021/02/04, unicode=true is default. + if (!LaTeXFeatures::isAvailableAtLeastFrom("hyperref", 2021, 2, 4) + && !runparams.isFullUnicode() && !runparams.use_japanese) + opt += "unicode=true,"; + + // only use the hyperref settings if hyperref is enabled by the user + // see bug #7052 + if (use_hyperref) { + // try to extract author and title from document when none is + // explicitly given + if (pdfusetitle && title.empty() && author.empty()) + opt += "pdfusetitle,"; + if (!opt.empty()) + opt += "\n "; + opt += "bookmarks=" + convert(bookmarks) + ','; + if (bookmarks) { + opt += "bookmarksnumbered=" + convert(bookmarksnumbered) + ','; + opt += "bookmarksopen=" + convert(bookmarksopen) + ','; + if (bookmarksopen) + opt += "bookmarksopenlevel=" + + convert(bookmarksopenlevel) + ','; + } + if (!opt.empty()) + opt += "\n "; + opt += "breaklinks=" + convert(breaklinks) + ','; + opt += "pdfborder={0 0 "; + opt += (pdfborder ? '0' : '1'); + opt += "},"; + if (pdfborder) + opt += "pdfborderstyle={},"; + opt += "backref=" + backref + ','; + opt += "colorlinks=" + convert(colorlinks) + ','; + if (!pagemode.empty()) + opt += "pdfpagemode=" + pagemode + ','; + + // load the pdftitle etc. as hypersetup, otherwise you'll get + // LaTeX-errors when using non-latin characters + if (!title.empty()) + hyperset += "pdftitle={" + title + "},"; + if (!author.empty()) + hyperset += "\n pdfauthor={" + author + "},"; + if (!subject.empty()) + hyperset += "\n pdfsubject={" + subject + "},"; + if (!keywords.empty()) + hyperset += "\n pdfkeywords={" + keywords + "},"; + if (!quoted_options.empty()){ + hyperset += "\n "; + hyperset += quoted_options; + } + hyperset = rtrim(hyperset,","); + } + + // check if the hyperref settings use an encoding that exceeds + // ours. If so, we have to switch to utf8. + Encoding const * const enc = runparams.encoding; + docstring const hs = from_utf8(hyperset); + bool need_unicode = false; + if (enc) { + for (char_type h : hs) { + if (!enc->encodable(h)) + need_unicode = true; + } + } + + // use in \\usepackage parameter as not all options can be handled inside \\hypersetup + if (!hyperref_already_provided) { + opt = rtrim(opt, ","); + opt = "\\usepackage[" + opt + "]\n {hyperref}\n"; + + if (!hyperset.empty()) + opt += "\\hypersetup{" + hyperset + "}\n"; + } else { + // only in case hyperref is already loaded by the current text class + // try to put it into hyperset + // + // FIXME: rename in this case the PDF settings dialog checkbox + // label from "Use Hyperref" to "Customize Hyperref Settings" + // as discussd in bug #6293 + opt = "\\hypersetup{" + rtrim(opt + hyperset, ",") + "}\n"; + } + + // hyperref expects LICR macros for non-ASCII chars. + // Usually, "(lua)inputenc" converts the input to LICR, with XeTeX utf-8 works, too. + // As hyperref provides good coverage for \inputencoding{utf8}, we can try + // this if the current input encoding does not support a character. + // FIXME: don't use \inputencoding if "inputenc" is not loaded (#9839). + if (need_unicode && enc && enc->iconvName() != "UTF-8") { + if (runparams.flavor != Flavor::XeTeX) + os << "\\inputencoding{utf8}\n"; + os << setEncoding("UTF-8"); + } + // If hyperref is loaded by the document class, we output + // \hypersetup \AtBeginDocument if hypersetup is not (yet) + // defined. In this case, the class loads hyperref late + // (see bug #7048). + if (hyperref_already_provided && !opt.empty()) { + os << "\\ifx\\hypersetup\\undefined\n" + << " \\AtBeginDocument{%\n " + << from_utf8(opt) + << " }\n" + << "\\else\n " + << from_utf8(opt) + << "\\fi\n"; + } else + os << from_utf8(opt); + if (need_unicode && enc && enc->iconvName() != "UTF-8") { + os << setEncoding(enc->iconvName()); + if (runparams.flavor != Flavor::XeTeX) + os << "\\inputencoding{" << from_ascii(enc->latexName()) << "}\n"; + } } + string PDFOptions::readToken(Lexer &lex, string const & token) { - if (token == "\\use_hyperref") { - lex >> use_hyperref; - } else if (token == "\\pdf_title") { - lex >> title; - } else if (token == "\\pdf_author") { - lex >> author; - } else if (token == "\\pdf_subject") { - lex >> subject; - } else if (token == "\\pdf_keywords") { - lex >> keywords; - } else if (token == "\\pdf_bookmarks") { - lex >> bookmarks; - } else if (token == "\\pdf_bookmarksnumbered") { - lex >> bookmarksnumbered; - } else if (token == "\\pdf_bookmarksopen") { - lex >> bookmarksopenlevel; - } else if (token == "\\pdf_bookmarksopenlevel") { - lex >> bookmarksopenlevel; - } else if (token == "\\pdf_breaklinks") { - lex >> breaklinks; - } else if (token == "\\pdf_pdfborder") { - lex >> pdfborder; - } else if (token == "\\pdf_colorlinks") { - lex >> colorlinks; - } else if (token == "\\pdf_backref") { - lex >> backref; - } else if (token == "\\pdf_pagebackref") { - lex >> pagebackref; - } else if (token == "\\pdf_pagemode") { - lex >> pagemode; - } else if (token == "\\pdf_quoted_options") { - lex >> quoted_options; - } else if (token == "\\pdf_store_options") { - lex >> store_options; - } else { - return token; - } - - return string(); - + if (token == "\\use_hyperref") { + lex >> use_hyperref; + } else if (token == "\\pdf_title") { + if (lex.isOK()) { + lex.next(true); + title = lex.getString(); + } + } else if (token == "\\pdf_author") { + if (lex.isOK()) { + lex.next(true); + author = lex.getString(); + } + } else if (token == "\\pdf_subject") { + if (lex.isOK()) { + lex.next(true); + subject = lex.getString(); + } + } else if (token == "\\pdf_keywords") { + if (lex.isOK()) { + lex.next(true); + keywords = lex.getString(); + } + } else if (token == "\\pdf_bookmarks") { + lex >> bookmarks; + } else if (token == "\\pdf_bookmarksnumbered") { + lex >> bookmarksnumbered; + } else if (token == "\\pdf_bookmarksopen") { + lex >> bookmarksopen; + } else if (token == "\\pdf_bookmarksopenlevel") { + lex >> bookmarksopenlevel; + } else if (token == "\\pdf_breaklinks") { + lex >> breaklinks; + } else if (token == "\\pdf_pdfborder") { + lex >> pdfborder; + } else if (token == "\\pdf_colorlinks") { + lex >> colorlinks; + } else if (token == "\\pdf_backref") { + lex >> backref; + } else if (token == "\\pdf_pdfusetitle") { + lex >> pdfusetitle; + } else if (token == "\\pdf_pagemode") { + lex >> pagemode; + } else if (token == "\\pdf_quoted_options") { + if (lex.isOK()) { + lex.next(true); + quoted_options = lex.getString(); + } + } else { + return token; + } + return string(); } -//prepared for check -string PDFOptions::quoted_options_get() const + +// check the string from UI +string PDFOptions::quoted_options_check(string const & str) const { - return quoted_options; + return subst(str, "\n", ""); } -// Keep implicit hyperref settings + +// set implicit settings for hyperref void PDFOptions::clear() { - use_hyperref = false; - title.clear(); - author.clear(); - subject.clear(); - keywords.clear(); - bookmarks = true; - bookmarksnumbered = false; - bookmarksopen = false; - bookmarksopenlevel.clear(); - breaklinks = false; - pdfborder = false; - colorlinks = false; - backref = false; - pagebackref = false; - pagemode.clear(); - quoted_options.clear(); - store_options = false; - + use_hyperref = false; + title.clear(); + author.clear(); + subject.clear(); + keywords.clear(); + bookmarks = true; + bookmarksnumbered = false; + bookmarksopen = false; + bookmarksopenlevel = 1; + breaklinks = false; + pdfborder = false; + colorlinks = false; + backref = "false"; + pagemode.clear(); + quoted_options.clear(); + pdfusetitle = true; //in contrast with hyperref } } // namespace lyx