void add_known_environment(string const & environment, string const & o1, bool o2, docstring const & beg, docstring const &end) { vector<ArgumentType> arguments; convertArgs(o1, o2, arguments); known_environments[environment] = arguments; if (!beg.empty() || ! end.empty()) possible_textclass_environments[environment] = FullEnvironment(arguments, beg, end); }
void BufferEncodings::validate(char_type c, LaTeXFeatures & features, bool for_mathed) { CharInfo const & ci = Encodings::unicodeCharInfo(c); if (ci.isUnicodeSymbol()) { // In mathed, c could be used both in textmode and mathmode docstring const textcommand = ci.textcommand(); bool const math_mode = for_mathed && isMathCmd(c); bool const use_math = math_mode || (!for_mathed && textcommand.empty()); bool const use_text = (for_mathed && isTextCmd(c)) || (!for_mathed && !textcommand.empty()); bool const plain_utf8 = (features.runparams().encoding->name() == "utf8-plain"); bool const unicode_math = (features.isRequired("unicode-math") && features.isAvailable("unicode-math")); // with utf8-plain, we only load packages when in mathed (see #7766) // and if we do not use unicode-math if ((math_mode && !unicode_math) || (use_math && !plain_utf8)) { string const mathpreamble = ci.mathpreamble(); if (!mathpreamble.empty()) { if (ci.mathfeature()) { string feats = mathpreamble; while (!feats.empty()) { string feat; feats = split(feats, feat, ','); features.require(feat); } } else features.addPreambleSnippet(mathpreamble); } } // with utf8-plain, we do not load packages (see #7766) if (use_text && !plain_utf8) { string const textpreamble = ci.textpreamble(); if (!textpreamble.empty()) { if (ci.textfeature()) { string feats = textpreamble; while (!feats.empty()) { string feat; feats = split(feats, feat, ','); features.require(feat); } } else features.addPreambleSnippet(textpreamble); } } } if (for_mathed && isMathSym(c)) { features.require("amstext"); features.require("lyxmathsym"); } }
docstring InsetCitation::toolTip(BufferView const & bv, int, int) const { Buffer const & buf = bv.buffer(); // Only after the buffer is loaded from file... if (!buf.isFullyLoaded()) return docstring(); BiblioInfo const & bi = buf.masterBibInfo(); if (bi.empty()) return _("No bibliography defined!"); docstring const & key = getParam("key"); if (key.empty()) return _("No citations selected!"); vector<docstring> keys = getVectorFromString(key); vector<docstring>::const_iterator it = keys.begin(); vector<docstring>::const_iterator en = keys.end(); docstring tip; for (; it != en; ++it) { docstring const key_info = bi.getInfo(*it, buffer()); if (key_info.empty()) continue; if (!tip.empty()) tip += "\n"; tip += wrap(key_info, -4); } return tip; }
QValidator::State PathValidator::validate(QString & qtext, int &) const { if (!latex_doc_) return QValidator::Acceptable; docstring const text = support::trim(qstring_to_ucs4(qtext)); if (text.empty()) return acceptable_if_empty_ ? QValidator::Acceptable : QValidator::Intermediate; docstring invalid_chars = from_ascii("#$%{}()[]\"^"); if (!tex_allows_spaces_) invalid_chars += ' '; if (text.find_first_of(invalid_chars) != docstring::npos) { static int counter = 0; if (counter == 0) { Alert::error(_("Invalid filename"), _("LyX does not provide LaTeX support for file names containing any of these characters:\n") + printable_list(invalid_chars)); } ++counter; return QValidator::Intermediate; } return QValidator::Acceptable; }
void RowPainter::paintTopLevelLabel() const { BufferParams const & bparams = pi_.base.bv->buffer().params(); ParagraphParameters const & pparams = par_.params(); Layout const & layout = par_.layout(); FontInfo const font = labelFont(false); docstring const str = par_.labelString(); if (str.empty()) return; double spacing_val = 1.0; if (!pparams.spacing().isDefault()) spacing_val = pparams.spacing().getValue(); else spacing_val = bparams.spacing().getValue(); FontMetrics const & fm = theFontMetrics(font); int const labeladdon = int(fm.maxHeight() * layout.spacing.getValue() * spacing_val); int maxdesc = int(fm.maxDescent() * layout.spacing.getValue() * spacing_val + (layout.labelbottomsep * defaultRowHeight())); double x = x_; if (layout.labeltype == LABEL_CENTERED) { x += (tm_.width() - row_.left_margin - row_.right_margin) / 2; x -= fm.width(str) / 2; } else if (row_.isRTL()) { x = xo_ + tm_.width() - row_.right_margin - fm.width(str); } pi_.pain.text(int(x), yo_ - maxdesc - labeladdon, str, font); }
FileFilterList::FileFilterList(docstring const & qt_style_filter) { // FIXME UNICODE string const filter = to_utf8(qt_style_filter) + (qt_style_filter.empty() ? string() : ";;") + to_utf8(_("All Files ")) #if defined(_WIN32) + ("(*.*)"); #else + ("(*)"); #endif // Split data such as "TeX documents (*.tex);;LyX Documents (*.lyx)" // into individual filters. static lyx::regex const separator_re(";;"); string::const_iterator it = filter.begin(); string::const_iterator const end = filter.end(); while (true) { match_results<string::const_iterator> what; if (!lyx::regex_search(it, end, what, separator_re)) { parse_filter(string(it, end)); break; } // Everything from the start of the input to // the start of the match. parse_filter(string(what[-1].first, what[-1].second)); // Increment the iterator to the end of the match. it += distance(it, what[0].second); } }
bool TextClass::hasLayout(docstring const & n) const { docstring const name = n.empty() ? defaultLayoutName() : n; return find_if(layoutlist_.begin(), layoutlist_.end(), LayoutNamesEqual(name)) != layoutlist_.end(); }
// FIXME XHTML // There are cases where we may need to close open fonts and such // and then re-open them when we are done. This would be the case, e.g., // if we were otherwise about to write: // <em>word <div class='foot'>footnote text.</div> emph</em> // The problem isn't so much that the footnote text will get emphasized: // we can handle that with CSS. The problem is that this is invalid XHTML. // One solution would be to make the footnote <span>, but the problem is // completely general, and so we'd have to make absolutely everything into // span. What I think will work is to check if we're about to write "div" and, // if so, try to close fonts, etc. // There are probably limits to how well we can do here, though, and we will // have to rely upon users not putting footnotes inside noun-type insets. docstring InsetText::insetAsXHTML(XHTMLStream & xs, OutputParams const & rp, XHTMLOptions opts) const { // we will always want to output all our paragraphs when we are // called this way. OutputParams runparams = rp; runparams.par_begin = 0; runparams.par_end = text().paragraphs().size(); if (undefined()) { xs.startDivision(false); xhtmlParagraphs(text_, buffer(), xs, runparams); xs.endDivision(); return docstring(); } InsetLayout const & il = getLayout(); if (opts & WriteOuterTag) xs << html::StartTag(il.htmltag(), il.htmlattr()); if ((opts & WriteLabel) && !il.counter().empty()) { BufferParams const & bp = buffer().masterBuffer()->params(); Counters & cntrs = bp.documentClass().counters(); cntrs.step(il.counter(), OutputUpdate); // FIXME: translate to paragraph language if (!il.htmllabel().empty()) { docstring const lbl = cntrs.counterLabel(from_utf8(il.htmllabel()), bp.language->code()); // FIXME is this check necessary? if (!lbl.empty()) { xs << html::StartTag(il.htmllabeltag(), il.htmllabelattr()); xs << lbl; xs << html::EndTag(il.htmllabeltag()); } } } if (opts & WriteInnerTag) xs << html::StartTag(il.htmlinnertag(), il.htmlinnerattr()); // we will eventually lose information about the containing inset if (!allowMultiPar() || opts == JustText) runparams.html_make_pars = false; if (il.isPassThru()) runparams.pass_thru = true; xs.startDivision(false); xhtmlParagraphs(text_, buffer(), xs, runparams); xs.endDivision(); if (opts & WriteInnerTag) xs << html::EndTag(il.htmlinnertag()); if (opts & WriteOuterTag) xs << html::EndTag(il.htmltag()); return docstring(); }
void InsetCaption::setCustomLabel(docstring const & label) { if (!isAscii(label) || label.empty()) // This must be a user defined layout. We cannot translate // this, since gettext accepts only ascii keys. custom_label_ = label; else custom_label_ = _(to_ascii(label)); }
vector<docstring> GuiCitation::searchKeys(BiblioInfo const & bi, vector<docstring> const & keys_to_search, bool only_keys, docstring const & search_expression, docstring field, bool case_sensitive, bool regex) { vector<docstring> foundKeys; docstring expr = trim(search_expression); if (expr.empty()) return foundKeys; if (!regex) // We must escape special chars in the search_expr so that // it is treated as a simple string by lyx::regex. expr = escape_special_chars(expr); lyx::regex reg_exp; try { reg_exp.assign(to_utf8(expr), case_sensitive ? lyx::regex_constants::ECMAScript : lyx::regex_constants::icase); } catch (lyx::regex_error const & e) { // lyx::regex throws an exception if the regular expression is not // valid. LYXERR(Debug::GUI, e.what()); return vector<docstring>(); } vector<docstring>::const_iterator it = keys_to_search.begin(); vector<docstring>::const_iterator end = keys_to_search.end(); for (; it != end; ++it ) { BiblioInfo::const_iterator info = bi.find(*it); if (info == bi.end()) continue; BibTeXInfo const & kvm = info->second; string data; if (only_keys) data = to_utf8(*it); else if (field.empty()) data = to_utf8(*it) + ' ' + to_utf8(kvm.allData()); else data = to_utf8(kvm[field]); if (data.empty()) continue; try { if (lyx::regex_search(data, reg_exp)) foundKeys.push_back(*it); } catch (lyx::regex_error const & e) { LYXERR(Debug::GUI, e.what()); return vector<docstring>(); } } return foundKeys; }
void add_known_command(string const & command, string const & o1, bool o2, docstring const & definition) { vector<ArgumentType> arguments; convertArgs(o1, o2, arguments); known_commands[command] = arguments; if (!definition.empty()) possible_textclass_commands[command] = FullCommand(arguments, definition); }
void InsetLayout::makeDefaultCSS() const { if (!htmldefaultstyle_.empty()) return; docstring const mainfontCSS = font_.asCSS(); if (!mainfontCSS.empty()) htmldefaultstyle_ = from_ascii(htmltag() + "." + defaultCSSClass() + " {\n") + mainfontCSS + from_ascii("\n}\n"); }
int GuiFontMetrics::signedWidth(docstring const & s) const { if (s.empty()) return 0; if (s[0] == '-') return -width(s.substr(1, s.size() - 1)); else return width(s); }
string const to_local8bit(docstring const & s) { // This conversion can fail, depending on input. if (s.empty()) return string(); QByteArray const local = toqstr(s).toLocal8Bit(); if (local.isEmpty()) throw to_local8bit_failure(); return string(local.begin(), local.end()); }
bool TextClass::hasInsetLayout(docstring const & n) const { if (n.empty()) return false; InsetLayouts::const_iterator it = insetlayoutlist_.begin(); InsetLayouts::const_iterator en = insetlayoutlist_.end(); for (; it != en; ++it) if (n == it->first) return true; return false; }
pit_type InsetText::openAddToTocForParagraph(pit_type pit, DocIterator const & dit, bool output_active, TocBackend & backend) const { Paragraph const & par = paragraphs()[pit]; TocBuilder & b = backend.builder(par.layout().tocType()); docstring const label = par.labelString(); b.pushItem(dit, label + (label.empty() ? "" : " "), output_active); return text().lastInSequence(pit); }
// the ref argument is the label name we are referencing. // we expect ref to be in the form: pfx:suffix. // // if it isn't, then we can't produce a formatted reference, // so we return "\ref" and put ref into label. // // for refstyle, we return "\pfxcmd", and put suffix into // label and pfx into prefix. this is because refstyle expects // the command: \pfxcmd{suffix}. // // for prettyref, we return "\prettyref" and put ref into label // and pfx into prefix. this is because prettyref uses the whole // label, thus: \prettyref{pfx:suffix}. // docstring InsetRef::getFormattedCmd(docstring const & ref, docstring & label, docstring & prefix) const { static docstring const defcmd = from_ascii("\\ref"); static docstring const prtcmd = from_ascii("\\prettyref"); label = split(ref, prefix, ':'); // we have to have xxx:xxxxx... if (label.empty()) { LYXERR0("Label `" << ref << "' contains no prefix."); label = ref; prefix = from_ascii(""); return defcmd; } if (prefix.empty()) { // we have ":xxxx" label = ref; return defcmd; } if (!buffer().params().use_refstyle) { // \prettyref uses the whole label label = ref; return prtcmd; } // make sure the prefix is legal for a latex command int const len = prefix.size(); for (int i = 0; i < len; i++) { char_type const c = prefix[i]; if (!isAlphaASCII(c)) { LYXERR0("Prefix `" << prefix << "' is invalid for LaTeX."); // restore the label label = ref; return defcmd; } } return from_ascii("\\") + prefix + from_ascii("ref"); }
docstring const translateIfPossible(docstring const & name, std::string const & language) { if (support::isAscii(name) && !name.empty()) // Probably from a standard configuration file, try to // translate return getMessages(language).get(to_ascii(name)); else // This must be from a user defined configuration file. We // cannot translate this, since gettext accepts only ascii // keys. return name; }
void InsetMathDelim::validate(LaTeXFeatures & features) const { InsetMathNest::validate(features); // The delimiters may be used without \left or \right as well. // Therefore they are listed in lib/symbols, and if they have // requirements, we need to add them here. MathWordList const & words = mathedWordList(); MathWordList::const_iterator it = words.find(left_); if (it != words.end()) { docstring const req = it->second.requires; if (!req.empty()) features.require(to_ascii(req)); } it = words.find(right_); if (it != words.end()) { docstring const req = it->second.requires; if (!req.empty()) features.require(to_ascii(req)); } }
void Counters::newCounter(docstring const & newc, docstring const & masterc, docstring const & ls, docstring const & lsa) { if (!masterc.empty() && !hasCounter(masterc)) { lyxerr << "Master counter does not exist: " << to_utf8(masterc) << endl; return; } counterList_[newc] = Counter(masterc, ls, lsa); }
bool IndicesList::rename(docstring const & oldname, docstring const & newname) { if (newname.empty()) return false; if (find_if(list.begin(), list.end(), IndexNamesEqual(newname)) != list.end()) // new name already taken return false; Index * index = find(oldname); if (!index) return false; index->setIndex(newname); return true; }
bool BranchList::rename(docstring const & oldname, docstring const & newname, bool const merge) { if (newname.empty()) return false; if (find_if(list.begin(), list.end(), BranchNamesEqual(newname)) != list.end()) { // new name already taken if (merge) return remove(oldname); return false; } Branch * branch = find(oldname); if (!branch) return false; branch->setBranch(newname); return true; }
void GuiCitation::filterByEntryType(BiblioInfo const & bi, vector<docstring> & keyVector, docstring entry_type) { if (entry_type.empty()) return; vector<docstring>::iterator it = keyVector.begin(); vector<docstring>::iterator end = keyVector.end(); vector<docstring> result; for (; it != end; ++it) { docstring const key = *it; BiblioInfo::const_iterator cit = bi.find(key); if (cit == bi.end()) continue; if (cit->second.entryType() == entry_type) result.push_back(key); } keyVector = result; }
QString Filter::toString() const { QString s; bool const has_description = !desc_.empty(); if (has_description) { s += toqstr(desc_); s += " ("; } for (size_t i = 0; i != globs_.size(); ++i) { if (i > 0) s += ' '; s += toqstr(globs_[i]); } if (has_description) s += ')'; return s; }
void GuiBibtex::applyView() { docstring dbs; int maxCount = selected_bibs_.count(); for (int i = 0; i < maxCount; i++) { if (i != 0) dbs += ','; QString item = selected_bibs_.at(i); docstring bibfile = qstring_to_ucs4(item); dbs += bibfile; } params_["bibfiles"] = dbs; docstring const bibstyle = qstring_to_ucs4(styleCB->currentText()); bool const bibtotoc = bibtocCB->isChecked(); if (bibtotoc && !bibstyle.empty()) { // both bibtotoc and style params_["options"] = "bibtotoc," + bibstyle; } else if (bibtotoc) { // bibtotoc and no style params_["options"] = from_ascii("bibtotoc"); } else { // only style. An empty one is valid, because some // documentclasses have an own \bibliographystyle{} // command! params_["options"] = bibstyle; } params_["biblatexopts"] = qstring_to_ucs4(biblatexOptsLE->text()); params_["btprint"] = qstring_to_ucs4(btPrintCO->itemData(btPrintCO->currentIndex()).toString()); params_["encoding"] = qstring_to_ucs4(bibEncodingCO->itemData(bibEncodingCO->currentIndex()).toString()); if (usingBiblatex()) params_["file_encodings"] = getStringFromVector(getFileEncodings(), from_ascii("\t")); }
bool IndicesList::add(docstring const & n, docstring const & s) { bool added = false; size_t i = 0; while (true) { size_t const j = n.find_first_of(separator_, i); docstring name; if (j == docstring::npos) name = n.substr(i); else name = n.substr(i, j - i); // Is this name already in the list? bool const already = find_if(list.begin(), list.end(), IndexNamesEqual(name)) != list.end(); if (!already) { added = true; Index in; in.setIndex(name); docstring sc = s.empty() ? trim(lowercase(name.substr(0, 3))) : s; if (findShortcut(sc) != 0) { int i = 1; docstring scn = sc + convert<docstring>(i); while (findShortcut(scn) != 0) { ++i; scn = sc + convert<docstring>(i); } in.setShortcut(scn); } else in.setShortcut(sc); list.push_back(in); } if (j == docstring::npos) break; i = j + 1; } return added; }
void LaTeXFeatures::getFloatDefinitions(odocstream & os) const { FloatList const & floats = params_.documentClass().floats(); // Here we will output the code to create the needed float styles. // We will try to do this as minimal as possible. // \floatstyle{ruled} // \newfloat{algorithm}{htbp}{loa} // \providecommand{\algorithmname}{Algorithm} // \floatname{algorithm}{\protect\algorithmname} UsedFloats::const_iterator cit = usedFloats_.begin(); UsedFloats::const_iterator end = usedFloats_.end(); for (; cit != end; ++cit) { Floating const & fl = floats.getType(cit->first); // For builtin floats we do nothing. if (!fl.needsFloatPkg()) continue; // We have to special case "table" and "figure" if (fl.floattype() == "tabular" || fl.floattype() == "figure") { // Output code to modify "table" or "figure" // but only if builtin == false // and that have to be true at this point in the // function. docstring const type = from_ascii(fl.floattype()); docstring const placement = from_ascii(fl.placement()); docstring const style = from_ascii(fl.style()); if (!style.empty()) { os << "\\floatstyle{" << style << "}\n" << "\\restylefloat{" << type << "}\n"; } if (!placement.empty()) { os << "\\floatplacement{" << type << "}{" << placement << "}\n"; } } else { // The other non builtin floats. docstring const type = from_ascii(fl.floattype()); docstring const placement = from_ascii(fl.placement()); docstring const ext = from_ascii(fl.ext()); docstring const within = from_ascii(fl.within()); docstring const style = from_ascii(fl.style()); docstring const name = translateIfPossible( from_utf8(fl.name()), buffer().language()->code()); os << "\\floatstyle{" << style << "}\n" << "\\newfloat{" << type << "}{" << placement << "}{" << ext << '}'; if (!within.empty()) os << '[' << within << ']'; os << '\n' << "\\providecommand{\\" << type << "name}{" << name << "}\n" << "\\floatname{" << type << "}{\\protect\\" << type << "name}\n"; // What missing here is to code to minimalize the code // output so that the same floatstyle will not be // used several times, when the same style is still in // effect. (Lgb) } if (cit->second) os << "\n\\newsubfloat{" << from_ascii(fl.floattype()) << "}\n"; } }
void InsetListings::latex(otexstream & os, OutputParams const & runparams) const { string param_string = params().params(); // NOTE: I use {} to quote text, which is an experimental feature // of the listings package (see page 25 of the manual) bool const isInline = params().isInline(); // get the paragraphs. We can not output them directly to given odocstream // because we can not yet determine the delimiter character of \lstinline docstring code; docstring uncodable; ParagraphList::const_iterator par = paragraphs().begin(); ParagraphList::const_iterator end = paragraphs().end(); bool encoding_switched = false; Encoding const * const save_enc = runparams.encoding; if (!runparams.isFullUnicode() && !runparams.encoding->hasFixedWidth()) { // We need to switch to a singlebyte encoding, since the // listings package cannot deal with multi-byte-encoded // glyphs (not needed with full-unicode aware backends // such as XeTeX). Language const * const outer_language = (runparams.local_font != 0) ? runparams.local_font->language() : buffer().params().language; // We try if there's a singlebyte encoding for the current // language; if not, fall back to latin1. Encoding const * const lstenc = (outer_language->encoding()->hasFixedWidth()) ? outer_language->encoding() : encodings.fromLyXName("iso8859-1"); switchEncoding(os.os(), buffer().params(), runparams, *lstenc, true); runparams.encoding = lstenc; encoding_switched = true; } while (par != end) { pos_type siz = par->size(); bool captionline = false; for (pos_type i = 0; i < siz; ++i) { if (i == 0 && par->isInset(i) && i + 1 == siz) captionline = true; // ignore all struck out text and (caption) insets if (par->isDeleted(i) || par->isInset(i)) continue; char_type c = par->getChar(i); // we can only output characters covered by the current // encoding! try { if (runparams.encoding->encodable(c)) code += c; else if (runparams.dryrun) { code += "<" + _("LyX Warning: ") + _("uncodable character") + " '"; code += docstring(1, c); code += "'>"; } else uncodable += c; } catch (EncodingException & /* e */) { if (runparams.dryrun) { code += "<" + _("LyX Warning: ") + _("uncodable character") + " '"; code += docstring(1, c); code += "'>"; } else uncodable += c; } } ++par; // for the inline case, if there are multiple paragraphs // they are simply joined. Otherwise, expect latex errors. if (par != end && !isInline && !captionline) code += "\n"; } if (isInline) { char const * delimiter = lstinline_delimiters; for (; delimiter != '\0'; ++delimiter) if (!contains(code, *delimiter)) break; // This code piece contains all possible special character? !!! // Replace ! with a warning message and use ! as delimiter. if (*delimiter == '\0') { docstring delim_error = "<" + _("LyX Warning: ") + _("no more lstline delimiters available") + ">"; code = subst(code, from_ascii("!"), delim_error); delimiter = lstinline_delimiters; if (!runparams.dryrun) { // FIXME: warning should be passed to the error dialog frontend::Alert::warning(_("Running out of delimiters"), _("For inline program listings, one character must be reserved\n" "as a delimiter. One of the listings, however, uses all available\n" "characters, so none is left for delimiting purposes.\n" "For the time being, I have replaced '!' by a warning, but you\n" "must investigate!")); } } if (param_string.empty()) os << "\\lstinline" << *delimiter; else os << "\\lstinline[" << from_utf8(param_string) << "]" << *delimiter; os << code << *delimiter; } else { OutputParams rp = runparams; rp.moving_arg = true; docstring const caption = getCaption(rp); if (param_string.empty() && caption.empty()) os << breakln << "\\begin{lstlisting}\n"; else { os << breakln << "\\begin{lstlisting}["; if (!caption.empty()) { os << "caption={" << caption << '}'; if (!param_string.empty()) os << ','; } os << from_utf8(param_string) << "]\n"; } os << code << breakln << "\\end{lstlisting}\n"; } if (encoding_switched){ // Switch back switchEncoding(os.os(), buffer().params(), runparams, *save_enc, true); runparams.encoding = save_enc; } if (!uncodable.empty()) { // issue a warning about omitted characters // FIXME: should be passed to the error dialog frontend::Alert::warning(_("Uncodable characters in listings inset"), bformat(_("The following characters in one of the program listings are\n" "not representable in the current encoding and have been omitted:\n%1$s."), uncodable)); } }
string const write_attribute(string const & name, docstring const & t) { return t.empty() ? string() : " " + name + "=\"" + to_utf8(t) + "\""; }
void writePlaintextParagraph(Buffer const & buf, Paragraph const & par, odocstream & os, OutputParams const & runparams, bool & ref_printed) { int ltype = 0; depth_type ltype_depth = 0; depth_type depth = par.params().depth(); // First write the layout string const tmp = to_utf8(par.layout().name()); if (compare_ascii_no_case(tmp, "itemize") == 0) { ltype = 1; ltype_depth = depth + 1; } else if (compare_ascii_no_case(tmp, "enumerate") == 0) { ltype = 2; ltype_depth = depth + 1; } else if (contains(ascii_lowercase(tmp), "ection")) { ltype = 3; ltype_depth = depth + 1; } else if (contains(ascii_lowercase(tmp), "aragraph")) { ltype = 4; ltype_depth = depth + 1; } else if (compare_ascii_no_case(tmp, "description") == 0) { ltype = 5; ltype_depth = depth + 1; } else if (compare_ascii_no_case(tmp, "abstract") == 0) { ltype = 6; ltype_depth = 0; } else if (compare_ascii_no_case(tmp, "bibliography") == 0) { ltype = 7; ltype_depth = 0; } else { ltype = 0; ltype_depth = 0; } /* the labelwidthstring used in lists */ /* noindent ? */ /* what about the alignment */ // runparams.linelen == 0 is special and means we don't have paragraph breaks string::size_type currlinelen = 0; os << docstring(depth * 2, ' '); currlinelen += depth * 2; //-- // we should probably change to the paragraph language in the // support/gettext.here (if possible) so that strings are output in // the correct language! (20012712 Jug) //-- switch (ltype) { case 0: // Standard case 4: // (Sub)Paragraph case 5: // Description break; case 6: // Abstract if (runparams.linelen > 0) { os << buf.B_("Abstract") << "\n\n"; currlinelen = 0; } else { docstring const abst = buf.B_("Abstract: "); os << abst; currlinelen += abst.length(); } break; case 7: // Bibliography if (!ref_printed) { if (runparams.linelen > 0) { os << buf.B_("References") << "\n\n"; currlinelen = 0; } else { docstring const refs = buf.B_("References: "); os << refs; currlinelen += refs.length(); } ref_printed = true; } break; default: { docstring const label = par.params().labelString(); if (!label.empty()) { os << label << ' '; currlinelen += label.length() + 1; } break; } } if (currlinelen == 0) { pair<int, docstring> p = addDepth(depth, ltype_depth); os << p.second; currlinelen += p.first; } docstring word; for (pos_type i = 0; i < par.size(); ++i) { // deleted characters don't make much sense in plain text output if (par.isDeleted(i)) continue; char_type c = par.getUChar(buf.params(), i); if (par.isInset(i) || c == ' ') { if (runparams.linelen > 0 && currlinelen + word.length() > runparams.linelen) { os << '\n'; pair<int, docstring> p = addDepth(depth, ltype_depth); os << p.second; currlinelen = p.first; } os << word; currlinelen += word.length(); word.erase(); } if (par.isInset(i)) { OutputParams rp = runparams; rp.depth = par.params().depth(); int len = par.getInset(i)->plaintext(os, rp); if (len >= Inset::PLAINTEXT_NEWLINE) currlinelen = len - Inset::PLAINTEXT_NEWLINE; else currlinelen += len; continue; } switch (c) { case ' ': os << ' '; currlinelen++; break; case '\0': LYXERR(Debug::INFO, "writePlaintextFile: NUL char in structure."); break; default: word += c; break; } } // currlinelen may be greater than runparams.linelen! // => check whether word is empty and do nothing in this case if (!word.empty()) { if (runparams.linelen > 0 && currlinelen + word.length() > runparams.linelen) { os << '\n'; pair<int, docstring> p = addDepth(depth, ltype_depth); os << p.second; currlinelen = p.first; } os << word; } }