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"
25 #include "output_xhtml.h"
27 #include "frontends/FontMetrics.h"
28 #include "frontends/Painter.h"
30 #include "support/debug.h"
31 #include "support/docstream.h"
32 #include "support/gettext.h"
33 #include "support/Translator.h"
41 typedef Translator<string, InsetIPADecoParams::Type> IPADecoTranslator;
42 typedef Translator<docstring, InsetIPADecoParams::Type> IPADecoTranslatorLoc;
44 IPADecoTranslator const init_ipadecotranslator()
46 IPADecoTranslator translator("toptiebar", InsetIPADecoParams::Toptiebar);
47 translator.addPair("bottomtiebar", InsetIPADecoParams::Bottomtiebar);
52 IPADecoTranslatorLoc const init_ipadecotranslator_loc()
54 IPADecoTranslatorLoc translator(_("Top tie bar"), InsetIPADecoParams::Toptiebar);
55 translator.addPair(_("Bottom tie bar"), InsetIPADecoParams::Bottomtiebar);
60 IPADecoTranslator const & ipadecotranslator()
62 static IPADecoTranslator const decotranslator =
63 init_ipadecotranslator();
64 return decotranslator;
68 IPADecoTranslatorLoc const & ipadecotranslator_loc()
70 static IPADecoTranslatorLoc const translator =
71 init_ipadecotranslator_loc();
76 typedef Translator<string, InsetIPAChar::Kind> IPACharTranslator;
78 IPACharTranslator const init_ipachartranslator()
80 IPACharTranslator translator("\\tone{51}", InsetIPAChar::TONE_FALLING);
81 translator.addPair("\\tone{15}", InsetIPAChar::TONE_RISING);
82 translator.addPair("\\tone{45}", InsetIPAChar::TONE_HIGH_RISING);
83 translator.addPair("\\tone{12}", InsetIPAChar::TONE_LOW_RISING);
84 translator.addPair("\\tone{454}", InsetIPAChar::TONE_HIGH_RISING_FALLING);
89 IPACharTranslator const & ipachartranslator()
91 static IPACharTranslator const chartranslator =
92 init_ipachartranslator();
93 return chartranslator;
99 InsetIPADecoParams::InsetIPADecoParams()
104 void InsetIPADecoParams::write(ostream & os) const
106 string const label = ipadecotranslator().find(type);
107 os << "IPADeco " << label << "\n";
111 void InsetIPADecoParams::read(Lexer & lex)
116 type = ipadecotranslator().find(label);
120 /////////////////////////////////////////////////////////////////////
124 /////////////////////////////////////////////////////////////////////
126 InsetIPADeco::InsetIPADeco(Buffer * buf, string const & label)
127 : InsetCollapsable(buf)
130 setFrameColor(Color_insetframe);
131 params_.type = ipadecotranslator().find(label);
135 InsetIPADeco::~InsetIPADeco()
139 docstring InsetIPADeco::layoutName() const
141 return from_ascii("IPADeco:" + ipadecotranslator().find(params_.type));
145 void InsetIPADeco::metrics(MetricsInfo & mi, Dimension & dim) const
147 InsetText::metrics(mi, dim);
149 if (params_.type == InsetIPADecoParams::Toptiebar) {
150 // consider width of the inset label
151 FontInfo font(getLayout().labelfont());
152 font.realize(sane_font);
158 docstring const label(1, char_type(0x2040));
159 theFontMetrics(font).rectText(label, w, a, d);
160 dim.asc += int(a * 0.5);
162 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
163 // consider width of the inset label
164 FontInfo font(getLayout().labelfont());
165 font.realize(sane_font);
171 docstring const label(1, char_type(0x203f));
172 theFontMetrics(font).rectText(label, w, a, d);
173 dim.des += int(d * 1.5);
176 // cache the inset dimension
177 setDimCache(mi, dim);
181 void InsetIPADeco::draw(PainterInfo & pi, int x, int y) const
184 InsetCollapsable::draw(pi, x, y);
186 // draw the inset marker
187 drawMarkers(pi, x, y);
189 Dimension const dim = Inset::dimension(*pi.base.bv);
191 if (params_.type == InsetIPADecoParams::Toptiebar) {
192 FontInfo font(getLayout().labelfont());
193 font.realize(sane_font);
199 int asc = dim.ascent();
200 docstring const label(1, char_type(0x2040));
201 theFontMetrics(font).rectText(label, w, a, d);
202 int const ww = max(dim.wid, w);
203 pi.pain.rectText(x + (ww - w) / 2, y - int(asc / 2.5),
204 label, font, Color_none, Color_none);
207 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
208 FontInfo font(getLayout().labelfont());
209 font.realize(sane_font);
215 int desc = dim.descent();
216 docstring const label(1, char_type(0x203f));
217 theFontMetrics(font).rectText(label, w, a, d);
218 int const ww = max(dim.wid, w);
219 pi.pain.rectText(x + (ww - w) / 2, y + int(desc / 1.5),
220 label, font, Color_none, Color_none);
225 void InsetIPADeco::write(ostream & os) const
228 InsetCollapsable::write(os);
232 void InsetIPADeco::read(Lexer & lex)
235 InsetCollapsable::read(lex);
239 void InsetIPADeco::doDispatch(Cursor & cur, FuncRequest & cmd)
241 switch (cmd.action()) {
242 case LFUN_QUOTE_INSERT: {
243 FuncRequest fr(LFUN_SELF_INSERT, "\"");
244 InsetText::doDispatch(cur, fr);
248 InsetText::doDispatch(cur, cmd);
254 bool InsetIPADeco::getStatus(Cursor & cur, FuncRequest const & cmd,
255 FuncStatus & flag) const
257 switch (cmd.action()) {
258 case LFUN_SCRIPT_INSERT: {
259 if (cmd.argument() == "subscript") {
260 flag.setEnabled(false);
266 flag.setEnabled(true);
272 return InsetText::getStatus(cur, cmd, flag);
276 void InsetIPADeco::latex(otexstream & os, OutputParams const & runparams) const
278 if (params_.type == InsetIPADecoParams::Toptiebar)
279 os << "\\texttoptiebar{";
280 else if (params_.type == InsetIPADecoParams::Bottomtiebar)
281 os << "\\textbottomtiebar{";
282 InsetCollapsable::latex(os, runparams);
287 int InsetIPADeco::plaintext(odocstringstream & os,
288 OutputParams const & runparams, size_t max_length) const
290 odocstringstream ods;
291 int h = (int)(InsetCollapsable::plaintext(ods, runparams, max_length) / 2);
292 docstring result = ods.str();
293 docstring const before = result.substr(0, h);
294 docstring const after = result.substr(h, result.size());
296 if (params_.type == InsetIPADecoParams::Toptiebar) {
301 else if (params_.type == InsetIPADecoParams::Bottomtiebar) {
306 return result.size();
310 int InsetIPADeco::docbook(odocstream & os, OutputParams const & runparams) const
312 // FIXME: Any docbook option here?
313 return InsetCollapsable::docbook(os, runparams);
317 docstring InsetIPADeco::xhtml(XHTMLStream & xs, OutputParams const & runparams) const
319 // FIXME: Like in plaintext, the combining characters "͡" (toptiebar)
320 // or "͜" (bottomtiebar) would need to be inserted just in the mid
321 // of the text string. (How) can this be done with the xhtml stream?
322 return InsetCollapsable::xhtml(xs, runparams);
326 docstring InsetIPADeco::toolTip(BufferView const &, int, int) const
328 return ipadecotranslator_loc().find(params_.type);
332 string InsetIPADeco::params2string(InsetIPADecoParams const & params)
335 data << "IPADeco" << ' ';
341 void InsetIPADeco::string2params(string const & in, InsetIPADecoParams & params)
343 params = InsetIPADecoParams();
348 istringstream data(in);
351 lex.setContext("InsetIPADeco::string2params");
352 lex >> "IPADeco" >> "toptiebar";
358 void InsetIPADeco::validate(LaTeXFeatures & features) const
360 features.require("tipa");
361 InsetText::validate(features);
365 bool InsetIPADeco::insetAllowed(InsetCode code) const
368 // code that is allowed
378 /////////////////////////////////////////////////////////////////////////
382 /////////////////////////////////////////////////////////////////////////
385 InsetIPAChar::InsetIPAChar(Kind k)
390 InsetIPAChar::Kind InsetIPAChar::kind() const
396 void InsetIPAChar::metrics(MetricsInfo & mi, Dimension & dim) const
398 frontend::FontMetrics const & fm =
399 theFontMetrics(mi.base.font);
400 dim.asc = fm.maxAscent();
401 dim.des = fm.maxDescent();
407 case TONE_HIGH_RISING:
408 case TONE_LOW_RISING:
409 case TONE_HIGH_RISING_FALLING:
413 docstring ds(s.begin(), s.end());
414 dim.wid = fm.width(ds);
415 setDimCache(mi, dim);
419 void InsetIPAChar::draw(PainterInfo & pi, int x, int y) const
421 FontInfo font = pi.base.font;
422 frontend::FontMetrics const & fm =
423 theFontMetrics(font);
428 int w = fm.width(char_type('-'));
429 int h = fm.ascent(char_type('M'));
433 pi.pain.line(x2, y2, x2, y, Color_foreground);
434 pi.pain.line(x2, y, x, y2, Color_foreground);
439 int w = fm.width(char_type('-'));
440 int h = fm.ascent(char_type('M'));
444 pi.pain.line(x2, y, x2, y2, Color_foreground);
445 pi.pain.line(x2, y2, x, y, Color_foreground);
448 case TONE_HIGH_RISING:
450 int w = fm.width(char_type('-'));
451 int h = fm.ascent(char_type('M'));
454 int y3 = y - int(h * 0.75);
456 pi.pain.line(x2, y, x2, y2, Color_foreground);
457 pi.pain.line(x2, y2, x, y3, Color_foreground);
460 case TONE_LOW_RISING:
462 int w = fm.width(char_type('-'));
463 int h = fm.ascent(char_type('M'));
466 int y3 = y - int(h * 0.25);
468 pi.pain.line(x2, y, x2, y2, Color_foreground);
469 pi.pain.line(x2, y3, x, y, Color_foreground);
472 case TONE_HIGH_RISING_FALLING:
474 int w = fm.width(char_type('-'));
475 int h = fm.ascent(char_type('M'));
478 int x3 = x + int(w * 0.5);
479 int y3 = y - int(h * 0.75);
481 pi.pain.line(x2, y, x2, y2, Color_foreground);
482 pi.pain.line(x2, y3, x3, y2, Color_foreground);
483 pi.pain.line(x3, y2, x, y3, Color_foreground);
490 void InsetIPAChar::write(ostream & os) const
492 string const command = ipachartranslator().find(kind_);
493 if (command.empty()) {
494 LYXERR0("InsetIPAChar::write: Unknown type");
497 os << "\\IPAChar " << command << "\n";
501 void InsetIPAChar::read(Lexer & lex)
504 string const command = lex.getString();
505 kind_ = ipachartranslator().find(command);
509 void InsetIPAChar::latex(otexstream & os,
510 OutputParams const &) const
512 string const command = ipachartranslator().find(kind_);
517 int InsetIPAChar::plaintext(odocstringstream & os, OutputParams const &, size_t) const
528 case TONE_HIGH_RISING:
532 case TONE_LOW_RISING:
536 case TONE_HIGH_RISING_FALLING:
546 int InsetIPAChar::docbook(odocstream & /*os*/, OutputParams const &) const
550 LYXERR0("IPA tone macros not yet implemented with DocBook!");
553 case TONE_HIGH_RISING:
554 case TONE_LOW_RISING:
555 case TONE_HIGH_RISING_FALLING:
562 docstring InsetIPAChar::xhtml(XHTMLStream & xs, OutputParams const &) const
566 xs << XHTMLStream::ESCAPE_NONE << "˥"
567 << XHTMLStream::ESCAPE_NONE << "˩";
570 xs << XHTMLStream::ESCAPE_NONE << "˩"
571 << XHTMLStream::ESCAPE_NONE << "˥";
573 case TONE_HIGH_RISING:
574 xs << XHTMLStream::ESCAPE_NONE << "˧"
575 << XHTMLStream::ESCAPE_NONE << "˥";
577 case TONE_LOW_RISING:
578 xs << XHTMLStream::ESCAPE_NONE << "˩"
579 << XHTMLStream::ESCAPE_NONE << "˧";
581 case TONE_HIGH_RISING_FALLING:
582 xs << XHTMLStream::ESCAPE_NONE << "˨"
583 << XHTMLStream::ESCAPE_NONE << "˥"
584 << XHTMLStream::ESCAPE_NONE << "˨";
591 void InsetIPAChar::toString(odocstream & os) const
593 odocstringstream ods;
594 plaintext(ods, OutputParams(0));
599 void InsetIPAChar::forOutliner(docstring & os, size_t) const
601 odocstringstream ods;
602 plaintext(ods, OutputParams(0));
607 void InsetIPAChar::validate(LaTeXFeatures & features) const
612 case TONE_HIGH_RISING:
613 case TONE_LOW_RISING:
614 case TONE_HIGH_RISING_FALLING:
615 features.require("tone");
623 bool InsetIPAChar::isLetter() const
629 bool InsetIPAChar::isLineSeparator() const