2 * \file InsetScript.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
13 #include "InsetScript.h"
16 #include "BufferParams.h"
17 #include "BufferView.h"
19 #include "Dimension.h"
20 #include "DispatchResult.h"
22 #include "FuncRequest.h"
23 #include "FuncStatus.h"
24 #include "LaTeXFeatures.h"
26 #include "LyXAction.h"
27 #include "MetricsInfo.h"
28 #include "OutputParams.h"
29 #include "output_xhtml.h"
30 #include "TextClass.h"
31 #include "TextMetrics.h"
33 #include "support/docstream.h"
34 #include "support/gettext.h"
35 #include "support/lstrings.h"
36 #include "support/Translator.h"
38 #include "frontends/Application.h"
39 #include "frontends/FontMetrics.h"
40 #include "frontends/Painter.h"
50 typedef Translator<string, InsetScriptParams::Type> ScriptTranslator;
51 typedef Translator<docstring, InsetScriptParams::Type> ScriptTranslatorLoc;
53 ScriptTranslator const init_scripttranslator()
55 ScriptTranslator translator("subscript", InsetScriptParams::Subscript);
56 translator.addPair("superscript", InsetScriptParams::Superscript);
61 ScriptTranslatorLoc const init_scripttranslator_loc()
63 ScriptTranslatorLoc translator(_("Subscript"), InsetScriptParams::Subscript);
64 translator.addPair(_("Superscript"), InsetScriptParams::Superscript);
69 ScriptTranslator const & scripttranslator()
71 static ScriptTranslator translator = init_scripttranslator();
76 ScriptTranslatorLoc const & scripttranslator_loc()
78 static ScriptTranslatorLoc translator = init_scripttranslator_loc();
85 InsetScriptParams::InsetScriptParams()
90 void InsetScriptParams::write(ostream & os) const
92 string const label = scripttranslator().find(type);
93 os << "script " << label << "\n";
97 void InsetScriptParams::read(Lexer & lex)
102 type = scripttranslator().find(label);
106 int InsetScriptParams::shift(FontInfo const & font) const
108 frontend::FontMetrics const & fm = theFontMetrics(font);
111 return fm.maxAscent() / 3;
113 return -fm.maxAscent() / 2;
120 /////////////////////////////////////////////////////////////////////
124 /////////////////////////////////////////////////////////////////////
126 InsetScript::InsetScript(Buffer * buf, InsetScriptParams const & params)
127 : InsetText(buf, InsetText::PlainLayout), params_(params)
133 InsetScript::InsetScript(Buffer * buf, string const & label)
137 params_.type = scripttranslator().find(label);
141 InsetScript::~InsetScript()
146 docstring InsetScript::name() const
148 return from_ascii("script:" + scripttranslator().find(params_.type));
152 Inset::DisplayType InsetScript::display() const
158 void InsetScript::metrics(MetricsInfo & mi, Dimension & dim) const
160 int const shift = params_.shift(mi.base.font);
161 ScriptChanger dummy(mi.base);
162 InsetText::metrics(mi, dim);
168 void InsetScript::draw(PainterInfo & pi, int x, int y) const
170 int const shift = params_.shift(pi.base.font);
171 ScriptChanger dummy(pi.base);
172 InsetText::draw(pi, x, y + shift);
176 void InsetScript::cursorPos(BufferView const & bv,
177 CursorSlice const & sl, bool boundary, int & x, int & y) const
179 Font const font = bv.textMetrics(&text()).displayFont(sl.pit(), sl.pos());
180 int const shift = params_.shift(font.fontInfo());
181 InsetText::cursorPos(bv, sl, boundary, x, y);
186 void InsetScript::write(ostream & os) const
193 void InsetScript::read(Lexer & lex)
196 InsetText::read(lex);
200 void InsetScript::edit(Cursor & cur, bool front, EntryDirection entry_from)
203 InsetText::edit(cur, front, entry_from);
207 Inset * InsetScript::editXY(Cursor & cur, int x, int y)
210 return InsetText::editXY(cur, x, y);
213 void InsetScript::doDispatch(Cursor & cur, FuncRequest & cmd)
215 switch (cmd.action()) {
216 case LFUN_INSET_MODIFY:
217 cur.recordUndoInset(ATOMIC_UNDO, this);
218 string2params(to_utf8(cmd.argument()), params_);
221 InsetText::doDispatch(cur, cmd);
227 bool InsetScript::insetAllowed(InsetCode code) const
230 // code that is not allowed in a script
236 case COLLAPSABLE_CODE:
238 case FLOAT_LIST_CODE:
241 case INDEX_PRINT_CODE:
244 case MATH_MACRO_CODE:
248 case NOMENCL_PRINT_CODE:
256 return InsetText::insetAllowed(code);
260 bool InsetScript::getStatus(Cursor & cur, FuncRequest const & cmd,
261 FuncStatus & flag) const
263 switch (cmd.action()) {
264 case LFUN_BREAK_PARAGRAPH:
266 case LFUN_LAYOUT_PARAGRAPH:
267 case LFUN_MATH_DISPLAY:
268 case LFUN_BOX_INSERT:
269 case LFUN_BRANCH_INSERT:
270 case LFUN_CAPTION_INSERT:
271 case LFUN_FLOAT_INSERT:
272 case LFUN_FLOAT_LIST_INSERT:
273 case LFUN_FLOAT_WIDE_INSERT:
274 case LFUN_FOOTNOTE_INSERT:
275 case LFUN_HFILL_INSERT:
276 case LFUN_INDEX_PRINT:
277 case LFUN_LISTING_INSERT:
278 case LFUN_MARGINALNOTE_INSERT:
279 case LFUN_NEWLINE_INSERT:
280 case LFUN_NEWPAGE_INSERT:
281 case LFUN_NOMENCL_PRINT:
282 case LFUN_PREVIEW_INSERT:
283 case LFUN_QUOTE_INSERT:
284 case LFUN_TABULAR_INSERT:
285 case LFUN_WRAP_INSERT:
286 flag.setEnabled(false);
288 case LFUN_INSET_MODIFY:
289 flag.setEnabled(true);
291 case LFUN_COMMAND_SEQUENCE: {
292 // argument contains ';'-terminated commands
293 string arg = to_utf8(cmd.argument());
294 // prevent insertion of display math formulas like AMS align
295 while (!arg.empty()) {
297 arg = support::split(arg, first, ';');
298 FuncRequest func(lyxaction.lookupFunc(first));
299 if (func.action() == LFUN_MATH_MUTATE) {
300 flag.setEnabled(false);
309 return InsetText::getStatus(cur, cmd, flag);
313 docstring InsetScript::toolTip(BufferView const &, int, int) const
315 OutputParams rp(&buffer().params().encoding());
316 odocstringstream ods;
317 InsetText::plaintext(ods, rp);
318 docstring content_tip = ods.str();
319 // shorten it if necessary
320 if (content_tip.size() > 200)
321 content_tip = content_tip.substr(0, 200) + "...";
322 docstring res = scripttranslator_loc().find(params_.type);
323 if (!content_tip.empty())
324 res += from_ascii(": ") + content_tip;
329 void InsetScript::validate(LaTeXFeatures & features) const
331 if (params_.type == InsetScriptParams::Subscript)
332 features.require("subscript");
333 InsetText::validate(features);
337 void InsetScript::latex(otexstream & os, OutputParams const & runparams) const
339 switch (params_.type) {
340 case InsetScriptParams::Subscript:
341 os << "\\textsubscript{";
343 case InsetScriptParams::Superscript:
344 os << "\\textsuperscript{";
347 InsetText::latex(os, runparams);
352 int InsetScript::plaintext(odocstream & os, OutputParams const & runparams) const
354 odocstringstream oss;
355 InsetText::plaintext(oss, runparams);
356 docstring const text = oss.str();
357 switch (params_.type) {
358 case InsetScriptParams::Subscript:
359 if (text.size() == 1) {
360 char_type const c = support::subscript(text[0]);
366 os << '[' << buffer().B_("subscript") << ':';
368 case InsetScriptParams::Superscript:
369 if (text.size() == 1) {
370 char_type const c = support::superscript(text[0]);
376 os << '[' << buffer().B_("superscript") << ':';
379 InsetText::plaintext(os, runparams);
382 return PLAINTEXT_NEWLINE;
386 int InsetScript::docbook(odocstream & os, OutputParams const & runparams) const
389 switch (params_.type) {
390 case InsetScriptParams::Subscript:
391 cmdname = "subscript";
393 case InsetScriptParams::Superscript:
394 cmdname = "superscript";
397 os << '<' + cmdname + '>';
398 int const i = InsetText::docbook(os, runparams);
399 os << "</" + cmdname + '>';
405 docstring InsetScript::xhtml(XHTMLStream & xs, OutputParams const & runparams) const
408 switch (params_.type) {
409 case InsetScriptParams::Subscript:
412 case InsetScriptParams::Superscript:
417 xs << html::StartTag(cmdname);
418 docstring const ret = InsetText::xhtml(xs, runparams);
419 xs << html::EndTag(cmdname);
424 docstring InsetScript::contextMenuName() const
426 return from_ascii("context-script");
430 string InsetScript::params2string(InsetScriptParams const & params)
439 void InsetScript::string2params(string const & in, InsetScriptParams & params)
441 params = InsetScriptParams();
446 istringstream data(in);
449 lex.setContext("InsetScript::string2params");
450 lex >> "script" >> "script";