lyx_mirror/src/insets/InsetScript.cpp
Enrico Forestieri d866717ef7 Integrate texrow with otexstream in order to perform automatic line
counting when exporting to latex. This is done for the code comprised
between \begin{document} and \end{document}, while the preamble code
still needs manual calls to TexRow::newline() for registering new lines.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@37584 a592a061-630c-0410-9148-cb99ea01b6c8
2011-02-10 20:02:48 +00:00

457 lines
9.4 KiB
C++

/**
* \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 translator = init_scripttranslator();
return translator;
}
ScriptTranslatorLoc const & scripttranslator_loc()
{
static ScriptTranslatorLoc 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::name() 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);
ScriptChanger dummy(mi.base);
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);
ScriptChanger dummy(pi.base);
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(ATOMIC_UNDO, 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_BREAK_PARAGRAPH:
case LFUN_LAYOUT:
case LFUN_LAYOUT_PARAGRAPH:
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_HFILL_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);
docstring content_tip = ods.str();
// shorten it if necessary
if (content_tip.size() > 200)
content_tip = content_tip.substr(0, 200) + "...";
docstring res = scripttranslator_loc().find(params_.type);
if (!content_tip.empty())
res += from_ascii(": ") + content_tip;
return res;
}
void InsetScript::validate(LaTeXFeatures & features) const
{
if (params_.type == InsetScriptParams::Subscript)
features.require("subscript");
InsetText::validate(features);
}
void InsetScript::latex(otexstream & os, OutputParams const & runparams) const
{
switch (params_.type) {
case InsetScriptParams::Subscript:
os << "\\textsubscript{";
break;
case InsetScriptParams::Superscript:
os << "\\textsuperscript{";
break;
}
InsetText::latex(os, runparams);
os << "}";
}
int InsetScript::plaintext(odocstream & os, OutputParams const & runparams) const
{
odocstringstream oss;
InsetText::plaintext(oss, runparams);
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);
os << ']';
return PLAINTEXT_NEWLINE;
}
int InsetScript::docbook(odocstream & os, OutputParams const & runparams) const
{
string cmdname;
switch (params_.type) {
case InsetScriptParams::Subscript:
cmdname = "subscript";
break;
case InsetScriptParams::Superscript:
cmdname = "superscript";
break;
}
os << '<' + cmdname + '>';
int const i = InsetText::docbook(os, runparams);
os << "</" + cmdname + '>';
return i;
}
docstring InsetScript::xhtml(XHTMLStream & xs, OutputParams const & runparams) const
{
string cmdname;
switch (params_.type) {
case InsetScriptParams::Subscript:
cmdname = "sub";
break;
case InsetScriptParams::Superscript:
cmdname = "sup";
break;
}
xs << html::StartTag(cmdname);
docstring const ret = InsetText::xhtml(xs, runparams);
xs << html::EndTag(cmdname);
return ret;
}
docstring InsetScript::contextMenuName() const
{
return from_ascii("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