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 decotranslator = init_ipadecotranslator();
63 return decotranslator;
67 IPADecoTranslatorLoc const & ipadecotranslator_loc()
69 static IPADecoTranslatorLoc translator = init_ipadecotranslator_loc();
74 typedef Translator<string, InsetIPAChar::Kind> IPACharTranslator;
76 IPACharTranslator const init_ipachartranslator()
78 IPACharTranslator translator("\\tone{51}", InsetIPAChar::TONE_FALLING);
79 translator.addPair("\\tone{15}", InsetIPAChar::TONE_RISING);
80 translator.addPair("\\tone{45}", InsetIPAChar::TONE_HIGH_RISING);
81 translator.addPair("\\tone{12}", InsetIPAChar::TONE_LOW_RISING);
82 translator.addPair("\\tone{454}", InsetIPAChar::TONE_HIGH_RISING_FALLING);
87 IPACharTranslator const & ipachartranslator()
89 static IPACharTranslator chartranslator = init_ipachartranslator();
90 return chartranslator;
96 InsetIPADecoParams::InsetIPADecoParams()
101 void InsetIPADecoParams::write(ostream & os) const
103 string const label = ipadecotranslator().find(type);
104 os << "IPADeco " << label << "\n";
108 void InsetIPADecoParams::read(Lexer & lex)
113 type = ipadecotranslator().find(label);
117 /////////////////////////////////////////////////////////////////////
121 /////////////////////////////////////////////////////////////////////
123 InsetIPADeco::InsetIPADeco(Buffer * buf, string const & label)
124 : InsetCollapsable(buf)
127 setFrameColor(Color_insetframe);
128 params_.type = ipadecotranslator().find(label);
132 InsetIPADeco::~InsetIPADeco()
136 docstring InsetIPADeco::layoutName() const
138 return from_ascii("IPADeco:" + ipadecotranslator().find(params_.type));
142 void InsetIPADeco::metrics(MetricsInfo & mi, Dimension & dim) const
144 InsetText::metrics(mi, dim);
146 if (params_.type == InsetIPADecoParams::Toptiebar) {
147 // consider width of the inset label
148 FontInfo font(getLayout().labelfont());
149 font.realize(sane_font);
155 docstring const label(1, char_type(0x2040));
156 theFontMetrics(font).rectText(label, w, a, d);
157 dim.asc += int(a * 0.5);
159 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
160 // consider width of the inset label
161 FontInfo font(getLayout().labelfont());
162 font.realize(sane_font);
168 docstring const label(1, char_type(0x203f));
169 theFontMetrics(font).rectText(label, w, a, d);
170 dim.des += int(d * 1.5);
173 // cache the inset dimension
174 setDimCache(mi, dim);
178 void InsetIPADeco::draw(PainterInfo & pi, int x, int y) const
181 InsetCollapsable::draw(pi, x, y);
183 // draw the inset marker
184 drawMarkers(pi, x, y);
186 Dimension const dim = Inset::dimension(*pi.base.bv);
188 if (params_.type == InsetIPADecoParams::Toptiebar) {
189 FontInfo font(getLayout().labelfont());
190 font.realize(sane_font);
196 int asc = dim.ascent();
197 docstring const label(1, char_type(0x2040));
198 theFontMetrics(font).rectText(label, w, a, d);
199 int const ww = max(dim.wid, w);
200 pi.pain.rectText(x + (ww - w) / 2, y - int(asc / 2.5),
201 label, font, Color_none, Color_none);
204 if (params_.type == InsetIPADecoParams::Bottomtiebar) {
205 FontInfo font(getLayout().labelfont());
206 font.realize(sane_font);
212 int desc = dim.descent();
213 docstring const label(1, char_type(0x203f));
214 theFontMetrics(font).rectText(label, w, a, d);
215 int const ww = max(dim.wid, w);
216 pi.pain.rectText(x + (ww - w) / 2, y + int(desc / 1.5),
217 label, font, Color_none, Color_none);
222 void InsetIPADeco::write(ostream & os) const
225 InsetCollapsable::write(os);
229 void InsetIPADeco::read(Lexer & lex)
232 InsetCollapsable::read(lex);
236 void InsetIPADeco::doDispatch(Cursor & cur, FuncRequest & cmd)
238 switch (cmd.action()) {
239 case LFUN_QUOTE_INSERT: {
240 FuncRequest fr(LFUN_SELF_INSERT, "\"");
241 InsetText::doDispatch(cur, fr);
245 InsetText::doDispatch(cur, cmd);
251 bool InsetIPADeco::getStatus(Cursor & cur, FuncRequest const & cmd,
252 FuncStatus & flag) const
254 switch (cmd.action()) {
255 case LFUN_SCRIPT_INSERT: {
256 if (cmd.argument() == "subscript") {
257 flag.setEnabled(false);
263 flag.setEnabled(true);
269 return InsetText::getStatus(cur, cmd, flag);
273 void InsetIPADeco::latex(otexstream & os, OutputParams const & runparams) const
275 if (params_.type == InsetIPADecoParams::Toptiebar)
276 os << "\\texttoptiebar{";
277 else if (params_.type == InsetIPADecoParams::Bottomtiebar)
278 os << "\\textbottomtiebar{";
279 InsetCollapsable::latex(os, runparams);
284 int InsetIPADeco::plaintext(odocstringstream & os,
285 OutputParams const & runparams, size_t max_length) const
287 odocstringstream ods;
288 int h = (int)(InsetCollapsable::plaintext(ods, runparams, max_length) / 2);
289 docstring result = ods.str();
290 docstring const before = result.substr(0, h);
291 docstring const after = result.substr(h, result.size());
293 if (params_.type == InsetIPADecoParams::Toptiebar) {
298 else if (params_.type == InsetIPADecoParams::Bottomtiebar) {
303 return result.size();
307 int InsetIPADeco::docbook(odocstream & os, OutputParams const & runparams) const
309 // FIXME: Any docbook option here?
310 return InsetCollapsable::docbook(os, runparams);
314 docstring InsetIPADeco::xhtml(XHTMLStream & xs, OutputParams const & runparams) const
316 // FIXME: Like in plaintext, the combining characters "͡" (toptiebar)
317 // or "͜" (bottomtiebar) would need to be inserted just in the mid
318 // of the text string. (How) can this be done with the xhtml stream?
319 return InsetCollapsable::xhtml(xs, runparams);
323 docstring InsetIPADeco::toolTip(BufferView const &, int, int) const
325 return ipadecotranslator_loc().find(params_.type);
329 string InsetIPADeco::params2string(InsetIPADecoParams const & params)
332 data << "IPADeco" << ' ';
338 void InsetIPADeco::string2params(string const & in, InsetIPADecoParams & params)
340 params = InsetIPADecoParams();
345 istringstream data(in);
348 lex.setContext("InsetIPADeco::string2params");
349 lex >> "IPADeco" >> "toptiebar";
355 void InsetIPADeco::validate(LaTeXFeatures & features) const
357 features.require("tipa");
358 InsetText::validate(features);
362 bool InsetIPADeco::insetAllowed(InsetCode code) const
365 // code that is allowed
375 /////////////////////////////////////////////////////////////////////////
379 /////////////////////////////////////////////////////////////////////////
382 InsetIPAChar::InsetIPAChar(Kind k)
387 InsetIPAChar::Kind InsetIPAChar::kind() const
393 void InsetIPAChar::metrics(MetricsInfo & mi, Dimension & dim) const
395 frontend::FontMetrics const & fm =
396 theFontMetrics(mi.base.font);
397 dim.asc = fm.maxAscent();
398 dim.des = fm.maxDescent();
404 case TONE_HIGH_RISING:
405 case TONE_LOW_RISING:
406 case TONE_HIGH_RISING_FALLING:
410 docstring ds(s.begin(), s.end());
411 dim.wid = fm.width(ds);
412 setDimCache(mi, dim);
416 void InsetIPAChar::draw(PainterInfo & pi, int x, int y) const
418 FontInfo font = pi.base.font;
419 frontend::FontMetrics const & fm =
420 theFontMetrics(font);
425 int w = fm.width(char_type('-'));
426 int h = fm.ascent(char_type('M'));
430 pi.pain.line(x2, y2, x2, y, Color_foreground);
431 pi.pain.line(x2, y, x, y2, Color_foreground);
436 int w = fm.width(char_type('-'));
437 int h = fm.ascent(char_type('M'));
441 pi.pain.line(x2, y, x2, y2, Color_foreground);
442 pi.pain.line(x2, y2, x, y, Color_foreground);
445 case TONE_HIGH_RISING:
447 int w = fm.width(char_type('-'));
448 int h = fm.ascent(char_type('M'));
451 int y3 = y - int(h * 0.75);
453 pi.pain.line(x2, y, x2, y2, Color_foreground);
454 pi.pain.line(x2, y2, x, y3, Color_foreground);
457 case TONE_LOW_RISING:
459 int w = fm.width(char_type('-'));
460 int h = fm.ascent(char_type('M'));
463 int y3 = y - int(h * 0.25);
465 pi.pain.line(x2, y, x2, y2, Color_foreground);
466 pi.pain.line(x2, y3, x, y, Color_foreground);
469 case TONE_HIGH_RISING_FALLING:
471 int w = fm.width(char_type('-'));
472 int h = fm.ascent(char_type('M'));
475 int x3 = x + int(w * 0.5);
476 int y3 = y - int(h * 0.75);
478 pi.pain.line(x2, y, x2, y2, Color_foreground);
479 pi.pain.line(x2, y3, x3, y2, Color_foreground);
480 pi.pain.line(x3, y2, x, y3, Color_foreground);
487 void InsetIPAChar::write(ostream & os) const
489 string const command = ipachartranslator().find(kind_);
490 if (command.empty()) {
491 LYXERR0("InsetIPAChar::write: Unknown type");
494 os << "\\IPAChar " << command << "\n";
498 void InsetIPAChar::read(Lexer & lex)
501 string const command = lex.getString();
502 kind_ = ipachartranslator().find(command);
506 void InsetIPAChar::latex(otexstream & os,
507 OutputParams const &) const
509 string const command = ipachartranslator().find(kind_);
514 int InsetIPAChar::plaintext(odocstringstream & os, OutputParams const &, size_t) const
525 case TONE_HIGH_RISING:
529 case TONE_LOW_RISING:
533 case TONE_HIGH_RISING_FALLING:
543 int InsetIPAChar::docbook(odocstream & /*os*/, OutputParams const &) const
547 LYXERR0("IPA tone macros not yet implemented with DocBook!");
550 case TONE_HIGH_RISING:
551 case TONE_LOW_RISING:
552 case TONE_HIGH_RISING_FALLING:
559 docstring InsetIPAChar::xhtml(XHTMLStream & xs, OutputParams const &) const
563 xs << XHTMLStream::ESCAPE_NONE << "˥"
564 << XHTMLStream::ESCAPE_NONE << "˩";
567 xs << XHTMLStream::ESCAPE_NONE << "˩"
568 << XHTMLStream::ESCAPE_NONE << "˥";
570 case TONE_HIGH_RISING:
571 xs << XHTMLStream::ESCAPE_NONE << "˧"
572 << XHTMLStream::ESCAPE_NONE << "˥";
574 case TONE_LOW_RISING:
575 xs << XHTMLStream::ESCAPE_NONE << "˩"
576 << XHTMLStream::ESCAPE_NONE << "˧";
578 case TONE_HIGH_RISING_FALLING:
579 xs << XHTMLStream::ESCAPE_NONE << "˨"
580 << XHTMLStream::ESCAPE_NONE << "˥"
581 << XHTMLStream::ESCAPE_NONE << "˨";
588 void InsetIPAChar::toString(odocstream & os) const
590 odocstringstream ods;
591 plaintext(ods, OutputParams(0));
596 void InsetIPAChar::forToc(docstring & os, size_t) const
598 odocstringstream ods;
599 plaintext(ods, OutputParams(0));
604 void InsetIPAChar::validate(LaTeXFeatures & features) const
609 case TONE_HIGH_RISING:
610 case TONE_LOW_RISING:
611 case TONE_HIGH_RISING_FALLING:
612 features.require("tone");
620 bool InsetIPAChar::isLetter() const
626 bool InsetIPAChar::isLineSeparator() const