Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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");
	}
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
	}
}
Ejemplo n.º 7
0
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();
}
Ejemplo n.º 8
0
// 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();
}
Ejemplo n.º 9
0
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));
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
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");
}
Ejemplo n.º 13
0
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);
}
Ejemplo n.º 14
0
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());
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
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);
}
Ejemplo n.º 17
0
// 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");
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
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));
	}
}
Ejemplo n.º 20
0
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);
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
0
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;
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 25
0
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"));
}
Ejemplo n.º 26
0
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;
}
Ejemplo n.º 27
0
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";
	}
}
Ejemplo n.º 28
0
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));
	}
}
Ejemplo n.º 29
0
string const write_attribute(string const & name, docstring const & t)
{
    return t.empty() ? string() : " " + name + "=\"" + to_utf8(t) + "\"";
}
Ejemplo n.º 30
0
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;
    }
}