X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetNomencl.cpp;h=05a5dea8cda6aaeda27c6c9072faee405cc02a4f;hb=938c44590cb643029ce47694edf7ab3949a800a2;hp=dec08854d2877a7e4707ef5e548e51753045ba05;hpb=9d0ea8aeff32833a90b3fe64df0c5518a9e241be;p=lyx.git diff --git a/src/insets/InsetNomencl.cpp b/src/insets/InsetNomencl.cpp index dec08854d2..05a5dea8cd 100644 --- a/src/insets/InsetNomencl.cpp +++ b/src/insets/InsetNomencl.cpp @@ -3,8 +3,10 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author O. U. Baran + * \author Uwe Stöhr + * \author Jürgen Spitzmüller * * Full author contact details are available in file CREDITS. */ @@ -14,45 +16,96 @@ #include "InsetNote.h" #include "Buffer.h" +#include "Cursor.h" #include "DispatchResult.h" +#include "Font.h" +#include "Encoding.h" #include "FuncRequest.h" -#include "support/gettext.h" +#include "FuncStatus.h" #include "InsetIterator.h" +#include "InsetList.h" +#include "Language.h" #include "LaTeXFeatures.h" -#include "MetricsInfo.h" +#include "Length.h" +#include "LyX.h" +#include "OutputParams.h" +#include "output_xhtml.h" #include "sgml.h" +#include "texstream.h" +#include "TocBackend.h" + +#include "frontends/FontMetrics.h" +#include "support/debug.h" #include "support/docstream.h" +#include "support/gettext.h" +#include "support/lstrings.h" +using namespace std; +using namespace lyx::support; namespace lyx { -using std::string; +///////////////////////////////////////////////////////////////////// +// +// InsetNomencl +// +///////////////////////////////////////////////////////////////////// -InsetNomencl::InsetNomencl(InsetCommandParams const & p) - : InsetCommand(p, "nomenclature"), +InsetNomencl::InsetNomencl(Buffer * buf, InsetCommandParams const & p) + : InsetCommand(buf, p), nomenclature_entry_id(sgml::uniqueID(from_ascii("nomen"))) {} -CommandInfo const * InsetNomencl::findInfo(std::string const & /* cmdName */) +ParamInfo const & InsetNomencl::findInfo(string const & /* cmdName */) { - static const char * const paramnames[] = {"prefix", "symbol", "description", ""}; - static const bool isoptional[] = {true, false, false}; - static const CommandInfo info = {3, paramnames, isoptional}; - return &info; + static ParamInfo param_info_; + if (param_info_.empty()) { + param_info_.add("prefix", ParamInfo::LATEX_OPTIONAL); + param_info_.add("symbol", ParamInfo::LATEX_REQUIRED, + ParamInfo::ParamHandling(ParamInfo::HANDLING_LATEXIFY + | ParamInfo::HANDLING_INDEX_ESCAPE)); + param_info_.add("description", ParamInfo::LATEX_REQUIRED, + ParamInfo::ParamHandling(ParamInfo::HANDLING_LATEXIFY + | ParamInfo::HANDLING_INDEX_ESCAPE)); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); + } + return param_info_; } -docstring const InsetNomencl::getScreenLabel(Buffer const &) const +docstring InsetNomencl::screenLabel() const { - return _("Nom"); + size_t const maxLabelChars = 25; + docstring label = _("Nom: ") + getParam("symbol"); + support::truncateWithEllipsis(label, maxLabelChars); + return label; } -int InsetNomencl::docbook(Buffer const &, odocstream & os, - OutputParams const &) const +docstring InsetNomencl::toolTip(BufferView const & /*bv*/, int /*x*/, int /*y*/) const +{ + docstring tip = _("Nomenclature Symbol: ") + getParam("symbol") + "\n"; + tip += _("Description: ") + "\t" + + subst(getParam("description"), from_ascii("\\\\"), from_ascii("\n\t")); + if (!getParam("prefix").empty()) + tip += "\n" + _("Sorting: ") + getParam("prefix"); + return tip; +} + + +int InsetNomencl::plaintext(odocstringstream & os, + OutputParams const &, size_t) const +{ + docstring s = "[" + getParam("symbol") + ": " + getParam("description") + "]"; + os << s; + return s.size(); +} + + +int InsetNomencl::docbook(odocstream & os, OutputParams const &) const { os << "" << sgml::escapeString(getParam("symbol")) @@ -61,6 +114,12 @@ int InsetNomencl::docbook(Buffer const &, odocstream & os, } +docstring InsetNomencl::xhtml(XHTMLStream &, OutputParams const &) const +{ + return docstring(); +} + + int InsetNomencl::docbookGlossary(odocstream & os) const { os << "\n" @@ -78,41 +137,198 @@ int InsetNomencl::docbookGlossary(odocstream & os) const void InsetNomencl::validate(LaTeXFeatures & features) const { features.require("nomencl"); + InsetCommand::validate(features); +} + + +void InsetNomencl::addToToc(DocIterator const & cpit, bool output_active, + UpdateType, TocBackend & backend) const +{ + docstring const str = getParam("symbol"); + TocBuilder & b = backend.builder("nomencl"); + b.pushItem(cpit, str, output_active); + b.pop(); } -InsetPrintNomencl::InsetPrintNomencl(InsetCommandParams const & p) - : InsetCommand(p, string()) +///////////////////////////////////////////////////////////////////// +// +// InsetPrintNomencl +// +///////////////////////////////////////////////////////////////////// + +InsetPrintNomencl::InsetPrintNomencl(Buffer * buf, InsetCommandParams const & p) + : InsetCommand(buf, p) {} -CommandInfo const * InsetPrintNomencl::findInfo(std::string const & /* cmdName */) +ParamInfo const & InsetPrintNomencl::findInfo(string const & /* cmdName */) { - static const char * const paramnames[] = {"labelwidth", ""}; - static const bool isoptional[] = {true}; - static const CommandInfo info = {1, paramnames, isoptional}; - return &info; + // The symbol width is set via nomencl's \nomlabelwidth in + // InsetPrintNomencl::latex and not as optional parameter of + // \printnomenclature + static ParamInfo param_info_; + if (param_info_.empty()) { + // how is the width set? + // values: none|auto|custom + param_info_.add("set_width", ParamInfo::LYX_INTERNAL); + // custom width + param_info_.add("width", ParamInfo::LYX_INTERNAL); + } + return param_info_; } -docstring const InsetPrintNomencl::getScreenLabel(Buffer const &) const +docstring InsetPrintNomencl::screenLabel() const { return _("Nomenclature"); } -int InsetPrintNomencl::docbook(Buffer const & buf, odocstream & os, - OutputParams const &) const +struct NomenclEntry { + NomenclEntry() : par(0) {} + NomenclEntry(docstring s, docstring d, Paragraph const * p) + : symbol(s), desc(d), par(p) + {} + + docstring symbol; + docstring desc; + Paragraph const * par; +}; + + +typedef map EntryMap; + + +docstring InsetPrintNomencl::xhtml(XHTMLStream &, OutputParams const & op) const +{ + shared_ptr toc = buffer().tocBackend().toc("nomencl"); + + EntryMap entries; + Toc::const_iterator it = toc->begin(); + Toc::const_iterator const en = toc->end(); + for (; it != en; ++it) { + DocIterator dit = it->dit(); + Paragraph const & par = dit.innerParagraph(); + Inset const * inset = par.getInset(dit.top().pos()); + if (!inset) + return docstring(); + InsetCommand const * ic = inset->asInsetCommand(); + if (!ic) + return docstring(); + + // FIXME We need a link to the paragraph here, so we + // need some kind of struct. + docstring const symbol = ic->getParam("symbol"); + docstring const desc = ic->getParam("description"); + docstring const prefix = ic->getParam("prefix"); + docstring const sortas = prefix.empty() ? symbol : prefix; + + entries[sortas] = NomenclEntry(symbol, desc, &par); + } + + if (entries.empty()) + return docstring(); + + // we'll use our own stream, because we are going to defer everything. + // that's how we deal with the fact that we're probably inside a standard + // paragraph, and we don't want to be. + odocstringstream ods; + XHTMLStream xs(ods); + + InsetLayout const & il = getLayout(); + string const & tag = il.htmltag(); + docstring toclabel = translateIfPossible(from_ascii("Nomenclature"), + op.local_font->language()->lang()); + + xs << html::StartTag("div", "class='nomencl'") + << html::StartTag(tag, "class='nomencl'") + << toclabel + << html::EndTag(tag) + << html::CR() + << html::StartTag("dl") + << html::CR(); + + EntryMap::const_iterator eit = entries.begin(); + EntryMap::const_iterator const een = entries.end(); + for (; eit != een; ++eit) { + NomenclEntry const & ne = eit->second; + string const parid = ne.par->magicLabel(); + xs << html::StartTag("dt") + << html::StartTag("a", "href='#" + parid + "' class='nomencl'") + << ne.symbol + << html::EndTag("a") + << html::EndTag("dt") + << html::CR() + << html::StartTag("dd") + << ne.desc + << html::EndTag("dd") + << html::CR(); + } + + xs << html::EndTag("dl") + << html::CR() + << html::EndTag("div") + << html::CR(); + + return ods.str(); +} + + +void InsetPrintNomencl::doDispatch(Cursor & cur, FuncRequest & cmd) +{ + switch (cmd.action()) { + + case LFUN_INSET_MODIFY: { + InsetCommandParams p(NOMENCL_PRINT_CODE); + // FIXME UNICODE + InsetCommand::string2params(to_utf8(cmd.argument()), p); + if (p.getCmdName().empty()) { + cur.noScreenUpdate(); + break; + } + + cur.recordUndo(); + setParams(p); + break; + } + + default: + InsetCommand::doDispatch(cur, cmd); + break; + } +} + + +bool InsetPrintNomencl::getStatus(Cursor & cur, FuncRequest const & cmd, + FuncStatus & status) const +{ + switch (cmd.action()) { + + case LFUN_INSET_DIALOG_UPDATE: + case LFUN_INSET_MODIFY: + status.setEnabled(true); + return true; + + default: + return InsetCommand::getStatus(cur, cmd, status); + } +} + + +// FIXME This should be changed to use the TOC. Perhaps +// that could be done when XHTML output is added. +int InsetPrintNomencl::docbook(odocstream & os, OutputParams const &) const { os << "\n"; int newlines = 2; - for (InsetIterator it = inset_iterator_begin(buf.inset()); it;) { + InsetIterator it = inset_iterator_begin(buffer().inset()); + while (it) { if (it->lyxCode() == NOMENCL_CODE) { newlines += static_cast(*it).docbookGlossary(os); ++it; - } else if(it->lyxCode() == NOTE_CODE && - static_cast(*it).params().type == InsetNoteParams::Note) { - // Don't output anything nested in note insets + } else if (!it->producesOutput()) { + // Ignore contents of insets that are not in output size_t const depth = it.depth(); ++it; while (it.depth() > depth) @@ -126,8 +342,89 @@ int InsetPrintNomencl::docbook(Buffer const & buf, odocstream & os, } +namespace { +docstring nomenclWidest(Buffer const & buffer, OutputParams const & runparams) +{ + // nomenclWidest() determines and returns the widest used + // nomenclature symbol in the document + + int w = 0; + docstring symb; + InsetNomencl const * nomencl = 0; + ParagraphList::const_iterator it = buffer.paragraphs().begin(); + ParagraphList::const_iterator end = buffer.paragraphs().end(); + + for (; it != end; ++it) { + if (it->insetList().empty()) + continue; + InsetList::const_iterator iit = it->insetList().begin(); + InsetList::const_iterator eend = it->insetList().end(); + for (; iit != eend; ++iit) { + Inset * inset = iit->inset; + if (inset->lyxCode() != NOMENCL_CODE) + continue; + nomencl = static_cast(inset); + docstring const symbol = + nomencl->getParam("symbol"); + // This is only an approximation, + // but the best we can get. + int const wx = use_gui ? + theFontMetrics(Font()).width(symbol) : + symbol.size(); + if (wx > w) { + w = wx; + symb = symbol; + } + } + } + // return the widest (or an empty) string + if (symb.empty()) + return symb; + + // we have to encode the string properly + pair latex_symb = + runparams.encoding->latexString(symb, runparams.dryrun); + if (!latex_symb.second.empty()) + LYXERR0("Omitting uncodable characters '" + << latex_symb.second + << "' in nomencl widest string!"); + return latex_symb.first; +} +} // namespace + + +void InsetPrintNomencl::latex(otexstream & os, OutputParams const & runparams_in) const +{ + OutputParams runparams = runparams_in; + if (getParam("set_width") == "auto") { + docstring widest = nomenclWidest(buffer(), runparams); + // Set the label width via nomencl's command \nomlabelwidth. + // This must be output before the command \printnomenclature + if (!widest.empty()) { + os << "\\settowidth{\\nomlabelwidth}{" + << widest + << "}\n"; + } + } else if (getParam("set_width") == "custom") { + // custom length as optional arg of \printnomenclature + string const width = + Length(to_ascii(getParam("width"))).asLatexString(); + os << '\\' + << from_ascii(getCmdName()) + << '[' + << from_ascii(width) + << "]" + << termcmd; + return; + } + // output the command \printnomenclature + os << getCommand(runparams); +} + + void InsetPrintNomencl::validate(LaTeXFeatures & features) const { + features.useInsetLayout(getLayout()); features.require("nomencl"); } @@ -138,4 +435,10 @@ InsetCode InsetPrintNomencl::lyxCode() const } +string InsetPrintNomencl::contextMenuName() const +{ + return "context-nomenclprint"; +} + + } // namespace lyx