2 * \file InsetIPAMacro.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Jürgen Spitzmüller
8 * Full author contact details are available in file CREDITS.
13 #include "InsetIPAMacro.h"
16 #include "BufferParams.h"
17 #include "Dimension.h"
20 #include "FuncRequest.h"
21 #include "FuncStatus.h"
22 #include "InsetLayout.h"
23 #include "LaTeXFeatures.h"
25 #include "MetricsInfo.h"
27 #include "texstream.h"
29 #include "frontends/FontMetrics.h"
30 #include "frontends/Painter.h"
32 #include "support/debug.h"
33 #include "support/docstream.h"
34 #include "support/gettext.h"
35 #include "support/Translator.h"
43 typedef Translator<string, InsetIPADecoParams::Type> IPADecoTranslator;
44 typedef Translator<docstring, InsetIPADecoParams::Type> IPADecoTranslatorLoc;
46 IPADecoTranslator const init_ipadecotranslator()
48 IPADecoTranslator translator("toptiebar", InsetIPADecoParams::Toptiebar);
49 translator.addPair("bottomtiebar", InsetIPADecoParams::Bottomtiebar);
54 IPADecoTranslatorLoc const init_ipadecotranslator_loc()
56 IPADecoTranslatorLoc translator(_("Top tie bar"), InsetIPADecoParams::Toptiebar);
57 translator.addPair(_("Bottom tie bar"), InsetIPADecoParams::Bottomtiebar);
62 IPADecoTranslator const & ipadecotranslator()
64 static IPADecoTranslator const decotranslator =
65 init_ipadecotranslator();
66 return decotranslator;
70 IPADecoTranslatorLoc const & ipadecotranslator_loc()
72 static IPADecoTranslatorLoc const translator =
73 init_ipadecotranslator_loc();
78 typedef Translator<string, InsetIPAChar::Kind> IPACharTranslator;
80 IPACharTranslator const init_ipachartranslator()
82 IPACharTranslator translator("\\tone{51}", InsetIPAChar::TONE_FALLING);
83 translator.addPair("\\tone{15}", InsetIPAChar::TONE_RISING);
84 translator.addPair("\\tone{45}", InsetIPAChar::TONE_HIGH_RISING);
85 translator.addPair("\\tone{12}", InsetIPAChar::TONE_LOW_RISING);
86 translator.addPair("\\tone{454}", InsetIPAChar::TONE_HIGH_RISING_FALLING);
91 IPACharTranslator const & ipachartranslator()
93 static IPACharTranslator const chartranslator =
94 init_ipachartranslator();
95 return chartranslator;
101 InsetIPADecoParams::InsetIPADecoParams()
106 void InsetIPADecoParams::write(ostream & os) const
108 string const label = ipadecotranslator().find(type);
109 os << "IPADeco " << label << "\n";
113 void InsetIPADecoParams::read(Lexer & lex)
118 type = ipadecotranslator().find(label);
122 /////////////////////////////////////////////////////////////////////
126 /////////////////////////////////////////////////////////////////////
128 InsetIPADeco::InsetIPADeco(Buffer * buf, string const & label)
129 : InsetCollapsible(buf)
132 setFrameColor(Color_insetframe);
133 params_.type = ipadecotranslator().find(label);
137 InsetIPADeco::~InsetIPADeco()
141 docstring InsetIPADeco::layoutName() const
143 return from_ascii("IPADeco:" + ipadecotranslator().find(params_.type));
147 void InsetIPADeco::metrics(MetricsInfo & mi, Dimension & dim) const
149 InsetText::metrics(mi, dim);
151 if (params_.type == InsetIPADecoParams::Toptiebar) {
152 // consider width of the inset label
153 FontInfo font(getLayout().labelfont());
154 font.realize(sane_font);
160 docstring const label(1, char_type(0x2040));
161 theFontMetrics(font).rectText(label, w, a, d);
162 dim.asc += int(a * 0.5);
164 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
165 // consider width of the inset label
166 FontInfo font(getLayout().labelfont());
167 font.realize(sane_font);
173 docstring const label(1, char_type(0x203f));
174 theFontMetrics(font).rectText(label, w, a, d);
175 dim.des += int(d * 1.5);
180 void InsetIPADeco::draw(PainterInfo & pi, int x, int y) const
183 InsetCollapsible::draw(pi, x, y);
185 // draw the inset marker
186 drawMarkers(pi, x, y);
188 Dimension const dim = dimension(*pi.base.bv);
190 if (params_.type == InsetIPADecoParams::Toptiebar) {
191 FontInfo font(getLayout().labelfont());
192 font.realize(sane_font);
198 int asc = dim.ascent();
199 docstring const label(1, char_type(0x2040));
200 theFontMetrics(font).rectText(label, w, a, d);
201 int const ww = max(dim.wid, w);
202 pi.pain.rectText(x + (ww - w) / 2, y - int(asc / 2.5),
203 label, font, Color_none, Color_none);
206 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
207 FontInfo font(getLayout().labelfont());
208 font.realize(sane_font);
214 int desc = dim.descent();
215 docstring const label(1, char_type(0x203f));
216 theFontMetrics(font).rectText(label, w, a, d);
217 int const ww = max(dim.wid, w);
218 pi.pain.rectText(x + (ww - w) / 2, y + int(desc / 1.5),
219 label, font, Color_none, Color_none);
224 void InsetIPADeco::write(ostream & os) const
227 InsetCollapsible::write(os);
231 void InsetIPADeco::read(Lexer & lex)
234 InsetCollapsible::read(lex);
238 void InsetIPADeco::doDispatch(Cursor & cur, FuncRequest & cmd)
240 switch (cmd.action()) {
241 case LFUN_QUOTE_INSERT: {
242 FuncRequest fr(LFUN_SELF_INSERT, "\"");
243 InsetText::doDispatch(cur, fr);
247 InsetText::doDispatch(cur, cmd);
253 bool InsetIPADeco::getStatus(Cursor & cur, FuncRequest const & cmd,
254 FuncStatus & flag) const
256 switch (cmd.action()) {
257 case LFUN_SCRIPT_INSERT: {
258 if (cmd.argument() == "subscript") {
259 flag.setEnabled(false);
265 flag.setEnabled(true);
271 return InsetText::getStatus(cur, cmd, flag);
275 void InsetIPADeco::latex(otexstream & os, OutputParams const & runparams) const
277 if (params_.type == InsetIPADecoParams::Toptiebar)
278 os << "\\texttoptiebar{";
279 else if (params_.type == InsetIPADecoParams::Bottomtiebar)
280 os << "\\textbottomtiebar{";
281 InsetCollapsible::latex(os, runparams);
287 std::pair<docstring, docstring> splitPlainTextInHalves(
288 const InsetIPADeco * inset, OutputParams const & runparams,
289 size_t max_length = INT_MAX)
291 odocstringstream ods;
292 int h = inset->InsetCollapsible::plaintext(ods, runparams, max_length) / 2;
293 docstring result = ods.str();
294 docstring const before = result.substr(0, h);
295 docstring const after = result.substr(h, result.size());
296 return {before, after};
301 int InsetIPADeco::plaintext(odocstringstream & os,
302 OutputParams const & runparams, size_t max_length) const
306 tie(before, after) = splitPlainTextInHalves(this, runparams, max_length);
308 if (params_.type == InsetIPADecoParams::Toptiebar) {
313 else if (params_.type == InsetIPADecoParams::Bottomtiebar) {
318 return before.size() + after.size();
322 void InsetIPADeco::docbook(XMLStream & xs, OutputParams const & runparams) const
324 // The special combining character must be put in the middle, between the two other characters.
325 // It will not work if there is anything else than two pure characters, so going back to plaintext.
328 tie(before, after) = splitPlainTextInHalves(this, runparams);
330 xs << XMLStream::ESCAPE_NONE << before;
331 if (params_.type == InsetIPADecoParams::Toptiebar)
332 xs << XMLStream::ESCAPE_NONE << "͡";
333 else if (params_.type == InsetIPADecoParams::Bottomtiebar)
334 xs << XMLStream::ESCAPE_NONE << "͜";
335 xs << XMLStream::ESCAPE_NONE << after;
339 docstring InsetIPADeco::xhtml(XMLStream & xs, OutputParams const & runparams) const
341 // The DocBook encoding for this inset has no DocBook tag, but sheer XML (relying on a plaintext
342 // transformation of the inset).
343 docbook(xs, runparams);
348 docstring InsetIPADeco::toolTip(BufferView const &, int, int) const
350 return ipadecotranslator_loc().find(params_.type);
354 string InsetIPADeco::params2string(InsetIPADecoParams const & params)
357 data << "IPADeco" << ' ';
363 void InsetIPADeco::string2params(string const & in, InsetIPADecoParams & params)
365 params = InsetIPADecoParams();
370 istringstream data(in);
373 lex.setContext("InsetIPADeco::string2params");
374 lex >> "IPADeco" >> "toptiebar";
380 void InsetIPADeco::validate(LaTeXFeatures & features) const
382 features.require("tipa");
383 InsetText::validate(features);
387 bool InsetIPADeco::insetAllowed(InsetCode code) const
390 // code that is allowed
400 /////////////////////////////////////////////////////////////////////////
404 /////////////////////////////////////////////////////////////////////////
407 InsetIPAChar::InsetIPAChar(Kind k)
408 : Inset(nullptr), kind_(k)
412 InsetIPAChar::Kind InsetIPAChar::kind() const
418 void InsetIPAChar::metrics(MetricsInfo & mi, Dimension & dim) const
420 frontend::FontMetrics const & fm =
421 theFontMetrics(mi.base.font);
422 dim.asc = fm.maxAscent();
423 dim.des = fm.maxDescent();
429 case TONE_HIGH_RISING:
430 case TONE_LOW_RISING:
431 case TONE_HIGH_RISING_FALLING:
435 docstring ds(s.begin(), s.end());
436 dim.wid = fm.width(ds);
440 void InsetIPAChar::draw(PainterInfo & pi, int x, int y) const
442 FontInfo font = pi.base.font;
443 frontend::FontMetrics const & fm =
444 theFontMetrics(font);
449 int w = fm.width(char_type('-'));
450 int h = fm.ascent(char_type('M'));
454 pi.pain.line(x2, y2, x2, y, Color_foreground);
455 pi.pain.line(x2, y, x, y2, Color_foreground);
460 int w = fm.width(char_type('-'));
461 int h = fm.ascent(char_type('M'));
465 pi.pain.line(x2, y, x2, y2, Color_foreground);
466 pi.pain.line(x2, y2, x, y, Color_foreground);
469 case TONE_HIGH_RISING:
471 int w = fm.width(char_type('-'));
472 int h = fm.ascent(char_type('M'));
475 int y3 = y - int(h * 0.75);
477 pi.pain.line(x2, y, x2, y2, Color_foreground);
478 pi.pain.line(x2, y2, x, y3, Color_foreground);
481 case TONE_LOW_RISING:
483 int w = fm.width(char_type('-'));
484 int h = fm.ascent(char_type('M'));
487 int y3 = y - int(h * 0.25);
489 pi.pain.line(x2, y, x2, y2, Color_foreground);
490 pi.pain.line(x2, y3, x, y, Color_foreground);
493 case TONE_HIGH_RISING_FALLING:
495 int w = fm.width(char_type('-'));
496 int h = fm.ascent(char_type('M'));
499 int x3 = x + int(w * 0.5);
500 int y3 = y - int(h * 0.75);
502 pi.pain.line(x2, y, x2, y2, Color_foreground);
503 pi.pain.line(x2, y3, x3, y2, Color_foreground);
504 pi.pain.line(x3, y2, x, y3, Color_foreground);
511 void InsetIPAChar::write(ostream & os) const
513 string const command = ipachartranslator().find(kind_);
514 if (command.empty()) {
515 LYXERR0("InsetIPAChar::write: Unknown type");
518 os << "\\IPAChar " << command << "\n";
522 void InsetIPAChar::read(Lexer & lex)
525 string const command = lex.getString();
526 kind_ = ipachartranslator().find(command);
530 void InsetIPAChar::latex(otexstream & os,
531 OutputParams const &) const
533 string const command = ipachartranslator().find(kind_);
538 int InsetIPAChar::plaintext(odocstringstream & os, OutputParams const &, size_t) const
549 case TONE_HIGH_RISING:
553 case TONE_LOW_RISING:
557 case TONE_HIGH_RISING_FALLING:
568 std::string ipaCharToXMLEntity(InsetIPAChar::Kind kind) {
570 case InsetIPAChar::Kind::TONE_FALLING:
571 return "˥˩";
572 case InsetIPAChar::Kind::TONE_RISING:
573 return "˩˥";
574 case InsetIPAChar::Kind::TONE_HIGH_RISING:
575 return "˧˥";
576 case InsetIPAChar::Kind::TONE_LOW_RISING:
577 return "˩˧";
578 case InsetIPAChar::Kind::TONE_HIGH_RISING_FALLING:
579 return "˨˥˨";
586 void InsetIPAChar::docbook(XMLStream & xs, OutputParams const &) const
588 xs << XMLStream::ESCAPE_NONE << from_ascii(ipaCharToXMLEntity(kind()));
592 docstring InsetIPAChar::xhtml(XMLStream & xs, OutputParams const &) const
594 xs << XMLStream::ESCAPE_NONE << from_ascii(ipaCharToXMLEntity(kind()));
599 void InsetIPAChar::toString(odocstream & os) const
601 odocstringstream ods;
602 plaintext(ods, OutputParams(0));
607 void InsetIPAChar::forOutliner(docstring & os, size_t const, bool const) const
609 odocstringstream ods;
610 plaintext(ods, OutputParams(0));
615 void InsetIPAChar::validate(LaTeXFeatures & features) const
620 case TONE_HIGH_RISING:
621 case TONE_LOW_RISING:
622 case TONE_HIGH_RISING_FALLING:
623 features.require("tone");