2002-09-25 14:26:13 +00:00
|
|
|
/**
|
2007-04-25 01:24:38 +00:00
|
|
|
* \file InsetRef.cpp
|
2002-09-25 14:26:13 +00:00
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
* Licence details can be found in the file COPYING.
|
|
|
|
*
|
2008-11-14 15:58:50 +00:00
|
|
|
* \author José Matos
|
2002-09-25 14:26:13 +00:00
|
|
|
*
|
2003-08-23 00:17:00 +00:00
|
|
|
* Full author contact details are available in file CREDITS.
|
2002-09-25 14:26:13 +00:00
|
|
|
*/
|
1999-09-27 18:44:28 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2007-04-25 01:24:38 +00:00
|
|
|
#include "InsetRef.h"
|
2003-09-05 09:01:27 +00:00
|
|
|
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "Buffer.h"
|
2010-10-13 12:36:53 +00:00
|
|
|
#include "BufferParams.h"
|
2007-04-26 14:56:30 +00:00
|
|
|
#include "Cursor.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "DispatchResult.h"
|
2018-04-07 01:31:11 +00:00
|
|
|
#include "FuncStatus.h"
|
2010-01-20 19:03:17 +00:00
|
|
|
#include "InsetLabel.h"
|
2013-03-19 15:30:09 +00:00
|
|
|
#include "Language.h"
|
2000-05-19 16:46:01 +00:00
|
|
|
#include "LaTeXFeatures.h"
|
2010-02-09 16:11:13 +00:00
|
|
|
#include "LyX.h"
|
2007-04-26 04:41:58 +00:00
|
|
|
#include "OutputParams.h"
|
2009-11-14 14:12:37 +00:00
|
|
|
#include "output_xhtml.h"
|
2020-03-14 15:29:53 +00:00
|
|
|
#include "Paragraph.h"
|
2008-02-27 16:23:27 +00:00
|
|
|
#include "ParIterator.h"
|
2019-05-09 23:35:40 +00:00
|
|
|
#include "xml.h"
|
2016-06-19 02:39:38 +00:00
|
|
|
#include "texstream.h"
|
2008-02-27 16:23:27 +00:00
|
|
|
#include "TocBackend.h"
|
2003-09-05 09:01:27 +00:00
|
|
|
|
2010-10-28 15:15:14 +00:00
|
|
|
#include "support/debug.h"
|
2007-11-01 22:17:22 +00:00
|
|
|
#include "support/docstream.h"
|
2008-02-27 16:23:27 +00:00
|
|
|
#include "support/gettext.h"
|
2001-06-27 14:10:35 +00:00
|
|
|
#include "support/lstrings.h"
|
2010-11-17 22:17:53 +00:00
|
|
|
#include "support/textutils.h"
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2007-12-12 18:57:56 +00:00
|
|
|
using namespace lyx::support;
|
2008-03-02 15:27:35 +00:00
|
|
|
using namespace std;
|
2003-10-06 15:43:21 +00:00
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
namespace lyx {
|
|
|
|
|
2003-09-05 09:01:27 +00:00
|
|
|
|
2009-11-08 15:53:21 +00:00
|
|
|
InsetRef::InsetRef(Buffer * buf, InsetCommandParams const & p)
|
2020-03-14 15:29:53 +00:00
|
|
|
: InsetCommand(buf, p), broken_(false), active_(true)
|
2000-08-08 13:55:26 +00:00
|
|
|
{}
|
|
|
|
|
2002-08-07 08:11:41 +00:00
|
|
|
|
2003-06-03 15:10:14 +00:00
|
|
|
InsetRef::InsetRef(InsetRef const & ir)
|
2020-03-14 15:29:53 +00:00
|
|
|
: InsetCommand(ir), broken_(false), active_(true)
|
2003-12-11 15:23:15 +00:00
|
|
|
{}
|
2003-02-25 14:51:38 +00:00
|
|
|
|
|
|
|
|
2007-12-12 19:28:07 +00:00
|
|
|
bool InsetRef::isCompatibleCommand(string const & s) {
|
2007-10-25 04:13:56 +00:00
|
|
|
//FIXME This is likely not the best way to handle this.
|
|
|
|
//But this stuff is hardcoded elsewhere already.
|
2017-07-03 17:53:14 +00:00
|
|
|
return s == "ref"
|
2007-10-25 04:13:56 +00:00
|
|
|
|| s == "pageref"
|
2017-07-03 17:53:14 +00:00
|
|
|
|| s == "vref"
|
2007-10-25 04:13:56 +00:00
|
|
|
|| s == "vpageref"
|
2010-10-13 12:36:53 +00:00
|
|
|
|| s == "formatted"
|
2018-02-14 16:18:24 +00:00
|
|
|
|| s == "prettyref" // for InsetMathRef FIXME
|
2010-07-13 03:23:29 +00:00
|
|
|
|| s == "eqref"
|
2016-06-18 22:38:24 +00:00
|
|
|
|| s == "nameref"
|
|
|
|
|| s == "labelonly";
|
2007-10-25 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-23 22:01:02 +00:00
|
|
|
ParamInfo const & InsetRef::findInfo(string const & /* cmdName */)
|
2007-10-25 04:13:56 +00:00
|
|
|
{
|
2008-02-23 22:01:02 +00:00
|
|
|
static ParamInfo param_info_;
|
|
|
|
if (param_info_.empty()) {
|
Per Abdel's suggestion that we focus on bug-fixing at this point, this will be the last patch in this series for a bit. But I wanted to get this done before I forget what it is I was doing, so here it is.
The idea behind this patch is to make real key-value support for InsetCommand parameters possible. This should be particularly useful for the listings version of InsetInclude, though we would need some kind of UI for it before it would really be helpful. (See below for some thoughts.) This doesn't substantially change anything else, though some things do get re-arranged a bit.
Basically, the idea is this. First, we introduce a whole range of parameter types: Normal LaTeX optional and required parameters; ones for LyX's internal use (like embed); and finally, in connection with keyval, ones that represent keys and ones that represent optional and required arguments where the keyval stuff will appear. (I'm assuming here that there will always be exactly one of those, and that it will accept only keyval-type material.) The parameters themselves are stored in a map, so it's really only the output routines that need to care about the different types of parameters.
Regarding the frontend, it seems to me that something like the following would work:
(i) scan the parameter list for LATEX_KEY type parameters
(ii) the dialog will have a series of lines, each of which has a combo box listing the acceptable keys and a QLineEdit for entering its value, as well as a "delete" button of some sort for removing this key and its value
(iii) there should be an "add line" button to add a new line, activated only when all other lines are filled with values
Probably not even too hard.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23235 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-25 22:13:45 +00:00
|
|
|
param_info_.add("name", ParamInfo::LATEX_OPTIONAL);
|
2010-02-13 13:08:32 +00:00
|
|
|
param_info_.add("reference", ParamInfo::LATEX_REQUIRED,
|
|
|
|
ParamInfo::HANDLING_ESCAPE);
|
2016-06-18 23:29:15 +00:00
|
|
|
param_info_.add("plural", ParamInfo::LYX_INTERNAL);
|
|
|
|
param_info_.add("caps", ParamInfo::LYX_INTERNAL);
|
2017-01-07 19:39:03 +00:00
|
|
|
param_info_.add("noprefix", ParamInfo::LYX_INTERNAL);
|
2008-02-23 22:01:02 +00:00
|
|
|
}
|
|
|
|
return param_info_;
|
2007-10-25 04:13:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-31 11:29:53 +00:00
|
|
|
docstring InsetRef::layoutName() const
|
|
|
|
{
|
|
|
|
return from_ascii("Ref");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void InsetRef::changeTarget(docstring const & new_label)
|
|
|
|
{
|
|
|
|
// With change tracking, we insert a new ref
|
|
|
|
// and delete the old one
|
|
|
|
if (buffer().masterParams().track_changes) {
|
|
|
|
InsetCommandParams icp(REF_CODE, "ref");
|
|
|
|
icp["reference"] = new_label;
|
|
|
|
string const data = InsetCommand::params2string(icp);
|
|
|
|
lyx::dispatch(FuncRequest(LFUN_INSET_INSERT, data));
|
|
|
|
lyx::dispatch(FuncRequest(LFUN_CHAR_DELETE_FORWARD));
|
|
|
|
} else
|
|
|
|
setParam("reference", new_label);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-04-07 01:31:11 +00:00
|
|
|
void InsetRef::doDispatch(Cursor & cur, FuncRequest & cmd)
|
|
|
|
{
|
|
|
|
string const inset = cmd.getArg(0);
|
|
|
|
string const arg = cmd.getArg(1);
|
|
|
|
string pstring;
|
|
|
|
if (cmd.action() == LFUN_INSET_MODIFY && inset == "ref") {
|
|
|
|
if (arg == "toggle-plural")
|
|
|
|
pstring = "plural";
|
|
|
|
else if (arg == "toggle-caps")
|
|
|
|
pstring = "caps";
|
|
|
|
else if (arg == "toggle-noprefix")
|
|
|
|
pstring = "noprefix";
|
2019-12-31 11:29:53 +00:00
|
|
|
else if (arg == "changetarget") {
|
|
|
|
string const oldtarget = cmd.getArg(2);
|
|
|
|
string const newtarget = cmd.getArg(3);
|
|
|
|
if (!oldtarget.empty() && !newtarget.empty()
|
|
|
|
&& getParam("reference") == from_utf8(oldtarget))
|
|
|
|
changeTarget(from_utf8(newtarget));
|
|
|
|
cur.forceBufferUpdate();
|
|
|
|
return;
|
|
|
|
}
|
2018-04-07 01:31:11 +00:00
|
|
|
}
|
2020-09-10 16:38:41 +00:00
|
|
|
|
|
|
|
// Ctrl + click: go to label
|
|
|
|
if (cmd.action() == LFUN_MOUSE_RELEASE && cmd.modifier() == ControlModifier) {
|
|
|
|
lyx::dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
|
|
|
|
lyx::dispatch(FuncRequest(LFUN_LABEL_GOTO, getParam("reference")));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-07 01:31:11 +00:00
|
|
|
// otherwise not for us
|
|
|
|
if (pstring.empty())
|
|
|
|
return InsetCommand::doDispatch(cur, cmd);
|
|
|
|
|
|
|
|
bool const isSet = (getParam(pstring) == "true");
|
|
|
|
setParam(pstring, from_ascii(isSet ? "false" : "true"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool InsetRef::getStatus(Cursor & cur, FuncRequest const & cmd,
|
|
|
|
FuncStatus & status) const
|
|
|
|
{
|
|
|
|
if (cmd.action() != LFUN_INSET_MODIFY)
|
|
|
|
return InsetCommand::getStatus(cur, cmd, status);
|
|
|
|
if (cmd.getArg(0) != "ref")
|
|
|
|
return InsetCommand::getStatus(cur, cmd, status);
|
|
|
|
|
|
|
|
string const arg = cmd.getArg(1);
|
|
|
|
string pstring;
|
2019-12-31 11:29:53 +00:00
|
|
|
if (arg == "changetarget")
|
|
|
|
return true;
|
2018-04-07 01:31:11 +00:00
|
|
|
if (arg == "toggle-plural")
|
|
|
|
pstring = "plural";
|
|
|
|
else if (arg == "toggle-caps")
|
|
|
|
pstring = "caps";
|
|
|
|
if (!pstring.empty()) {
|
|
|
|
status.setEnabled(buffer().params().use_refstyle &&
|
|
|
|
params().getCmdName() == "formatted");
|
|
|
|
bool const isSet = (getParam(pstring) == "true");
|
|
|
|
status.setOnOff(isSet);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (arg == "toggle-noprefix") {
|
|
|
|
status.setEnabled(params().getCmdName() == "labelonly");
|
|
|
|
bool const isSet = (getParam("noprefix") == "true");
|
|
|
|
status.setOnOff(isSet);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// otherwise not for us
|
|
|
|
return InsetCommand::getStatus(cur, cmd, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-18 23:29:15 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
void capitalize(docstring & s) {
|
|
|
|
char_type t = uppercase(s[0]);
|
|
|
|
s[0] = t;
|
|
|
|
}
|
|
|
|
|
2017-07-23 11:11:54 +00:00
|
|
|
} // namespace
|
2016-06-18 23:29:15 +00:00
|
|
|
|
|
|
|
|
2010-11-08 17:50:02 +00:00
|
|
|
// the ref argument is the label name we are referencing.
|
|
|
|
// we expect ref to be in the form: pfx:suffix.
|
|
|
|
//
|
2017-07-03 17:53:14 +00:00
|
|
|
// if it isn't, then we can't produce a formatted reference,
|
2010-11-08 17:50:02 +00:00
|
|
|
// so we return "\ref" and put ref into label.
|
|
|
|
//
|
2017-07-03 17:53:14 +00:00
|
|
|
// for refstyle, we return "\pfxcmd", and put suffix into
|
2010-11-08 17:50:02 +00:00
|
|
|
// label and pfx into prefix. this is because refstyle expects
|
|
|
|
// the command: \pfxcmd{suffix}.
|
2017-07-03 17:53:14 +00:00
|
|
|
//
|
2010-11-08 17:50:02 +00:00
|
|
|
// for prettyref, we return "\prettyref" and put ref into label
|
2011-03-13 20:29:52 +00:00
|
|
|
// and pfx into prefix. this is because prettyref uses the whole
|
|
|
|
// label, thus: \prettyref{pfx:suffix}.
|
2010-11-08 17:50:02 +00:00
|
|
|
//
|
2017-07-03 17:53:14 +00:00
|
|
|
docstring InsetRef::getFormattedCmd(docstring const & ref,
|
2016-06-18 23:29:15 +00:00
|
|
|
docstring & label, docstring & prefix, docstring const & caps) const
|
2010-10-28 15:15:14 +00:00
|
|
|
{
|
|
|
|
static docstring const defcmd = from_ascii("\\ref");
|
2010-11-01 21:54:20 +00:00
|
|
|
static docstring const prtcmd = from_ascii("\\prettyref");
|
2017-07-03 17:53:14 +00:00
|
|
|
|
2010-10-28 15:15:14 +00:00
|
|
|
label = split(ref, prefix, ':');
|
2010-11-01 21:54:20 +00:00
|
|
|
|
|
|
|
// we have to have xxx:xxxxx...
|
2010-11-10 16:45:55 +00:00
|
|
|
if (label.empty()) {
|
2017-01-07 19:39:03 +00:00
|
|
|
LYXERR0("Label `" << ref << "' contains no `:' separator.");
|
2010-11-10 16:45:55 +00:00
|
|
|
label = ref;
|
|
|
|
prefix = from_ascii("");
|
|
|
|
return defcmd;
|
|
|
|
}
|
|
|
|
|
2010-10-28 15:15:14 +00:00
|
|
|
if (prefix.empty()) {
|
2010-11-10 16:45:55 +00:00
|
|
|
// we have ":xxxx"
|
2010-10-29 13:07:05 +00:00
|
|
|
label = ref;
|
2010-10-28 15:15:14 +00:00
|
|
|
return defcmd;
|
|
|
|
}
|
2017-07-03 17:53:14 +00:00
|
|
|
|
2010-11-01 21:54:20 +00:00
|
|
|
if (!buffer().params().use_refstyle) {
|
|
|
|
// \prettyref uses the whole label
|
|
|
|
label = ref;
|
|
|
|
return prtcmd;
|
|
|
|
}
|
|
|
|
|
2010-10-28 15:15:14 +00:00
|
|
|
// make sure the prefix is legal for a latex command
|
2020-09-10 16:38:41 +00:00
|
|
|
size_t const len = prefix.size();
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
2010-11-17 22:17:53 +00:00
|
|
|
char_type const c = prefix[i];
|
|
|
|
if (!isAlphaASCII(c)) {
|
2010-11-17 21:19:01 +00:00
|
|
|
LYXERR0("Prefix `" << prefix << "' is invalid for LaTeX.");
|
2010-10-28 15:15:14 +00:00
|
|
|
// restore the label
|
|
|
|
label = ref;
|
|
|
|
return defcmd;
|
|
|
|
}
|
|
|
|
}
|
2016-06-18 23:29:15 +00:00
|
|
|
if (caps == "true") {
|
|
|
|
capitalize(prefix);
|
|
|
|
}
|
2010-10-28 15:15:14 +00:00
|
|
|
return from_ascii("\\") + prefix + from_ascii("ref");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
docstring InsetRef::getEscapedLabel(OutputParams const & rp) const
|
|
|
|
{
|
|
|
|
InsetCommandParams const & p = params();
|
|
|
|
ParamInfo const & pi = p.info();
|
|
|
|
ParamInfo::ParamData const & pd = pi["reference"];
|
2017-01-28 12:00:33 +00:00
|
|
|
return p.prepareCommand(rp, getParam("reference"), pd.handling());
|
2010-10-28 15:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-10 20:02:48 +00:00
|
|
|
void InsetRef::latex(otexstream & os, OutputParams const & rp) const
|
1999-09-27 18:44:28 +00:00
|
|
|
{
|
2015-02-24 09:17:45 +00:00
|
|
|
string const & cmd = getCmdName();
|
|
|
|
docstring const & data = getEscapedLabel(rp);
|
2011-03-13 20:29:52 +00:00
|
|
|
|
2014-03-22 11:25:25 +00:00
|
|
|
if (rp.inulemcmd > 0)
|
2012-08-30 12:09:23 +00:00
|
|
|
os << "\\mbox{";
|
|
|
|
|
2011-03-19 10:37:24 +00:00
|
|
|
if (cmd == "eqref" && buffer().params().use_refstyle) {
|
2011-12-03 23:15:04 +00:00
|
|
|
// we advertise this as printing "(n)", so we'll do that, at least
|
|
|
|
// for refstyle, since refstlye's own \eqref prints, by default,
|
|
|
|
// "equation n". if one wants \eqref, one can get it by using a
|
|
|
|
// formatted label in this case.
|
2011-03-19 10:37:24 +00:00
|
|
|
os << '(' << from_ascii("\\ref{") << data << from_ascii("})");
|
2017-07-03 17:53:14 +00:00
|
|
|
}
|
2011-03-19 10:37:24 +00:00
|
|
|
else if (cmd == "formatted") {
|
|
|
|
docstring label;
|
|
|
|
docstring prefix;
|
2017-07-03 17:53:14 +00:00
|
|
|
docstring const fcmd =
|
2016-06-18 23:29:15 +00:00
|
|
|
getFormattedCmd(data, label, prefix, getParam("caps"));
|
|
|
|
os << fcmd;
|
|
|
|
if (buffer().params().use_refstyle && getParam("plural") == "true")
|
|
|
|
os << "[s]";
|
|
|
|
os << '{' << label << '}';
|
2011-03-19 10:37:24 +00:00
|
|
|
}
|
2016-06-18 22:38:24 +00:00
|
|
|
else if (cmd == "labelonly") {
|
2017-01-07 19:39:03 +00:00
|
|
|
docstring const & ref = getParam("reference");
|
|
|
|
if (getParam("noprefix") != "true")
|
|
|
|
os << ref;
|
|
|
|
else {
|
|
|
|
docstring prefix;
|
|
|
|
docstring suffix = split(ref, prefix, ':');
|
|
|
|
if (suffix.empty()) {
|
|
|
|
LYXERR0("Label `" << ref << "' contains no `:' separator.");
|
|
|
|
os << ref;
|
|
|
|
} else {
|
|
|
|
os << suffix;
|
|
|
|
}
|
|
|
|
}
|
2016-06-18 22:38:24 +00:00
|
|
|
}
|
2011-03-19 10:37:24 +00:00
|
|
|
else {
|
2010-10-13 12:36:53 +00:00
|
|
|
InsetCommandParams p(REF_CODE, cmd);
|
2010-10-28 15:15:14 +00:00
|
|
|
docstring const ref = getParam("reference");
|
2010-10-13 12:36:53 +00:00
|
|
|
p["reference"] = ref;
|
2010-10-28 15:15:14 +00:00
|
|
|
os << p.getCommand(rp);
|
2011-03-13 20:29:52 +00:00
|
|
|
}
|
2012-08-30 12:09:23 +00:00
|
|
|
|
2014-03-22 11:25:25 +00:00
|
|
|
if (rp.inulemcmd > 0)
|
2012-08-30 12:09:23 +00:00
|
|
|
os << "}";
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-08 19:52:18 +00:00
|
|
|
int InsetRef::plaintext(odocstringstream & os,
|
|
|
|
OutputParams const &, size_t) const
|
2000-04-24 20:58:23 +00:00
|
|
|
{
|
2007-02-24 14:35:38 +00:00
|
|
|
docstring const str = getParam("reference");
|
2007-02-15 23:28:31 +00:00
|
|
|
os << '[' << str << ']';
|
2020-09-10 16:38:41 +00:00
|
|
|
return 2 + int(str.size());
|
2000-04-24 20:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-08 21:27:49 +00:00
|
|
|
void InsetRef::docbook(XMLStream & xs, OutputParams const &) const
|
2000-03-06 02:42:40 +00:00
|
|
|
{
|
2020-06-08 21:27:49 +00:00
|
|
|
docstring const & ref = getParam("reference");
|
|
|
|
InsetLabel const * il = buffer().insetLabel(ref, true);
|
|
|
|
string const & cmd = params().getCmdName();
|
|
|
|
docstring linkend = xml::cleanID(ref);
|
|
|
|
|
|
|
|
// A name is provided, LyX will provide it. This is supposed to be a very rare case.
|
|
|
|
// Link with linkend, as is it within the document (not outside, in which case xlink:href is better suited).
|
2006-10-20 16:12:49 +00:00
|
|
|
docstring const & name = getParam("name");
|
2020-06-08 21:27:49 +00:00
|
|
|
if (!name.empty()) {
|
|
|
|
docstring attr = from_utf8("linkend=\"") + linkend + from_utf8("\"");
|
|
|
|
|
|
|
|
xs << xml::StartTag("link", to_utf8(attr));
|
|
|
|
xs << name;
|
|
|
|
xs << xml::EndTag("link");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The DocBook processor will generate the name when required.
|
|
|
|
docstring display_before;
|
|
|
|
docstring display_after;
|
|
|
|
docstring role;
|
|
|
|
|
|
|
|
if (il && !il->counterValue().empty()) {
|
|
|
|
// Try to construct a label from the InsetLabel we reference.
|
|
|
|
if (cmd == "vref" || cmd == "pageref" || cmd == "vpageref" || cmd == "nameref" || cmd == "formatted") {
|
|
|
|
// "ref on page #", "on page #", etc. The DocBook processor deals with generating the right text,
|
|
|
|
// including in the right language.
|
|
|
|
role = from_ascii(cmd);
|
|
|
|
|
|
|
|
if (cmd == "formatted") {
|
|
|
|
// A formatted reference may have many parameters. Generate all of them as roles, the only
|
|
|
|
// way arbitrary parameters can be passed into DocBook.
|
|
|
|
if (buffer().params().use_refstyle && getParam("caps") == "true")
|
|
|
|
role += " refstyle-caps";
|
|
|
|
if (buffer().params().use_refstyle && getParam("plural") == "true")
|
|
|
|
role += " refstyle-plural";
|
|
|
|
}
|
|
|
|
} else if (cmd == "eqref") {
|
|
|
|
display_before = from_ascii("(");
|
|
|
|
display_after = from_ascii(")");
|
2006-10-20 16:12:49 +00:00
|
|
|
}
|
2020-06-08 21:27:49 +00:00
|
|
|
// TODO: what about labelonly? I don't get how this is supposed to work...
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
2001-06-27 14:10:35 +00:00
|
|
|
|
2020-06-08 21:27:49 +00:00
|
|
|
// No name, ask DocBook to generate one.
|
2020-07-21 00:44:11 +00:00
|
|
|
docstring attr = from_utf8("linkend=\"") + xml::cleanID(ref) + from_utf8("\"");
|
2020-06-08 21:27:49 +00:00
|
|
|
if (!role.empty())
|
|
|
|
attr += " role=\"" + role + "\"";
|
|
|
|
xs << display_before;
|
|
|
|
xs << xml::CompTag("xref", to_utf8(attr));
|
|
|
|
xs << display_after;
|
1999-09-27 18:44:28 +00:00
|
|
|
}
|
2000-05-19 16:46:01 +00:00
|
|
|
|
2000-09-14 17:53:12 +00:00
|
|
|
|
2019-05-09 23:35:40 +00:00
|
|
|
docstring InsetRef::xhtml(XMLStream & xs, OutputParams const & op) const
|
2009-11-14 14:12:37 +00:00
|
|
|
{
|
2010-01-20 19:03:17 +00:00
|
|
|
docstring const & ref = getParam("reference");
|
2018-12-29 09:08:02 +00:00
|
|
|
InsetLabel const * il = buffer().insetLabel(ref, true);
|
2010-01-20 19:03:17 +00:00
|
|
|
string const & cmd = params().getCmdName();
|
|
|
|
docstring display_string;
|
|
|
|
|
|
|
|
if (il && !il->counterValue().empty()) {
|
|
|
|
// Try to construct a label from the InsetLabel we reference.
|
|
|
|
docstring const & value = il->counterValue();
|
|
|
|
if (cmd == "ref")
|
|
|
|
display_string = value;
|
|
|
|
else if (cmd == "vref")
|
2010-01-20 20:33:36 +00:00
|
|
|
// normally, would be "ref on page #", but we have no pages
|
|
|
|
display_string = value;
|
2010-01-20 19:03:17 +00:00
|
|
|
else if (cmd == "pageref" || cmd == "vpageref")
|
2013-03-18 23:47:17 +00:00
|
|
|
// normally would be "on page #", but we have no pages.
|
2013-03-19 15:30:09 +00:00
|
|
|
display_string = translateIfPossible(from_ascii("elsewhere"),
|
|
|
|
op.local_font->language()->lang());
|
2010-01-20 19:03:17 +00:00
|
|
|
else if (cmd == "eqref")
|
2013-03-18 22:08:31 +00:00
|
|
|
display_string = '(' + value + ')';
|
2016-06-18 23:29:15 +00:00
|
|
|
else if (cmd == "formatted") {
|
2013-03-18 23:30:17 +00:00
|
|
|
display_string = il->prettyCounter();
|
2016-06-18 23:29:15 +00:00
|
|
|
if (buffer().params().use_refstyle && getParam("caps") == "true")
|
|
|
|
capitalize(display_string);
|
|
|
|
// it is hard to see what to do about plurals...
|
|
|
|
}
|
2013-03-18 23:30:17 +00:00
|
|
|
else if (cmd == "nameref")
|
|
|
|
// FIXME We don't really have the ability to handle these
|
|
|
|
// properly in XHTML output yet (bug #8599).
|
|
|
|
// It might not be that hard to do. We have the InsetLabel,
|
|
|
|
// and we can presumably find its paragraph using the TOC.
|
2014-10-16 20:50:03 +00:00
|
|
|
// But the label might be referencing a section, yet not be
|
|
|
|
// in that section. So this is not trivial.
|
2010-01-20 20:33:36 +00:00
|
|
|
display_string = il->prettyCounter();
|
2017-07-03 17:53:14 +00:00
|
|
|
} else
|
2010-01-20 19:03:17 +00:00
|
|
|
display_string = ref;
|
|
|
|
|
2009-11-14 14:12:37 +00:00
|
|
|
// FIXME What we'd really like to do is to be able to output some
|
|
|
|
// appropriate sort of text here. But to do that, we need to associate
|
|
|
|
// some sort of counter with the label, and we don't have that yet.
|
2019-05-09 23:35:40 +00:00
|
|
|
docstring const attr = "href=\"#" + xml::cleanAttr(ref) + '"';
|
|
|
|
xs << xml::StartTag("a", to_utf8(attr));
|
2010-01-20 19:03:17 +00:00
|
|
|
xs << display_string;
|
2019-05-09 23:35:40 +00:00
|
|
|
xs << xml::EndTag("a");
|
2009-11-14 14:12:37 +00:00
|
|
|
return docstring();
|
|
|
|
}
|
|
|
|
|
2009-12-31 15:52:16 +00:00
|
|
|
|
2010-12-15 01:34:04 +00:00
|
|
|
void InsetRef::toString(odocstream & os) const
|
2005-11-25 14:40:34 +00:00
|
|
|
{
|
2013-03-08 19:52:18 +00:00
|
|
|
odocstringstream ods;
|
2020-09-10 16:38:41 +00:00
|
|
|
plaintext(ods, OutputParams(nullptr));
|
2013-03-08 19:52:18 +00:00
|
|
|
os << ods.str();
|
2005-11-25 14:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-04 18:38:47 +00:00
|
|
|
void InsetRef::forOutliner(docstring & os, size_t const, bool const) const
|
2010-12-20 21:55:09 +00:00
|
|
|
{
|
2010-12-20 22:47:09 +00:00
|
|
|
// There's no need for details in the TOC, and a long label
|
|
|
|
// will just get in the way.
|
|
|
|
os += '#';
|
2010-12-20 21:55:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-06 12:23:01 +00:00
|
|
|
void InsetRef::updateBuffer(ParIterator const & it, UpdateType, bool const /*deleted*/)
|
2008-02-27 16:23:27 +00:00
|
|
|
{
|
2010-02-26 20:16:12 +00:00
|
|
|
docstring const & ref = getParam("reference");
|
2020-03-14 15:29:53 +00:00
|
|
|
|
|
|
|
// Check if this one is active (i.e., neither deleted with change-tracking
|
|
|
|
// nor in an inset that does not produce output, such as notes or inactive branches)
|
|
|
|
Paragraph const & para = it.paragraph();
|
|
|
|
active_ = !para.isDeleted(it.pos()) && para.inInset().producesOutput();
|
|
|
|
// If not, check whether we are in a deleted/non-outputting inset
|
|
|
|
if (active_) {
|
|
|
|
for (size_type sl = 0 ; sl < it.depth() ; ++sl) {
|
|
|
|
Paragraph const & outer_par = it[sl].paragraph();
|
|
|
|
if (outer_par.isDeleted(it[sl].pos())
|
|
|
|
|| !outer_par.inInset().producesOutput()) {
|
|
|
|
active_ = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-03 17:58:26 +00:00
|
|
|
// register this inset into the buffer reference cache.
|
2013-03-18 23:32:30 +00:00
|
|
|
buffer().addReference(ref, this, it);
|
2008-03-03 17:58:26 +00:00
|
|
|
|
2010-02-26 20:16:12 +00:00
|
|
|
docstring label;
|
2017-01-07 19:39:03 +00:00
|
|
|
string const & cmd = getCmdName();
|
2008-03-03 17:58:26 +00:00
|
|
|
for (int i = 0; !types[i].latex_name.empty(); ++i) {
|
2017-01-07 19:39:03 +00:00
|
|
|
if (cmd == types[i].latex_name) {
|
2010-02-26 20:16:12 +00:00
|
|
|
label = _(types[i].short_gui_name);
|
2008-03-03 17:58:26 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-01-07 19:39:03 +00:00
|
|
|
|
|
|
|
if (cmd != "labelonly")
|
|
|
|
label += ref;
|
|
|
|
else {
|
|
|
|
if (getParam("noprefix") != "true")
|
|
|
|
label += ref;
|
|
|
|
else {
|
|
|
|
docstring prefix;
|
|
|
|
docstring suffix = split(ref, prefix, ':');
|
|
|
|
if (suffix.empty()) {
|
|
|
|
label += ref;
|
|
|
|
} else {
|
|
|
|
label += suffix;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-16 10:13:58 +00:00
|
|
|
|
2011-05-13 19:39:56 +00:00
|
|
|
if (!buffer().params().isLatex() && !getParam("name").empty()) {
|
2010-02-26 20:16:12 +00:00
|
|
|
label += "||";
|
|
|
|
label += getParam("name");
|
|
|
|
}
|
2017-05-16 10:13:58 +00:00
|
|
|
|
2010-02-26 20:16:12 +00:00
|
|
|
unsigned int const maxLabelChars = 24;
|
2015-10-20 15:11:31 +00:00
|
|
|
if (label.size() > maxLabelChars) {
|
2010-02-26 20:16:12 +00:00
|
|
|
tooltip_ = label;
|
2015-10-04 18:38:47 +00:00
|
|
|
support::truncateWithEllipsis(label, maxLabelChars);
|
|
|
|
} else
|
2010-02-26 20:16:12 +00:00
|
|
|
tooltip_ = from_ascii("");
|
2017-05-16 10:13:58 +00:00
|
|
|
|
2015-10-04 18:38:47 +00:00
|
|
|
screen_label_ = label;
|
2017-05-16 10:13:58 +00:00
|
|
|
broken_ = false;
|
2020-03-14 13:17:30 +00:00
|
|
|
setBroken(broken_);
|
2017-05-16 10:13:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
docstring InsetRef::screenLabel() const
|
|
|
|
{
|
|
|
|
return (broken_ ? _("BROKEN: ") : docstring()) + screen_label_;
|
2008-03-02 15:27:35 +00:00
|
|
|
}
|
2008-02-27 16:44:57 +00:00
|
|
|
|
2008-03-02 15:27:35 +00:00
|
|
|
|
2015-09-27 06:05:00 +00:00
|
|
|
void InsetRef::addToToc(DocIterator const & cpit, bool output_active,
|
2020-03-14 14:35:47 +00:00
|
|
|
UpdateType, TocBackend & backend) const
|
2008-03-02 15:27:35 +00:00
|
|
|
{
|
2020-03-14 15:29:53 +00:00
|
|
|
active_ = output_active;
|
2008-03-02 15:27:35 +00:00
|
|
|
docstring const & label = getParam("reference");
|
2018-12-31 17:30:20 +00:00
|
|
|
if (buffer().insetLabel(label)) {
|
2020-10-03 06:54:06 +00:00
|
|
|
broken_ = !buffer().activeLabel(label) && active_;
|
2020-03-14 13:17:30 +00:00
|
|
|
setBroken(broken_);
|
2020-03-14 14:35:47 +00:00
|
|
|
if (broken_ && output_active) {
|
|
|
|
shared_ptr<Toc> toc2 = backend.toc("brokenrefs");
|
|
|
|
toc2->push_back(TocItem(cpit, 0, screenLabel(), output_active));
|
|
|
|
}
|
2008-03-02 15:27:35 +00:00
|
|
|
// This InsetRef has already been taken care of in InsetLabel::addToToc().
|
2008-02-27 16:44:57 +00:00
|
|
|
return;
|
2018-12-31 17:30:20 +00:00
|
|
|
}
|
2008-02-27 16:44:57 +00:00
|
|
|
|
2008-03-03 17:58:26 +00:00
|
|
|
// It seems that this reference does not point to any valid label.
|
2017-05-16 10:13:58 +00:00
|
|
|
broken_ = true;
|
2020-03-14 13:17:30 +00:00
|
|
|
setBroken(broken_);
|
2017-01-13 10:06:48 +00:00
|
|
|
shared_ptr<Toc> toc = backend.toc("label");
|
2017-05-16 10:13:58 +00:00
|
|
|
toc->push_back(TocItem(cpit, 0, screenLabel(), output_active));
|
2020-03-14 14:18:28 +00:00
|
|
|
shared_ptr<Toc> toc2 = backend.toc("brokenrefs");
|
|
|
|
toc2->push_back(TocItem(cpit, 0, screenLabel(), output_active));
|
2008-02-27 16:23:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-28 10:25:20 +00:00
|
|
|
void InsetRef::validate(LaTeXFeatures & features) const
|
2000-05-19 16:46:01 +00:00
|
|
|
{
|
2010-07-13 03:23:29 +00:00
|
|
|
string const cmd = getCmdName();
|
|
|
|
if (cmd == "vref" || cmd == "vpageref")
|
2001-11-19 15:34:11 +00:00
|
|
|
features.require("varioref");
|
2011-07-13 15:18:29 +00:00
|
|
|
else if (cmd == "formatted") {
|
2010-11-10 16:45:55 +00:00
|
|
|
docstring const data = getEscapedLabel(features.runparams());
|
|
|
|
docstring label;
|
|
|
|
docstring prefix;
|
2017-07-03 17:53:14 +00:00
|
|
|
docstring const fcmd =
|
2016-06-18 23:29:15 +00:00
|
|
|
getFormattedCmd(data, label, prefix, getParam("caps"));
|
2010-10-13 12:36:53 +00:00
|
|
|
if (buffer().params().use_refstyle) {
|
|
|
|
features.require("refstyle");
|
2013-02-07 13:44:42 +00:00
|
|
|
if (prefix == "cha")
|
2016-09-25 10:37:40 +00:00
|
|
|
features.addPreambleSnippet(from_ascii("\\let\\charef=\\chapref"));
|
2013-02-07 13:44:42 +00:00
|
|
|
else if (!prefix.empty()) {
|
2016-09-25 10:37:40 +00:00
|
|
|
docstring lcmd = "\\AtBeginDocument{\\providecommand" +
|
|
|
|
fcmd + "[1]{\\ref{" + prefix + ":#1}}}";
|
2010-10-28 15:15:14 +00:00
|
|
|
features.addPreambleSnippet(lcmd);
|
2013-02-07 13:44:42 +00:00
|
|
|
}
|
2010-11-10 16:45:55 +00:00
|
|
|
} else {
|
2010-10-13 12:36:53 +00:00
|
|
|
features.require("prettyref");
|
2010-11-10 16:45:55 +00:00
|
|
|
// prettyref uses "cha" for chapters, so we provide a kind of
|
|
|
|
// translation.
|
|
|
|
if (prefix == "chap")
|
2016-09-25 10:37:40 +00:00
|
|
|
features.addPreambleSnippet(from_ascii("\\let\\pr@chap=\\pr@cha"));
|
2010-11-10 16:45:55 +00:00
|
|
|
}
|
2011-07-13 15:18:29 +00:00
|
|
|
} else if (cmd == "eqref" && !buffer().params().use_refstyle)
|
2011-12-03 23:15:04 +00:00
|
|
|
// with refstyle, we simply output "(\ref{label})"
|
2003-08-18 17:41:30 +00:00
|
|
|
features.require("amsmath");
|
2010-07-16 15:19:04 +00:00
|
|
|
else if (cmd == "nameref")
|
2010-07-13 03:23:29 +00:00
|
|
|
features.require("nameref");
|
2000-08-04 13:12:30 +00:00
|
|
|
}
|
2001-01-21 21:41:35 +00:00
|
|
|
|
2019-08-05 14:30:01 +00:00
|
|
|
bool InsetRef::forceLTR(OutputParams const & rp) const
|
2019-03-15 10:23:53 +00:00
|
|
|
{
|
2019-08-05 14:30:01 +00:00
|
|
|
// We force LTR for references. However,
|
|
|
|
// * Namerefs are output in the scripts direction
|
|
|
|
// at least with fontspec/bidi and luabidi, though (see #11518).
|
|
|
|
// * Parentheses are automatically swapped with XeTeX/bidi
|
|
|
|
// [not with LuaTeX/luabidi] (see #11626).
|
2019-03-15 10:23:53 +00:00
|
|
|
// FIXME: Re-Audit all other RTL cases.
|
2019-08-05 14:30:01 +00:00
|
|
|
if (rp.useBidiPackage())
|
|
|
|
return false;
|
2019-03-15 10:23:53 +00:00
|
|
|
return (getCmdName() != "nameref" || !buffer().masterParams().useNonTeXFonts);
|
|
|
|
}
|
|
|
|
|
2002-06-24 17:26:15 +00:00
|
|
|
|
2013-10-07 22:59:05 +00:00
|
|
|
InsetRef::type_info const InsetRef::types[] = {
|
2003-04-24 12:16:56 +00:00
|
|
|
{ "ref", N_("Standard"), N_("Ref: ")},
|
|
|
|
{ "eqref", N_("Equation"), N_("EqRef: ")},
|
|
|
|
{ "pageref", N_("Page Number"), N_("Page: ")},
|
|
|
|
{ "vpageref", N_("Textual Page Number"), N_("TextPage: ")},
|
|
|
|
{ "vref", N_("Standard+Textual Page"), N_("Ref+Text: ")},
|
2016-06-07 00:41:07 +00:00
|
|
|
{ "nameref", N_("Reference to Name"), N_("NameRef: ")},
|
2019-01-06 17:51:02 +00:00
|
|
|
{ "formatted", N_("Formatted"), N_("Format: ")},
|
2016-06-18 22:38:24 +00:00
|
|
|
{ "labelonly", N_("Label Only"), N_("Label: ")},
|
2001-01-21 21:41:35 +00:00
|
|
|
{ "", "", "" }
|
|
|
|
};
|
2001-01-26 17:11:01 +00:00
|
|
|
|
|
|
|
|
2017-07-03 17:53:14 +00:00
|
|
|
docstring InsetRef::getTOCString() const
|
2014-10-30 22:39:58 +00:00
|
|
|
{
|
2020-03-14 15:29:53 +00:00
|
|
|
docstring const & label = getParam("reference");
|
|
|
|
if (buffer().insetLabel(label))
|
|
|
|
broken_ = !buffer().activeLabel(label) && active_;
|
|
|
|
else
|
|
|
|
broken_ = active_;
|
2017-05-16 10:13:58 +00:00
|
|
|
return tooltip_.empty() ? screenLabel() : tooltip_;
|
2014-10-30 22:39:58 +00:00
|
|
|
}
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
} // namespace lyx
|