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);
286 int InsetIPADeco::plaintext(odocstringstream & os,
287 OutputParams const & runparams, size_t max_length) const
289 odocstringstream ods;
290 int h = (int)(InsetCollapsible::plaintext(ods, runparams, max_length) / 2);
291 docstring result = ods.str();
292 docstring const before = result.substr(0, h);
293 docstring const after = result.substr(h, result.size());
295 if (params_.type == InsetIPADecoParams::Toptiebar) {
300 else if (params_.type == InsetIPADecoParams::Bottomtiebar) {
305 return result.size();
309 void InsetIPADeco::docbook(XMLStream & xs, OutputParams const & runparams) const
311 // The special combining character must be put in the middle, between the two other characters.
312 // It will not work if there is anything else than two pure characters, so going back to plaintext.
313 odocstringstream ods;
314 int h = (int)(InsetText::plaintext(ods, runparams) / 2);
315 docstring result = ods.str();
316 docstring const before = result.substr(0, h);
317 docstring const after = result.substr(h, result.size());
319 xs << XMLStream::ESCAPE_NONE << before;
320 if (params_.type == InsetIPADecoParams::Toptiebar)
321 xs << XMLStream::ESCAPE_NONE << "͡";
322 else if (params_.type == InsetIPADecoParams::Bottomtiebar)
323 xs << XMLStream::ESCAPE_NONE << "͜";
324 xs << XMLStream::ESCAPE_NONE << after;
328 docstring InsetIPADeco::xhtml(XMLStream & xs, OutputParams const & runparams) const
330 // FIXME: Like in plaintext, the combining characters "͡" (toptiebar)
331 // or "͜" (bottomtiebar) would need to be inserted just in the mid
332 // of the text string. (How) can this be done with the xhtml stream?
333 return InsetCollapsible::xhtml(xs, runparams);
337 docstring InsetIPADeco::toolTip(BufferView const &, int, int) const
339 return ipadecotranslator_loc().find(params_.type);
343 string InsetIPADeco::params2string(InsetIPADecoParams const & params)
346 data << "IPADeco" << ' ';
352 void InsetIPADeco::string2params(string const & in, InsetIPADecoParams & params)
354 params = InsetIPADecoParams();
359 istringstream data(in);
362 lex.setContext("InsetIPADeco::string2params");
363 lex >> "IPADeco" >> "toptiebar";
369 void InsetIPADeco::validate(LaTeXFeatures & features) const
371 features.require("tipa");
372 InsetText::validate(features);
376 bool InsetIPADeco::insetAllowed(InsetCode code) const
379 // code that is allowed
389 /////////////////////////////////////////////////////////////////////////
393 /////////////////////////////////////////////////////////////////////////
396 InsetIPAChar::InsetIPAChar(Kind k)
397 : Inset(nullptr), kind_(k)
401 InsetIPAChar::Kind InsetIPAChar::kind() const
407 void InsetIPAChar::metrics(MetricsInfo & mi, Dimension & dim) const
409 frontend::FontMetrics const & fm =
410 theFontMetrics(mi.base.font);
411 dim.asc = fm.maxAscent();
412 dim.des = fm.maxDescent();
418 case TONE_HIGH_RISING:
419 case TONE_LOW_RISING:
420 case TONE_HIGH_RISING_FALLING:
424 docstring ds(s.begin(), s.end());
425 dim.wid = fm.width(ds);
429 void InsetIPAChar::draw(PainterInfo & pi, int x, int y) const
431 FontInfo font = pi.base.font;
432 frontend::FontMetrics const & fm =
433 theFontMetrics(font);
438 int w = fm.width(char_type('-'));
439 int h = fm.ascent(char_type('M'));
443 pi.pain.line(x2, y2, x2, y, Color_foreground);
444 pi.pain.line(x2, y, x, y2, Color_foreground);
449 int w = fm.width(char_type('-'));
450 int h = fm.ascent(char_type('M'));
454 pi.pain.line(x2, y, x2, y2, Color_foreground);
455 pi.pain.line(x2, y2, x, y, Color_foreground);
458 case TONE_HIGH_RISING:
460 int w = fm.width(char_type('-'));
461 int h = fm.ascent(char_type('M'));
464 int y3 = y - int(h * 0.75);
466 pi.pain.line(x2, y, x2, y2, Color_foreground);
467 pi.pain.line(x2, y2, x, y3, Color_foreground);
470 case TONE_LOW_RISING:
472 int w = fm.width(char_type('-'));
473 int h = fm.ascent(char_type('M'));
476 int y3 = y - int(h * 0.25);
478 pi.pain.line(x2, y, x2, y2, Color_foreground);
479 pi.pain.line(x2, y3, x, y, Color_foreground);
482 case TONE_HIGH_RISING_FALLING:
484 int w = fm.width(char_type('-'));
485 int h = fm.ascent(char_type('M'));
488 int x3 = x + int(w * 0.5);
489 int y3 = y - int(h * 0.75);
491 pi.pain.line(x2, y, x2, y2, Color_foreground);
492 pi.pain.line(x2, y3, x3, y2, Color_foreground);
493 pi.pain.line(x3, y2, x, y3, Color_foreground);
500 void InsetIPAChar::write(ostream & os) const
502 string const command = ipachartranslator().find(kind_);
503 if (command.empty()) {
504 LYXERR0("InsetIPAChar::write: Unknown type");
507 os << "\\IPAChar " << command << "\n";
511 void InsetIPAChar::read(Lexer & lex)
514 string const command = lex.getString();
515 kind_ = ipachartranslator().find(command);
519 void InsetIPAChar::latex(otexstream & os,
520 OutputParams const &) const
522 string const command = ipachartranslator().find(kind_);
527 int InsetIPAChar::plaintext(odocstringstream & os, OutputParams const &, size_t) const
538 case TONE_HIGH_RISING:
542 case TONE_LOW_RISING:
546 case TONE_HIGH_RISING_FALLING:
556 void InsetIPAChar::docbook(XMLStream & xs, OutputParams const &) const
560 xs << XMLStream::ESCAPE_NONE << "˥";
561 xs << XMLStream::ESCAPE_NONE << "˩";
564 xs << XMLStream::ESCAPE_NONE << "˩";
565 xs << XMLStream::ESCAPE_NONE << "˥";
567 case TONE_HIGH_RISING:
568 xs << XMLStream::ESCAPE_NONE << "˧";
569 xs << XMLStream::ESCAPE_NONE << "˥";
571 case TONE_LOW_RISING:
572 xs << XMLStream::ESCAPE_NONE << "˩";
573 xs << XMLStream::ESCAPE_NONE << "˧";
575 case TONE_HIGH_RISING_FALLING:
576 xs << XMLStream::ESCAPE_NONE << "˨";
577 xs << XMLStream::ESCAPE_NONE << "˥";
578 xs << XMLStream::ESCAPE_NONE << "˨";
584 docstring InsetIPAChar::xhtml(XMLStream & xs, OutputParams const &) const
588 xs << XMLStream::ESCAPE_NONE << "˥"
589 << XMLStream::ESCAPE_NONE << "˩";
592 xs << XMLStream::ESCAPE_NONE << "˩"
593 << XMLStream::ESCAPE_NONE << "˥";
595 case TONE_HIGH_RISING:
596 xs << XMLStream::ESCAPE_NONE << "˧"
597 << XMLStream::ESCAPE_NONE << "˥";
599 case TONE_LOW_RISING:
600 xs << XMLStream::ESCAPE_NONE << "˩"
601 << XMLStream::ESCAPE_NONE << "˧";
603 case TONE_HIGH_RISING_FALLING:
604 xs << XMLStream::ESCAPE_NONE << "˨"
605 << XMLStream::ESCAPE_NONE << "˥"
606 << XMLStream::ESCAPE_NONE << "˨";
613 void InsetIPAChar::toString(odocstream & os) const
615 odocstringstream ods;
616 plaintext(ods, OutputParams(0));
621 void InsetIPAChar::forOutliner(docstring & os, size_t const, bool const) const
623 odocstringstream ods;
624 plaintext(ods, OutputParams(0));
629 void InsetIPAChar::validate(LaTeXFeatures & features) const
634 case TONE_HIGH_RISING:
635 case TONE_LOW_RISING:
636 case TONE_HIGH_RISING_FALLING:
637 features.require("tone");