lyx_mirror/src/insets/InsetScript.cpp

413 lines
8.5 KiB
C++
Raw Normal View History

/**
* \file InsetScript.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Georg Baum
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetScript.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "BufferView.h"
#include "Cursor.h"
#include "Dimension.h"
#include "DispatchResult.h"
#include "Exporter.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
#include "LaTeXFeatures.h"
#include "Lexer.h"
#include "LyXAction.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "TextClass.h"
#include "TextMetrics.h"
#include "support/docstream.h"
#include "support/gettext.h"
#include "support/lstrings.h"
#include "support/Translator.h"
#include "frontends/Application.h"
#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
#include <algorithm>
using namespace std;
namespace lyx {
namespace {
typedef Translator<string, InsetScriptParams::Type> ScriptTranslator;
typedef Translator<docstring, InsetScriptParams::Type> ScriptTranslatorLoc;
ScriptTranslator const init_scripttranslator()
{
ScriptTranslator translator("subscript", InsetScriptParams::Subscript);
translator.addPair("superscript", InsetScriptParams::Superscript);
return translator;
}
ScriptTranslatorLoc const init_scripttranslator_loc()
{
ScriptTranslatorLoc translator(_("Subscript"), InsetScriptParams::Subscript);
translator.addPair(_("Superscript"), InsetScriptParams::Superscript);
return translator;
}
ScriptTranslator const & scripttranslator()
{
static ScriptTranslator const translator =
init_scripttranslator();
return translator;
}
ScriptTranslatorLoc const & scripttranslator_loc()
{
static ScriptTranslatorLoc const translator =
init_scripttranslator_loc();
return translator;
}
} // anon
InsetScriptParams::InsetScriptParams()
: type(Subscript)
{}
void InsetScriptParams::write(ostream & os) const
{
string const label = scripttranslator().find(type);
os << "script " << label << "\n";
}
void InsetScriptParams::read(Lexer & lex)
{
string label;
lex >> label;
if (lex)
type = scripttranslator().find(label);
}
int InsetScriptParams::shift(FontInfo const & font) const
{
frontend::FontMetrics const & fm = theFontMetrics(font);
switch (type) {
case Subscript:
return fm.maxAscent() / 3;
case Superscript:
return -fm.maxAscent() / 2;
}
// shut up compiler
return 0;
}
/////////////////////////////////////////////////////////////////////
//
// InsetScript
//
/////////////////////////////////////////////////////////////////////
InsetScript::InsetScript(Buffer * buf, InsetScriptParams const & params)
: InsetText(buf, InsetText::PlainLayout), params_(params)
{
setDrawFrame(false);
}
InsetScript::InsetScript(Buffer * buf, string const & label)
: InsetText(buf)
{
setDrawFrame(false);
params_.type = scripttranslator().find(label);
}
InsetScript::~InsetScript()
{
}
docstring InsetScript::layoutName() const
{
return from_ascii("Script:" + scripttranslator().find(params_.type));
}
Inset::DisplayType InsetScript::display() const
{
return Inline;
}
void InsetScript::metrics(MetricsInfo & mi, Dimension & dim) const
{
int const shift = params_.shift(mi.base.font);
Changer dummy = mi.base.changeScript();
InsetText::metrics(mi, dim);
dim.asc -= shift;
dim.des += shift;
}
void InsetScript::draw(PainterInfo & pi, int x, int y) const
{
int const shift = params_.shift(pi.base.font);
Changer dummy = pi.base.changeScript();
InsetText::draw(pi, x, y + shift);
}
void InsetScript::cursorPos(BufferView const & bv,
CursorSlice const & sl, bool boundary, int & x, int & y) const
{
Font const font = bv.textMetrics(&text()).displayFont(sl.pit(), sl.pos());
int const shift = params_.shift(font.fontInfo());
InsetText::cursorPos(bv, sl, boundary, x, y);
y += shift;
}
void InsetScript::write(ostream & os) const
{
params_.write(os);
text().write(os);
}
void InsetScript::read(Lexer & lex)
{
params_.read(lex);
InsetText::read(lex);
}
void InsetScript::edit(Cursor & cur, bool front, EntryDirection entry_from)
{
cur.push(*this);
InsetText::edit(cur, front, entry_from);
}
Inset * InsetScript::editXY(Cursor & cur, int x, int y)
{
cur.push(*this);
return InsetText::editXY(cur, x, y);
}
void InsetScript::doDispatch(Cursor & cur, FuncRequest & cmd)
{
switch (cmd.action()) {
case LFUN_INSET_MODIFY:
cur.recordUndoInset(this);
string2params(to_utf8(cmd.argument()), params_);
break;
default:
InsetText::doDispatch(cur, cmd);
break;
}
}
bool InsetScript::insetAllowed(InsetCode code) const
{
switch (code) {
// code that is not allowed in a script
case BIBITEM_CODE:
case BIBTEX_CODE:
case BOX_CODE:
case BRANCH_CODE:
case CAPTION_CODE:
case COLLAPSABLE_CODE:
case FLOAT_CODE:
case FLOAT_LIST_CODE:
case FOOT_CODE:
case INCLUDE_CODE:
case INDEX_PRINT_CODE:
case LISTINGS_CODE:
case MARGIN_CODE:
case MATH_MACRO_CODE:
case MATHMACRO_CODE:
case NEWLINE_CODE:
case NEWPAGE_CODE:
case NOMENCL_PRINT_CODE:
case QUOTE_CODE:
case PREVIEW_CODE:
case TABULAR_CODE:
case TOC_CODE:
case WRAP_CODE:
return false;
default:
return InsetText::insetAllowed(code);
}
}
bool InsetScript::getStatus(Cursor & cur, FuncRequest const & cmd,
FuncStatus & flag) const
{
switch (cmd.action()) {
case LFUN_MATH_DISPLAY:
case LFUN_BOX_INSERT:
case LFUN_BRANCH_INSERT:
case LFUN_CAPTION_INSERT:
case LFUN_FLOAT_INSERT:
case LFUN_FLOAT_LIST_INSERT:
case LFUN_FLOAT_WIDE_INSERT:
case LFUN_FOOTNOTE_INSERT:
case LFUN_INDEX_PRINT:
case LFUN_LISTING_INSERT:
case LFUN_MARGINALNOTE_INSERT:
case LFUN_NEWLINE_INSERT:
case LFUN_NEWPAGE_INSERT:
case LFUN_NOMENCL_PRINT:
case LFUN_PREVIEW_INSERT:
case LFUN_QUOTE_INSERT:
case LFUN_TABULAR_INSERT:
case LFUN_WRAP_INSERT:
flag.setEnabled(false);
return true;
case LFUN_INSET_MODIFY:
flag.setEnabled(true);
return true;
case LFUN_COMMAND_SEQUENCE: {
// argument contains ';'-terminated commands
string arg = to_utf8(cmd.argument());
// prevent insertion of display math formulas like AMS align
while (!arg.empty()) {
string first;
arg = support::split(arg, first, ';');
FuncRequest func(lyxaction.lookupFunc(first));
if (func.action() == LFUN_MATH_MUTATE) {
flag.setEnabled(false);
return true;
}
}
break;
}
default:
break;
}
return InsetText::getStatus(cur, cmd, flag);
}
docstring InsetScript::toolTip(BufferView const &, int, int) const
{
OutputParams rp(&buffer().params().encoding());
odocstringstream ods;
InsetText::plaintext(ods, rp, 200);
docstring content_tip = ods.str();
// shorten it if necessary
support::truncateWithEllipsis(content_tip, 200);
docstring res = scripttranslator_loc().find(params_.type);
if (!content_tip.empty())
res += from_ascii(": ") + content_tip;
return res;
}
int InsetScript::plaintext(odocstringstream & os,
OutputParams const & runparams, size_t max_length) const
{
odocstringstream oss;
InsetText::plaintext(oss, runparams, max_length);
docstring const text = oss.str();
switch (params_.type) {
case InsetScriptParams::Subscript:
if (text.size() == 1) {
char_type const c = support::subscript(text[0]);
if (c != text[0]) {
os.put(c);
return 0;
}
}
os << '[' << buffer().B_("subscript") << ':';
break;
case InsetScriptParams::Superscript:
if (text.size() == 1) {
char_type const c = support::superscript(text[0]);
if (c != text[0]) {
os.put(c);
return 0;
}
}
os << '[' << buffer().B_("superscript") << ':';
break;
}
InsetText::plaintext(os, runparams, max_length);
os << ']';
return PLAINTEXT_NEWLINE;
}
int InsetScript::docbook(odocstream & os, OutputParams const & runparams) const
{
docstring cmdname;
switch (params_.type) {
case InsetScriptParams::Subscript:
cmdname = from_ascii("subscript");
break;
case InsetScriptParams::Superscript:
cmdname = from_ascii("superscript");
break;
}
os << '<' + cmdname + '>';
int const i = InsetText::docbook(os, runparams);
os << "</" + cmdname + '>';
return i;
}
string InsetScript::contextMenuName() const
{
return "context-script";
}
string InsetScript::params2string(InsetScriptParams const & params)
{
ostringstream data;
data << "script ";
params.write(data);
return data.str();
}
void InsetScript::string2params(string const & in, InsetScriptParams & params)
{
params = InsetScriptParams();
if (in.empty())
return;
istringstream data(in);
Lexer lex;
lex.setStream(data);
lex.setContext("InsetScript::string2params");
lex >> "script" >> "script";
params.read(lex);
}
} // namespace lyx