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_docbook.h"
30 #include "output_xhtml.h"
31 #include "TextClass.h"
32 #include "TextMetrics.h"
34 #include "support/docstream.h"
35 #include "support/gettext.h"
36 #include "support/lstrings.h"
37 #include "support/Translator.h"
39 #include "frontends/Application.h"
40 #include "frontends/FontMetrics.h"
41 #include "frontends/Painter.h"
51 typedef Translator<string, InsetScriptParams::Type> ScriptTranslator;
52 typedef Translator<docstring, InsetScriptParams::Type> ScriptTranslatorLoc;
54 ScriptTranslator const init_scripttranslator()
56 ScriptTranslator translator("subscript", InsetScriptParams::Subscript);
57 translator.addPair("superscript", InsetScriptParams::Superscript);
62 ScriptTranslatorLoc const init_scripttranslator_loc()
64 ScriptTranslatorLoc translator(_("Subscript"), InsetScriptParams::Subscript);
65 translator.addPair(_("Superscript"), InsetScriptParams::Superscript);
70 ScriptTranslator const & scripttranslator()
72 static ScriptTranslator const translator =
73 init_scripttranslator();
78 ScriptTranslatorLoc const & scripttranslator_loc()
80 static ScriptTranslatorLoc const translator =
81 init_scripttranslator_loc();
88 InsetScriptParams::InsetScriptParams()
93 void InsetScriptParams::write(ostream & os) const
95 string const label = scripttranslator().find(type);
96 os << "script " << label << "\n";
100 void InsetScriptParams::read(Lexer & lex)
105 type = scripttranslator().find(label);
109 int InsetScriptParams::shift(FontInfo const & font) const
111 frontend::FontMetrics const & fm = theFontMetrics(font);
114 return fm.maxAscent() / 3;
116 return -fm.maxAscent() / 2;
123 /////////////////////////////////////////////////////////////////////
127 /////////////////////////////////////////////////////////////////////
129 InsetScript::InsetScript(Buffer * buf, InsetScriptParams const & params)
130 : InsetText(buf, InsetText::PlainLayout), params_(params)
136 InsetScript::InsetScript(Buffer * buf, string const & label)
140 params_.type = scripttranslator().find(label);
144 InsetScript::~InsetScript()
149 docstring InsetScript::layoutName() const
151 return from_ascii("Script:" + scripttranslator().find(params_.type));
155 void InsetScript::metrics(MetricsInfo & mi, Dimension & dim) const
157 int const shift = params_.shift(mi.base.font);
158 // Remember the value of the outser font, so that it can be used in cursorPos.
159 outer_font_ = mi.base.font;
160 Changer dummy = mi.base.changeScript();
161 InsetText::metrics(mi, dim);
167 void InsetScript::draw(PainterInfo & pi, int x, int y) const
169 int const shift = params_.shift(pi.base.font);
170 Changer dummy = pi.base.changeScript();
171 InsetText::draw(pi, x, y + shift);
175 void InsetScript::cursorPos(BufferView const & bv,
176 CursorSlice const & sl, bool boundary, int & x, int & y) const
178 int const shift = params_.shift(outer_font_);
179 InsetText::cursorPos(bv, sl, boundary, x, y);
184 void InsetScript::write(ostream & os) const
191 void InsetScript::read(Lexer & lex)
194 InsetText::read(lex);
198 void InsetScript::edit(Cursor & cur, bool front, EntryDirection entry_from)
201 InsetText::edit(cur, front, entry_from);
205 Inset * InsetScript::editXY(Cursor & cur, int x, int y)
208 return InsetText::editXY(cur, x, y);
211 void InsetScript::doDispatch(Cursor & cur, FuncRequest & cmd)
213 switch (cmd.action()) {
214 case LFUN_INSET_MODIFY:
215 cur.recordUndoInset(this);
216 string2params(to_utf8(cmd.argument()), params_);
219 InsetText::doDispatch(cur, cmd);
225 bool InsetScript::insetAllowed(InsetCode code) const
228 // code that is not allowed in a script
234 case COLLAPSIBLE_CODE:
236 case FLOAT_LIST_CODE:
239 case INDEX_PRINT_CODE:
242 case MATH_MACRO_CODE:
246 case NOMENCL_PRINT_CODE:
254 return InsetText::insetAllowed(code);
258 bool InsetScript::getStatus(Cursor & cur, FuncRequest const & cmd,
259 FuncStatus & flag) const
261 switch (cmd.action()) {
262 case LFUN_MATH_DISPLAY:
263 case LFUN_BOX_INSERT:
264 case LFUN_BRANCH_INSERT:
265 case LFUN_CAPTION_INSERT:
266 case LFUN_FLOAT_INSERT:
267 case LFUN_FLOAT_LIST_INSERT:
268 case LFUN_FLOAT_WIDE_INSERT:
269 case LFUN_FOOTNOTE_INSERT:
270 case LFUN_INDEX_PRINT:
271 case LFUN_LISTING_INSERT:
272 case LFUN_MARGINALNOTE_INSERT:
273 case LFUN_NEWLINE_INSERT:
274 case LFUN_NEWPAGE_INSERT:
275 case LFUN_NOMENCL_PRINT:
276 case LFUN_PREVIEW_INSERT:
277 case LFUN_QUOTE_INSERT:
278 case LFUN_TABULAR_INSERT:
279 case LFUN_TABULAR_STYLE_INSERT:
280 case LFUN_WRAP_INSERT:
281 flag.setEnabled(false);
283 case LFUN_INSET_MODIFY:
284 flag.setEnabled(true);
286 case LFUN_COMMAND_SEQUENCE: {
287 // argument contains ';'-terminated commands
288 string arg = to_utf8(cmd.argument());
289 // prevent insertion of display math formulas like AMS align
290 while (!arg.empty()) {
292 arg = support::split(arg, first, ';');
293 FuncRequest func(lyxaction.lookupFunc(first));
294 if (func.action() == LFUN_MATH_MUTATE) {
295 flag.setEnabled(false);
304 return InsetText::getStatus(cur, cmd, flag);
308 docstring InsetScript::toolTip(BufferView const &, int, int) const
310 OutputParams rp(&buffer().params().encoding());
311 odocstringstream ods;
312 InsetText::plaintext(ods, rp, 200);
313 docstring content_tip = ods.str();
314 // shorten it if necessary
315 support::truncateWithEllipsis(content_tip, 200);
316 docstring res = scripttranslator_loc().find(params_.type);
317 if (!content_tip.empty())
318 res += from_ascii(": ") + content_tip;
323 int InsetScript::plaintext(odocstringstream & os,
324 OutputParams const & runparams, size_t max_length) const
326 odocstringstream oss;
327 InsetText::plaintext(oss, runparams, max_length);
328 docstring const text = oss.str();
329 switch (params_.type) {
330 case InsetScriptParams::Subscript:
331 if (text.size() == 1) {
332 char_type const c = support::subscript(text[0]);
338 os << '[' << buffer().B_("subscript") << ':';
340 case InsetScriptParams::Superscript:
341 if (text.size() == 1) {
342 char_type const c = support::superscript(text[0]);
348 os << '[' << buffer().B_("superscript") << ':';
351 InsetText::plaintext(os, runparams, max_length);
354 return PLAINTEXT_NEWLINE;
358 void InsetScript::docbook(XMLStream & xs, OutputParams const & runparams) const
361 switch (params_.type) {
362 case InsetScriptParams::Subscript:
363 cmdname = from_ascii("subscript");
365 case InsetScriptParams::Superscript:
366 cmdname = from_ascii("superscript");
370 xs << xml::StartTag(cmdname);
371 InsetText::docbook(xs, runparams);
372 xs << xml::EndTag(cmdname);
376 string InsetScript::contextMenuName() const
378 return "context-script";
382 string InsetScript::params2string(InsetScriptParams const & params)
391 void InsetScript::string2params(string const & in, InsetScriptParams & params)
393 params = InsetScriptParams();
398 istringstream data(in);
401 lex.setContext("InsetScript::string2params");
402 lex >> "script" >> "script";