New counter manipulation inset.

This inset allows counters to be set, reset, saved, restored, etc,
both in the LyX GUI and in the output; optionally, the effect can be
limited to the GUI. Of course, LaTeX provides means for doing all of
these things, so they could previously be done with ERT, as far as
the output is concerned. But there was no mechanism for manipulating
counters in the GUI and none for other output formats.
This commit is contained in:
Richard Kimberly Heck 2020-04-30 21:56:58 -04:00
parent db5021c42e
commit 684d27c0fb
13 changed files with 640 additions and 121 deletions

View File

@ -18,6 +18,7 @@
#include "Lexer.h" #include "Lexer.h"
#include "support/convert.h" #include "support/convert.h"
#include "support/counter_reps.h"
#include "support/debug.h" #include "support/debug.h"
#include "support/gettext.h" #include "support/gettext.h"
#include "support/lassert.h" #include "support/lassert.h"
@ -143,6 +144,18 @@ int Counter::value() const
} }
void Counter::saveValue()
{
saved_value_ = value_;
}
void Counter::restoreValue()
{
value_ = saved_value_;
}
void Counter::step() void Counter::step()
{ {
++value_; ++value_;
@ -265,6 +278,34 @@ int Counters::value(docstring const & ctr) const
} }
void Counters::saveValue(docstring const & ctr) const
{
CounterList::const_iterator const cit = counterList_.find(ctr);
if (cit == counterList_.end()) {
lyxerr << "value: Counter does not exist: "
<< to_utf8(ctr) << endl;
return;
}
Counter const & cnt = cit->second;
Counter & ccnt = const_cast<Counter &>(cnt);
ccnt.saveValue();
}
void Counters::restoreValue(docstring const & ctr) const
{
CounterList::const_iterator const cit = counterList_.find(ctr);
if (cit == counterList_.end()) {
lyxerr << "value: Counter does not exist: "
<< to_utf8(ctr) << endl;
return;
}
Counter const & cnt = cit->second;
Counter & ccnt = const_cast<Counter &>(cnt);
ccnt.restoreValue();
}
void Counters::resetSlaves(docstring const & count) void Counters::resetSlaves(docstring const & count)
{ {
for (auto & ctr : counterList_) { for (auto & ctr : counterList_) {
@ -357,124 +398,6 @@ void Counters::copy(Counters & from, Counters & to, docstring const & match)
} }
namespace {
char loweralphaCounter(int const n)
{
if (n < 1 || n > 26)
return '?';
return 'a' + n - 1;
}
char alphaCounter(int const n)
{
if (n < 1 || n > 26)
return '?';
return 'A' + n - 1;
}
char hebrewCounter(int const n)
{
static const char hebrew[22] = {
'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8',
'\xe9', '\xeb', '\xec', '\xee', '\xf0', '\xf1', '\xf2', '\xf4', '\xf6',
'\xf7', '\xf8', '\xf9', '\xfa'
};
if (n < 1 || n > 22)
return '?';
return hebrew[n - 1];
}
// On the special cases, see http://mathworld.wolfram.com/RomanNumerals.html
// and for a list of roman numerals up to and including 3999, see
// http://www.research.att.com/~njas/sequences/a006968.txt. (Thanks to Joost
// for this info.)
docstring const romanCounter(int const n)
{
static char const * const ones[9] = {
"I", "II", "III", "IV", "V",
"VI", "VII", "VIII", "IX"
};
static char const * const tens[9] = {
"X", "XX", "XXX", "XL", "L",
"LX", "LXX", "LXXX", "XC"
};
static char const * const hunds[9] = {
"C", "CC", "CCC", "CD", "D",
"DC", "DCC", "DCCC", "CM"
};
if (n >= 1000 || n < 1)
return from_ascii("??");
int val = n;
string roman;
switch (n) {
//special cases
case 900:
roman = "CM";
break;
case 400:
roman = "CD";
break;
default:
if (val >= 100) {
int hundreds = val / 100;
roman = hunds[hundreds - 1];
val = val % 100;
}
if (val >= 10) {
switch (val) {
//special case
case 90:
roman = roman + "XC";
val = 0; //skip next
break;
default:
int tensnum = val / 10;
roman = roman + tens[tensnum - 1];
val = val % 10;
} // end switch
} // end tens
if (val > 0)
roman = roman + ones[val -1];
}
return from_ascii(roman);
}
docstring const lowerromanCounter(int const n)
{
return lowercase(romanCounter(n));
}
docstring const fnsymbolCounter(int const n)
{
switch(n) {
case 1: return docstring(1, 0x002a); //*
case 2: return docstring(1, 0x2020); // dagger
case 3: return docstring(1, 0x2021); // double dagger
case 4: return docstring(1, 0x00A7); // section sign
case 5: return docstring(1, 0x00B6); // pilcrow sign
case 6: return docstring(1, 0x2016); // vertical bar
case 7: return docstring(2, 0x002a); // two *
case 8: return docstring(2, 0x2020); // two daggers
case 9: return docstring(2, 0x2021); // two double daggers
default:
return from_ascii("?");
};
}
} // namespace
docstring Counters::labelItem(docstring const & ctr, docstring Counters::labelItem(docstring const & ctr,
docstring const & numbertype) const docstring const & numbertype) const
{ {
@ -687,4 +610,12 @@ void Counters::endEnvironment()
} }
vector<docstring> Counters::listOfCounters() const {
vector<docstring> ret;
for(auto const & k : counterList_)
ret.emplace_back(k.first);
return ret;
}
} // namespace lyx } // namespace lyx

View File

@ -45,6 +45,10 @@ public:
/// ///
int value() const; int value() const;
/// ///
void saveValue();
///
void restoreValue();
///
void step(); void step();
/// ///
void reset(); void reset();
@ -79,6 +83,8 @@ private:
/// This is actually one less than the initial value, since the /// This is actually one less than the initial value, since the
/// counter is always stepped before being used. /// counter is always stepped before being used.
int initial_value_; int initial_value_;
///
int saved_value_;
/// contains master counter name. /// contains master counter name.
/** The master counter is the counter that, if stepped /** The master counter is the counter that, if stepped
* (incremented) zeroes this counter. E.g. "subsection"'s * (incremented) zeroes this counter. E.g. "subsection"'s
@ -128,6 +134,10 @@ public:
void addto(docstring const & ctr, int val); void addto(docstring const & ctr, int val);
/// ///
int value(docstring const & ctr) const; int value(docstring const & ctr) const;
///
void saveValue(docstring const & ctr) const;
///
void restoreValue(docstring const & ctr) const;
/// Reset recursively all the counters that are slaves of the one named by \c ctr. /// Reset recursively all the counters that are slaves of the one named by \c ctr.
void resetSlaves(docstring const & ctr); void resetSlaves(docstring const & ctr);
/// Increment by one master of counter named by \c ctr. /// Increment by one master of counter named by \c ctr.
@ -202,6 +212,8 @@ public:
/// ///
void restoreLastCounter() { counter_stack_.pop_back(); } void restoreLastCounter() { counter_stack_.pop_back(); }
// @} // @}
///
std::vector<docstring> listOfCounters() const;
private: private:
/** expands recursively any \\the<counter> macro in the /** expands recursively any \\the<counter> macro in the
* labelstring of \c counter. The \c lang code is used to * labelstring of \c counter. The \c lang code is used to

View File

@ -555,6 +555,7 @@ SOURCEFILESINSETS = \
insets/InsetCollapsible.cpp \ insets/InsetCollapsible.cpp \
insets/InsetCommand.cpp \ insets/InsetCommand.cpp \
insets/InsetCommandParams.cpp \ insets/InsetCommandParams.cpp \
insets/InsetCounter.cpp \
insets/InsetERT.cpp \ insets/InsetERT.cpp \
insets/InsetExternal.cpp \ insets/InsetExternal.cpp \
insets/InsetFlex.cpp \ insets/InsetFlex.cpp \
@ -615,6 +616,7 @@ HEADERFILESINSETS = \
insets/InsetCollapsible.h \ insets/InsetCollapsible.h \
insets/InsetCommand.h \ insets/InsetCommand.h \
insets/InsetCommandParams.h \ insets/InsetCommandParams.h \
insets/InsetCounter.h \
insets/InsetERT.h \ insets/InsetERT.h \
insets/InsetExternal.h \ insets/InsetExternal.h \
insets/InsetFlex.h \ insets/InsetFlex.h \

View File

@ -26,6 +26,7 @@
#include "insets/InsetBranch.h" #include "insets/InsetBranch.h"
#include "insets/InsetCaption.h" #include "insets/InsetCaption.h"
#include "insets/InsetCitation.h" #include "insets/InsetCitation.h"
#include "insets/InsetCounter.h"
#include "insets/InsetFlex.h" #include "insets/InsetFlex.h"
#include "insets/InsetERT.h" #include "insets/InsetERT.h"
#include "insets/InsetListings.h" #include "insets/InsetListings.h"
@ -301,6 +302,12 @@ Inset * createInsetHelper(Buffer * buf, FuncRequest const & cmd)
return new InsetCitation(buf, icp); return new InsetCitation(buf, icp);
} }
case COUNTER_CODE: {
InsetCommandParams icp(code);
InsetCommand::string2params(to_utf8(cmd.argument()), icp);
return new InsetCounter(buf, icp);
}
case ERT_CODE: { case ERT_CODE: {
return new InsetERT(buf, return new InsetERT(buf,
InsetERT::string2params(to_utf8(cmd.argument()))); InsetERT::string2params(to_utf8(cmd.argument())));
@ -551,6 +558,9 @@ Inset * readInset(Lexer & lex, Buffer * buf)
case CITE_CODE: case CITE_CODE:
inset.reset(new InsetCitation(buf, inscmd)); inset.reset(new InsetCitation(buf, inscmd));
break; break;
case COUNTER_CODE:
inset.reset(new InsetCounter(buf, inscmd));
break;
case HYPERLINK_CODE: case HYPERLINK_CODE:
inset.reset(new InsetHyperlink(buf, inscmd)); inset.reset(new InsetHyperlink(buf, inscmd));
break; break;

View File

@ -74,6 +74,7 @@ static void build_translator()
insetnames[TOC_CODE] = InsetName("toc"); insetnames[TOC_CODE] = InsetName("toc");
insetnames[QUOTE_CODE] = InsetName("quote"); insetnames[QUOTE_CODE] = InsetName("quote");
insetnames[REF_CODE] = InsetName("ref"); insetnames[REF_CODE] = InsetName("ref");
insetnames[COUNTER_CODE] = InsetName("counter");
insetnames[HYPERLINK_CODE] = InsetName("href"); insetnames[HYPERLINK_CODE] = InsetName("href");
insetnames[SEPARATOR_CODE] = InsetName("separator"); insetnames[SEPARATOR_CODE] = InsetName("separator");
insetnames[ENDING_CODE] = InsetName("ending"); insetnames[ENDING_CODE] = InsetName("ending");

View File

@ -237,6 +237,8 @@ enum InsetCode {
/// ///
MATH_CLASS_CODE, MATH_CLASS_CODE,
/// ///
COUNTER_CODE,
///
INSET_CODE_SIZE INSET_CODE_SIZE
}; };

View File

@ -346,7 +346,8 @@ bool decodeInsetParam(string const & name, string & data,
case NOMENCL_PRINT_CODE: case NOMENCL_PRINT_CODE:
case REF_CODE: case REF_CODE:
case TOC_CODE: case TOC_CODE:
case HYPERLINK_CODE: { case HYPERLINK_CODE:
case COUNTER_CODE: {
InsetCommandParams p(code); InsetCommandParams p(code);
data = InsetCommand::params2string(p); data = InsetCommand::params2string(p);
break; break;

View File

@ -20,6 +20,7 @@
#include "InsetBibitem.h" #include "InsetBibitem.h"
#include "InsetBibtex.h" #include "InsetBibtex.h"
#include "InsetCitation.h" #include "InsetCitation.h"
#include "InsetCounter.h"
#include "InsetFloatList.h" #include "InsetFloatList.h"
#include "InsetHyperlink.h" #include "InsetHyperlink.h"
#include "InsetInclude.h" #include "InsetInclude.h"
@ -63,6 +64,8 @@ static ParamInfo const & findInfo(InsetCode code, string const & cmdName)
return InsetBibtex::findInfo(cmdName); return InsetBibtex::findInfo(cmdName);
case CITE_CODE: case CITE_CODE:
return InsetCitation::findInfo(cmdName); return InsetCitation::findInfo(cmdName);
case COUNTER_CODE:
return InsetCounter::findInfo(cmdName);
case FLOAT_LIST_CODE: case FLOAT_LIST_CODE:
return InsetFloatList::findInfo(cmdName); return InsetFloatList::findInfo(cmdName);
case HYPERLINK_CODE: case HYPERLINK_CODE:
@ -201,6 +204,8 @@ string InsetCommandParams::getDefaultCmd(InsetCode code)
return InsetBibtex::defaultCommand(); return InsetBibtex::defaultCommand();
case CITE_CODE: case CITE_CODE:
return InsetCitation::defaultCommand(); return InsetCitation::defaultCommand();
case COUNTER_CODE:
return InsetCounter::defaultCommand();
case FLOAT_LIST_CODE: case FLOAT_LIST_CODE:
return InsetFloatList::defaultCommand(); return InsetFloatList::defaultCommand();
case HYPERLINK_CODE: case HYPERLINK_CODE:
@ -238,6 +243,8 @@ bool InsetCommandParams::isCompatibleCommand(InsetCode code, string const & s)
return InsetBibtex::isCompatibleCommand(s); return InsetBibtex::isCompatibleCommand(s);
case CITE_CODE: case CITE_CODE:
return InsetCitation::isCompatibleCommand(s); return InsetCitation::isCompatibleCommand(s);
case COUNTER_CODE:
return InsetCounter::isCompatibleCommand(s);
case FLOAT_LIST_CODE: case FLOAT_LIST_CODE:
return InsetFloatList::isCompatibleCommand(s); return InsetFloatList::isCompatibleCommand(s);
case HYPERLINK_CODE: case HYPERLINK_CODE:
@ -282,7 +289,7 @@ void InsetCommandParams::setCmdName(string const & name)
void InsetCommandParams::read(Lexer & lex) void InsetCommandParams::read(Lexer & lex)
{ {
Read(lex, 0); Read(lex, nullptr);
} }
@ -356,7 +363,7 @@ void InsetCommandParams::Read(Lexer & lex, Buffer const * buffer)
void InsetCommandParams::write(ostream & os) const void InsetCommandParams::write(ostream & os) const
{ {
Write(os, 0); Write(os, nullptr);
} }

284
src/insets/InsetCounter.cpp Normal file
View File

@ -0,0 +1,284 @@
/**
* \file InsetCounter.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Richard Kimberly Heck
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetCounter.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "Counters.h"
#include "LaTeXFeatures.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "sgml.h"
#include "texstream.h"
#include "TextClass.h"
#include "support/convert.h"
#include "support/counter_reps.h"
#include "support/docstream.h"
#include "support/gettext.h"
#include "support/lassert.h"
#include "support/lstrings.h"
#include <map>
/*
#include "Cursor.h"
#include "DispatchResult.h"
#include "Language.h"
#include "LyX.h"
#include "ParIterator.h"
#include "TocBackend.h"
#include "support/debug.h"
#include "support/textutils.h"
*/
using namespace lyx::support;
using namespace std;
namespace lyx {
InsetCounter::InsetCounter(Buffer * buf, InsetCommandParams const & p)
: InsetCommand(buf, p)
{}
InsetCounter::InsetCounter(InsetCounter const & ir)
: InsetCommand(ir)
{}
const map<string, string> InsetCounter::counterTable =
{
{"set", N_("Set")},
{"addto", N_("Add To")},
{"reset", N_("Reset")},
{"save", N_("Save")},
{"restore", N_("Restore")},
{"value", N_("Value")}
};
bool InsetCounter::isCompatibleCommand(string const & s) {
return counterTable.count(s);
}
ParamInfo const & InsetCounter::findInfo(string const & /* cmdName */)
{
static ParamInfo param_info_;
if (param_info_.empty()) {
param_info_.add("counter", ParamInfo::LYX_INTERNAL);
param_info_.add("value", ParamInfo::LYX_INTERNAL);
param_info_.add("vtype", ParamInfo::LYX_INTERNAL);
param_info_.add("lyxonly", ParamInfo::LYX_INTERNAL);
}
return param_info_;
}
void InsetCounter::latex(otexstream & os, OutputParams const &) const
{
bool const lyxonly = lowercase(getParam("lyxonly")) == "true";
if (lyxonly)
return;
string const cmd = getCmdName();
docstring cntr = getParam("counter");
Counters & cnts = buffer().params().documentClass().counters();
if (cmd == "set") {
docstring const & val = getParam("value");
os << "\\setcounter{" << cntr << "}{" << val << "}";
} else if (cmd == "addto") {
docstring const & val = getParam("value");
os << "\\addtocounter{" << cntr << "}{" << val << "}";
} else if (cmd == "reset") {
os << "\\setcounter{" << cntr << "}{0}";
} else if (cmd == "save") {
cnts.saveValue(cntr);
os << "\\setcounter{" << lyxSaveCounter()
<< "}{\\value{" << cntr << "}}";
} else if (cmd == "restore") {
cnts.restoreValue(cntr);
os << "\\setcounter{" << cntr
<< "{\\value{" << lyxSaveCounter() << "}}";
} else if (cmd == "value") {
os << "\\value{" << cntr << "}";
}
}
void InsetCounter::toString(odocstream & os) const
{
os << "[Counter " << from_utf8(getCmdName()) << ": "
<< getParam("counter") << "]";
}
int InsetCounter::plaintext(odocstringstream & os,
OutputParams const &, size_t) const
{
toString(os);
return 0;
}
void InsetCounter::trackCounters(string const & cmd) const
{
Counters & cnts = buffer().params().documentClass().counters();
docstring cntr = getParam("counter");
if (cmd == "set") {
docstring const & val = getParam("value");
cnts.set(cntr, convert<int>(val));
} else if (cmd == "addto") {
docstring const & val = getParam("value");
cnts.addto(cntr, convert<int>(val));
} else if (cmd == "reset") {
cnts.reset(cntr);
} else if (cmd == "save") {
cnts.saveValue(cntr);
} else if (cmd == "restore") {
cnts.restoreValue(cntr);
}
}
const map<string, string> InsetCounter::valueTable =
{
{"Roman", N_("Roman Uppercase")},
{"roman", N_("Roman Lowercase")},
{"Alpha", N_("Uppercase Letter")},
{"alpha", N_("Lowercase Letter")},
{"arabic", N_("Arabic Numeral")}
};
docstring InsetCounter::value() const {
docstring const & cnt = getParam("counter");
string const & vtype = getCmdName();
int const val = buffer().params().documentClass().counters().value(cnt);
if (vtype == "Roman")
return romanCounter(val);
if (vtype == "roman")
return lowerromanCounter(val);
if (vtype == "Alpha")
return docstring(1, alphaCounter(val));
if (vtype == "alpha")
return docstring(1, loweralphaCounter(val));
if (vtype == "arabic")
return convert<docstring>(val);
LATTEST(false);
return empty_docstring();
}
int InsetCounter::docbook(odocstream & os, OutputParams const &) const
{
// Here, we need to track counter values ourselves,
// since unlike in the LaTeX case, there is no external
// mechanism for doing that.
string const cmd = getCmdName();
if (cmd == "value") {
docstring cntr = getParam("counter");
Counters & cnts = buffer().params().documentClass().counters();
if (cnts.hasCounter(cntr))
os << cnts.value(cntr);
} else
trackCounters(cmd);
return 0;
}
docstring InsetCounter::xhtml(XHTMLStream & xs, OutputParams const &) const
{
// Here, we need to track counter values ourselves,
// since unlike in the LaTeX case, there is no external
// mechanism for doing that.
string const cmd = getCmdName();
if (cmd == "value") {
docstring cntr = getParam("counter");
Counters & cnts = buffer().params().documentClass().counters();
if (cnts.hasCounter(cntr))
xs << cnts.value(cntr);
} else
trackCounters(cmd);
return docstring();
}
void InsetCounter::updateBuffer(ParIterator const &, UpdateType, bool const)
{
string const cmd = getCmdName();
docstring cntr = getParam("counter");
Counters & cnts = buffer().params().documentClass().counters();
map<string, string>::const_iterator cit = counterTable.find(cmd);
LASSERT(cit != counterTable.end(), return);
string const label = cit->second;
docstring const tlabel = translateIfPossible(from_ascii(label));
if (cmd == "set") {
docstring const & val = getParam("value");
cnts.set(cntr, convert<int>(val));
screen_label_ = bformat(_("Counter: Set %1$s"), cntr);
tooltip_ = bformat(_("Set value of counter %1$s to %2$s"), cntr, val);
} else if (cmd == "addto") {
docstring const & val = getParam("value");
cnts.addto(cntr, convert<int>(val));
screen_label_ = bformat(_("Counter: Add to %1$s"), cntr);
tooltip_ = bformat(_("Add to value of counter %1$s"), cntr);
} else if (cmd == "reset") {
cnts.reset(cntr);
screen_label_ = bformat(_("Counter: Reset %1$s"), cntr);
tooltip_ = bformat(_("Reset value of counter %1$s"), cntr);
} else if (cmd == "save") {
cnts.saveValue(cntr);
screen_label_ = bformat(_("Counter: Save %1$s"), cntr);
tooltip_ = bformat(_("Save value of counter %1$s"), cntr);
} else if (cmd == "restore") {
cnts.restoreValue(cntr);
screen_label_ = bformat(_("Counter: Restore %1$s"), cntr);
tooltip_ = bformat(_("Restore value of counter %1$s"), cntr);
} else if (cmd == "value") {
screen_label_ = bformat(_("Counter: Value %1$s"), cntr);
tooltip_ = bformat(_("Print value of counter %1$s"), cntr);
}
}
docstring InsetCounter::lyxSaveCounter() const
{
docstring cntr = getParam("counter");
return from_ascii("LyXSave") + cntr;
}
void InsetCounter::validate(LaTeXFeatures & features) const
{
// create save counter if needed
string const cmd = getCmdName();
docstring const lyxonly = getParam("lyxonly");
if ((cmd == "save" || cmd == "restore") && lyxonly != "true") {
features.addPreambleSnippet(from_ascii("\\newcounter{") + lyxSaveCounter() + "}");
}
InsetCommand::validate(features);
}
string InsetCounter::contextMenuName() const
{
return "context-counter";
}
} // namespace lyx

99
src/insets/InsetCounter.h Normal file
View File

@ -0,0 +1,99 @@
// -*- C++ -*-
/**
* \file InsetCounter.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Richard Kimberly Heck
*
* Full author contact details are available in file CREDITS.
*/
#ifndef INSET_COUNTER_H
#define INSET_COUNTER_H
#include "InsetCommand.h"
namespace lyx {
///
class InsetCounter : public InsetCommand {
public:
///
InsetCounter(Buffer * buffer, InsetCommandParams const &);
/// \name Public functions inherited from Inset class
//@{
///
bool isLabeled() const { return true; }
///
docstring toolTip(BufferView const &, int, int) const
{ return tooltip_; }
///
bool hasSettings() const { return true; }
///
InsetCode lyxCode() const { return COUNTER_CODE; }
///
void latex(otexstream &, OutputParams const &) const;
///
int plaintext(odocstringstream & ods, OutputParams const & op,
size_t max_length = INT_MAX) const;
///
int docbook(odocstream &, OutputParams const &) const;
///
docstring xhtml(XHTMLStream &, OutputParams const &) const;
///
void toString(odocstream &) const;
///
void validate(LaTeXFeatures & features) const;
///
void updateBuffer(ParIterator const & it, UpdateType, bool const);
///
std::string contextMenuName() const;
//@}
/// \name Static public methods obligated for InsetCommand derived classes
//@{
///
static ParamInfo const & findInfo(std::string const &);
///
static std::string defaultCommand() { return "set"; }
///
static bool isCompatibleCommand(std::string const & s);
//@}
/// keys are commands, values are GUI strings
static const std::map<std::string, std::string> counterTable;
static const std::map<std::string, std::string> valueTable;
protected:
///
InsetCounter(InsetCounter const &);
private:
/// \name Private functions inherited from Inset class
//@{
///
Inset * clone() const { return new InsetCounter(*this); }
//@}
/// \name Private functions inherited from InsetCommand class
//@{
///
docstring screenLabel() const { return screen_label_; }
//@}
///
docstring value() const;
///
docstring lyxSaveCounter() const;
///
void trackCounters(std::string const & cmd) const;
///
mutable docstring screen_label_;
///
mutable docstring tooltip_;
};
} // namespace lyx
#endif // INSET_REF_H

View File

@ -44,6 +44,8 @@ liblyxsupport_a_SOURCES = \
convert.cpp \ convert.cpp \
convert.h \ convert.h \
copied_ptr.h \ copied_ptr.h \
counter_reps.cpp \
counter_reps.h \
debug.cpp \ debug.cpp \
debug.h \ debug.h \
docstream.cpp \ docstream.cpp \

View File

@ -0,0 +1,135 @@
/**
* \file convert.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author André Pönitz
* \author Lars Gullik Bjønnes
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "support/counter_reps.h"
#include "support/docstring.h"
#include "support/lstrings.h"
using namespace std;
namespace lyx {
char loweralphaCounter(int const n)
{
if (n < 1 || n > 26)
return '?';
return 'a' + n - 1;
}
char alphaCounter(int const n)
{
if (n < 1 || n > 26)
return '?';
return 'A' + n - 1;
}
char hebrewCounter(int const n)
{
static const char hebrew[22] = {
'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8',
'\xe9', '\xeb', '\xec', '\xee', '\xf0', '\xf1', '\xf2', '\xf4', '\xf6',
'\xf7', '\xf8', '\xf9', '\xfa'
};
if (n < 1 || n > 22)
return '?';
return hebrew[n - 1];
}
// On the special cases, see http://mathworld.wolfram.com/RomanNumerals.html
// and for a list of roman numerals up to and including 3999, see
// http://www.research.att.com/~njas/sequences/a006968.txt. (Thanks to Joost
// for this info.)
docstring const romanCounter(int const n)
{
static char const * const ones[9] = {
"I", "II", "III", "IV", "V",
"VI", "VII", "VIII", "IX"
};
static char const * const tens[9] = {
"X", "XX", "XXX", "XL", "L",
"LX", "LXX", "LXXX", "XC"
};
static char const * const hunds[9] = {
"C", "CC", "CCC", "CD", "D",
"DC", "DCC", "DCCC", "CM"
};
if (n >= 1000 || n < 1)
return from_ascii("??");
int val = n;
string roman;
switch (n) {
//special cases
case 900:
roman = "CM";
break;
case 400:
roman = "CD";
break;
default:
if (val >= 100) {
int hundreds = val / 100;
roman = hunds[hundreds - 1];
val = val % 100;
}
if (val >= 10) {
switch (val) {
//special case
case 90:
roman = roman + "XC";
val = 0; //skip next
break;
default:
int tensnum = val / 10;
roman = roman + tens[tensnum - 1];
val = val % 10;
} // end switch
} // end tens
if (val > 0)
roman = roman + ones[val -1];
}
return from_ascii(roman);
}
docstring const lowerromanCounter(int const n)
{
return support::lowercase(romanCounter(n));
}
docstring const fnsymbolCounter(int const n)
{
switch(n) {
case 1: return docstring(1, 0x002a); //*
case 2: return docstring(1, 0x2020); // dagger
case 3: return docstring(1, 0x2021); // double dagger
case 4: return docstring(1, 0x00A7); // section sign
case 5: return docstring(1, 0x00B6); // pilcrow sign
case 6: return docstring(1, 0x2016); // vertical bar
case 7: return docstring(2, 0x002a); // two *
case 8: return docstring(2, 0x2020); // two daggers
case 9: return docstring(2, 0x2021); // two double daggers
default:
return from_ascii("?");
};
}
} // namespace lyx

View File

@ -0,0 +1,33 @@
// -*- C++ -*-
/**
* \file counter_reps.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Lars Gullik Bjønnes
* \author Richard Kimberly Heck (roman numerals)
* \author Jean-Marc Lasgouttes
*
* Full author contact details are available in file CREDITS.
*
* A collection of helper functions to convert counters to different
* formats.
*/
#ifndef COUNTER_REPS_H
#define COUNTER_REPS_H
#include "support/strfwd.h"
namespace lyx {
char loweralphaCounter(int const n);
char alphaCounter(int const n);
char hebrewCounter(int const n);
docstring const romanCounter(int const n);
docstring const lowerromanCounter(int const n);
docstring const fnsymbolCounter(int const n);
} // namespace lyx
#endif