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 "LaTeXFeatures.h"
24 #include "MetricsInfo.h"
26 #include "texstream.h"
28 #include "frontends/FontMetrics.h"
29 #include "frontends/Painter.h"
31 #include "support/debug.h"
32 #include "support/docstream.h"
33 #include "support/gettext.h"
34 #include "support/Translator.h"
42 typedef Translator<string, InsetIPADecoParams::Type> IPADecoTranslator;
43 typedef Translator<docstring, InsetIPADecoParams::Type> IPADecoTranslatorLoc;
45 IPADecoTranslator const init_ipadecotranslator()
47 IPADecoTranslator translator("toptiebar", InsetIPADecoParams::Toptiebar);
48 translator.addPair("bottomtiebar", InsetIPADecoParams::Bottomtiebar);
53 IPADecoTranslatorLoc const init_ipadecotranslator_loc()
55 IPADecoTranslatorLoc translator(_("Top tie bar"), InsetIPADecoParams::Toptiebar);
56 translator.addPair(_("Bottom tie bar"), InsetIPADecoParams::Bottomtiebar);
61 IPADecoTranslator const & ipadecotranslator()
63 static IPADecoTranslator const decotranslator =
64 init_ipadecotranslator();
65 return decotranslator;
69 IPADecoTranslatorLoc const & ipadecotranslator_loc()
71 static IPADecoTranslatorLoc const translator =
72 init_ipadecotranslator_loc();
77 typedef Translator<string, InsetIPAChar::Kind> IPACharTranslator;
79 IPACharTranslator const init_ipachartranslator()
81 IPACharTranslator translator("\\tone{51}", InsetIPAChar::TONE_FALLING);
82 translator.addPair("\\tone{15}", InsetIPAChar::TONE_RISING);
83 translator.addPair("\\tone{45}", InsetIPAChar::TONE_HIGH_RISING);
84 translator.addPair("\\tone{12}", InsetIPAChar::TONE_LOW_RISING);
85 translator.addPair("\\tone{454}", InsetIPAChar::TONE_HIGH_RISING_FALLING);
90 IPACharTranslator const & ipachartranslator()
92 static IPACharTranslator const chartranslator =
93 init_ipachartranslator();
94 return chartranslator;
100 InsetIPADecoParams::InsetIPADecoParams()
105 void InsetIPADecoParams::write(ostream & os) const
107 string const label = ipadecotranslator().find(type);
108 os << "IPADeco " << label << "\n";
112 void InsetIPADecoParams::read(Lexer & lex)
117 type = ipadecotranslator().find(label);
121 /////////////////////////////////////////////////////////////////////
125 /////////////////////////////////////////////////////////////////////
127 InsetIPADeco::InsetIPADeco(Buffer * buf, string const & label)
128 : InsetCollapsible(buf)
131 setFrameColor(Color_insetframe);
132 params_.type = ipadecotranslator().find(label);
136 InsetIPADeco::~InsetIPADeco()
140 docstring InsetIPADeco::layoutName() const
142 return from_ascii("IPADeco:" + ipadecotranslator().find(params_.type));
146 void InsetIPADeco::metrics(MetricsInfo & mi, Dimension & dim) const
148 InsetText::metrics(mi, dim);
150 if (params_.type == InsetIPADecoParams::Toptiebar) {
151 // consider width of the inset label
152 FontInfo font(getLayout().labelfont());
153 font.realize(sane_font);
159 docstring const label(1, char_type(0x2040));
160 theFontMetrics(font).rectText(label, w, a, d);
161 dim.asc += int(a * 0.5);
163 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
164 // consider width of the inset label
165 FontInfo font(getLayout().labelfont());
166 font.realize(sane_font);
172 docstring const label(1, char_type(0x203f));
173 theFontMetrics(font).rectText(label, w, a, d);
174 dim.des += int(d * 1.5);
179 void InsetIPADeco::draw(PainterInfo & pi, int x, int y) const
182 InsetCollapsible::draw(pi, x, y);
184 // draw the inset marker
185 drawMarkers(pi, x, y);
187 Dimension const dim = dimension(*pi.base.bv);
189 if (params_.type == InsetIPADecoParams::Toptiebar) {
190 FontInfo font(getLayout().labelfont());
191 font.realize(sane_font);
197 int asc = dim.ascent();
198 docstring const label(1, char_type(0x2040));
199 theFontMetrics(font).rectText(label, w, a, d);
200 int const ww = max(dim.wid, w);
201 pi.pain.rectText(x + (ww - w) / 2, y - int(asc / 2.5),
202 label, font, Color_none, Color_none);
205 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
206 FontInfo font(getLayout().labelfont());
207 font.realize(sane_font);
213 int desc = dim.descent();
214 docstring const label(1, char_type(0x203f));
215 theFontMetrics(font).rectText(label, w, a, d);
216 int const ww = max(dim.wid, w);
217 pi.pain.rectText(x + (ww - w) / 2, y + int(desc / 1.5),
218 label, font, Color_none, Color_none);
223 void InsetIPADeco::write(ostream & os) const
226 InsetCollapsible::write(os);
230 void InsetIPADeco::read(Lexer & lex)
233 InsetCollapsible::read(lex);
237 void InsetIPADeco::doDispatch(Cursor & cur, FuncRequest & cmd)
239 switch (cmd.action()) {
240 case LFUN_QUOTE_INSERT: {
241 FuncRequest fr(LFUN_SELF_INSERT, "\"");
242 InsetText::doDispatch(cur, fr);
246 InsetText::doDispatch(cur, cmd);
252 bool InsetIPADeco::getStatus(Cursor & cur, FuncRequest const & cmd,
253 FuncStatus & flag) const
255 switch (cmd.action()) {
256 case LFUN_SCRIPT_INSERT: {
257 if (cmd.argument() == "subscript") {
258 flag.setEnabled(false);
264 flag.setEnabled(true);
270 return InsetText::getStatus(cur, cmd, flag);
274 void InsetIPADeco::latex(otexstream & os, OutputParams const & runparams) const
276 if (params_.type == InsetIPADecoParams::Toptiebar)
277 os << "\\texttoptiebar{";
278 else if (params_.type == InsetIPADecoParams::Bottomtiebar)
279 os << "\\textbottomtiebar{";
280 InsetCollapsible::latex(os, runparams);
285 int InsetIPADeco::plaintext(odocstringstream & os,
286 OutputParams const & runparams, size_t max_length) const
288 odocstringstream ods;
289 int h = (int)(InsetCollapsible::plaintext(ods, runparams, max_length) / 2);
290 docstring result = ods.str();
291 docstring const before = result.substr(0, h);
292 docstring const after = result.substr(h, result.size());
294 if (params_.type == InsetIPADecoParams::Toptiebar) {
299 else if (params_.type == InsetIPADecoParams::Bottomtiebar) {
304 return result.size();
308 void InsetIPADeco::docbook(XMLStream & xs, OutputParams const & runparams) const
310 // The special combining character must be put in the middle, between the two other characters.
311 // It will not work if there is anything else than two pure characters, so going back to plaintext.
312 odocstringstream ods;
313 int h = (int)(InsetText::plaintext(ods, runparams) / 2);
314 docstring result = ods.str();
315 docstring const before = result.substr(0, h);
316 docstring const after = result.substr(h, result.size());
318 xs << XMLStream::ESCAPE_NONE << before;
319 if (params_.type == InsetIPADecoParams::Toptiebar)
320 xs << XMLStream::ESCAPE_NONE << "͡";
321 else if (params_.type == InsetIPADecoParams::Bottomtiebar)
322 xs << XMLStream::ESCAPE_NONE << "͜";
323 xs << XMLStream::ESCAPE_NONE << after;
327 docstring InsetIPADeco::xhtml(XMLStream & xs, OutputParams const & runparams) const
329 // FIXME: Like in plaintext, the combining characters "͡" (toptiebar)
330 // or "͜" (bottomtiebar) would need to be inserted just in the mid
331 // of the text string. (How) can this be done with the xhtml stream?
332 return InsetCollapsible::xhtml(xs, runparams);
336 docstring InsetIPADeco::toolTip(BufferView const &, int, int) const
338 return ipadecotranslator_loc().find(params_.type);
342 string InsetIPADeco::params2string(InsetIPADecoParams const & params)
345 data << "IPADeco" << ' ';
351 void InsetIPADeco::string2params(string const & in, InsetIPADecoParams & params)
353 params = InsetIPADecoParams();
358 istringstream data(in);
361 lex.setContext("InsetIPADeco::string2params");
362 lex >> "IPADeco" >> "toptiebar";
368 void InsetIPADeco::validate(LaTeXFeatures & features) const
370 features.require("tipa");
371 InsetText::validate(features);
375 bool InsetIPADeco::insetAllowed(InsetCode code) const
378 // code that is allowed
388 /////////////////////////////////////////////////////////////////////////
392 /////////////////////////////////////////////////////////////////////////
395 InsetIPAChar::InsetIPAChar(Kind k)
400 InsetIPAChar::Kind InsetIPAChar::kind() const
406 void InsetIPAChar::metrics(MetricsInfo & mi, Dimension & dim) const
408 frontend::FontMetrics const & fm =
409 theFontMetrics(mi.base.font);
410 dim.asc = fm.maxAscent();
411 dim.des = fm.maxDescent();
417 case TONE_HIGH_RISING:
418 case TONE_LOW_RISING:
419 case TONE_HIGH_RISING_FALLING:
423 docstring ds(s.begin(), s.end());
424 dim.wid = fm.width(ds);
428 void InsetIPAChar::draw(PainterInfo & pi, int x, int y) const
430 FontInfo font = pi.base.font;
431 frontend::FontMetrics const & fm =
432 theFontMetrics(font);
437 int w = fm.width(char_type('-'));
438 int h = fm.ascent(char_type('M'));
442 pi.pain.line(x2, y2, x2, y, Color_foreground);
443 pi.pain.line(x2, y, x, y2, Color_foreground);
448 int w = fm.width(char_type('-'));
449 int h = fm.ascent(char_type('M'));
453 pi.pain.line(x2, y, x2, y2, Color_foreground);
454 pi.pain.line(x2, y2, x, y, Color_foreground);
457 case TONE_HIGH_RISING:
459 int w = fm.width(char_type('-'));
460 int h = fm.ascent(char_type('M'));
463 int y3 = y - int(h * 0.75);
465 pi.pain.line(x2, y, x2, y2, Color_foreground);
466 pi.pain.line(x2, y2, x, y3, Color_foreground);
469 case TONE_LOW_RISING:
471 int w = fm.width(char_type('-'));
472 int h = fm.ascent(char_type('M'));
475 int y3 = y - int(h * 0.25);
477 pi.pain.line(x2, y, x2, y2, Color_foreground);
478 pi.pain.line(x2, y3, x, y, Color_foreground);
481 case TONE_HIGH_RISING_FALLING:
483 int w = fm.width(char_type('-'));
484 int h = fm.ascent(char_type('M'));
487 int x3 = x + int(w * 0.5);
488 int y3 = y - int(h * 0.75);
490 pi.pain.line(x2, y, x2, y2, Color_foreground);
491 pi.pain.line(x2, y3, x3, y2, Color_foreground);
492 pi.pain.line(x3, y2, x, y3, Color_foreground);
499 void InsetIPAChar::write(ostream & os) const
501 string const command = ipachartranslator().find(kind_);
502 if (command.empty()) {
503 LYXERR0("InsetIPAChar::write: Unknown type");
506 os << "\\IPAChar " << command << "\n";
510 void InsetIPAChar::read(Lexer & lex)
513 string const command = lex.getString();
514 kind_ = ipachartranslator().find(command);
518 void InsetIPAChar::latex(otexstream & os,
519 OutputParams const &) const
521 string const command = ipachartranslator().find(kind_);
526 int InsetIPAChar::plaintext(odocstringstream & os, OutputParams const &, size_t) const
537 case TONE_HIGH_RISING:
541 case TONE_LOW_RISING:
545 case TONE_HIGH_RISING_FALLING:
555 void InsetIPAChar::docbook(XMLStream & xs, OutputParams const &) const
559 xs << XMLStream::ESCAPE_NONE << "˥";
560 xs << XMLStream::ESCAPE_NONE << "˩";
563 xs << XMLStream::ESCAPE_NONE << "˩";
564 xs << XMLStream::ESCAPE_NONE << "˥";
566 case TONE_HIGH_RISING:
567 xs << XMLStream::ESCAPE_NONE << "˧";
568 xs << XMLStream::ESCAPE_NONE << "˥";
570 case TONE_LOW_RISING:
571 xs << XMLStream::ESCAPE_NONE << "˩";
572 xs << XMLStream::ESCAPE_NONE << "˧";
574 case TONE_HIGH_RISING_FALLING:
575 xs << XMLStream::ESCAPE_NONE << "˨";
576 xs << XMLStream::ESCAPE_NONE << "˥";
577 xs << XMLStream::ESCAPE_NONE << "˨";
583 docstring InsetIPAChar::xhtml(XMLStream & xs, OutputParams const &) const
587 xs << XMLStream::ESCAPE_NONE << "˥"
588 << XMLStream::ESCAPE_NONE << "˩";
591 xs << XMLStream::ESCAPE_NONE << "˩"
592 << XMLStream::ESCAPE_NONE << "˥";
594 case TONE_HIGH_RISING:
595 xs << XMLStream::ESCAPE_NONE << "˧"
596 << XMLStream::ESCAPE_NONE << "˥";
598 case TONE_LOW_RISING:
599 xs << XMLStream::ESCAPE_NONE << "˩"
600 << XMLStream::ESCAPE_NONE << "˧";
602 case TONE_HIGH_RISING_FALLING:
603 xs << XMLStream::ESCAPE_NONE << "˨"
604 << XMLStream::ESCAPE_NONE << "˥"
605 << XMLStream::ESCAPE_NONE << "˨";
612 void InsetIPAChar::toString(odocstream & os) const
614 odocstringstream ods;
615 plaintext(ods, OutputParams(0));
620 void InsetIPAChar::forOutliner(docstring & os, size_t const, bool const) const
622 odocstringstream ods;
623 plaintext(ods, OutputParams(0));
628 void InsetIPAChar::validate(LaTeXFeatures & features) const
633 case TONE_HIGH_RISING:
634 case TONE_LOW_RISING:
635 case TONE_HIGH_RISING_FALLING:
636 features.require("tone");