Author: spitz Date: Tue Mar 6 08:54:22 2012 New Revision: 40867 URL: http://www.lyx.org/trac/changeset/40867
Log: Implement a native IPA inset (bug #2591) with instant preview. Currently only basic functionality (our math-tipa functionality plus multipar input). Further enhancements (such as proper unicode input and a specific toolbar) are planned. DocBook and XHTML output also need to be audited. The lyx2lyx reversion routine surely can be improved (help appreciated), and I don't know tex2lyx enough to handle this file format change. Added: lyx-devel/trunk/src/insets/InsetIPA.cpp (contents, props changed) lyx-devel/trunk/src/insets/InsetIPA.h (contents, props changed) Modified: lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py lyx-devel/trunk/lib/ui/stdmenus.inc lyx-devel/trunk/src/FuncCode.h lyx-devel/trunk/src/LyXAction.cpp lyx-devel/trunk/src/Makefile.am lyx-devel/trunk/src/Text3.cpp lyx-devel/trunk/src/factory.cpp lyx-devel/trunk/src/insets/InsetCode.h lyx-devel/trunk/src/version.h Modified: lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py ============================================================================== --- lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py Tue Mar 6 08:54:22 2012 (r40867) @@ -535,6 +535,44 @@ document.body[i:i+1] = subst_begin +def revert_tipa(document): + " Revert native TIPA insets to mathed or ERT. " + i = 0 + while 1: + i = find_token(document.body, "\\begin_inset IPA", i) + if i == -1: + return + j = find_end_of_inset(document.body, i) + if j == -1: + document.warning("Malformed lyx document: Can't find end of IPA inset") + i += 1 + continue + Multipar = False + n = find_token(document.body, "\\begin_layout", i, j) + if n == -1: + document.warning("Malformed lyx document: IPA inset has no embedded layout") + i += 1 + continue + m = find_end_of_layout(document.body, n) + if m == -1: + document.warning("Malformed lyx document: Can't find end of embedded layout") + i += 1 + continue + content = document.body[n+1:m] + p = find_token(document.body, "\\begin_layout", m, j) + if p != -1 or len(content) > 1: + Multipar = True + content = document.body[i+1:j] + if Multipar: + # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA} + document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}") + add_to_preamble(document, ["\\usepackage{tipa,tipx}"]) + else: + # single-par IPA insets can be reverted to mathed + document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"] + i = j + + ## # Conversion hub # @@ -553,10 +591,12 @@ [423, [convert_use_mathtools]], [424, [convert_cite_engine_type]], [425, []], - [426, []] + [426, []], + [427, []] ] revert = [ + [426, [revert_tipa]], [425, [revert_verbatim]], [424, [revert_cancel]], [423, [revert_cite_engine_type]], Modified: lyx-devel/trunk/lib/ui/stdmenus.inc ============================================================================== --- lyx-devel/trunk/lib/ui/stdmenus.inc Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/lib/ui/stdmenus.inc Tue Mar 6 08:54:22 2012 (r40867) @@ -388,7 +388,7 @@ Item "Protected Hyphen|y" "specialchar-insert nobreakdash" Item "Breakable Slash|a" "specialchar-insert slash" Item "Menu Separator|M" "specialchar-insert menu-separator" - Item "Phonetic Symbols|P" "command-sequence math-insert \text\textipa ; char-forward ;" + Item "Phonetic Symbols|P" "ipa-insert" End Menu "insert_formatting" Modified: lyx-devel/trunk/src/FuncCode.h ============================================================================== --- lyx-devel/trunk/src/FuncCode.h Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/src/FuncCode.h Tue Mar 6 08:54:22 2012 (r40867) @@ -451,6 +451,7 @@ LFUN_BUFFER_EXPORT_AS, // tommaso 20111006 // 350 LFUN_CLIPBOARD_PASTE_SIMPLE, // tommaso, 20111028 + LFUN_IPA_INSERT, // spitz, 20120305 LFUN_LASTACTION // end of the table }; Modified: lyx-devel/trunk/src/LyXAction.cpp ============================================================================== --- lyx-devel/trunk/src/LyXAction.cpp Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/src/LyXAction.cpp Tue Mar 6 08:54:22 2012 (r40867) @@ -542,6 +542,14 @@ * \endvar */ { LFUN_INDEX_PRINT, "index-print", Noop, Edit }, +/*! + * \var lyx::FuncCode lyx::LFUN_IPA_INSERT + * \li Action: Inserts an IPA inset. + * \li Syntax: ipa-insert + * \li Origin: spitz, 05 Mar 2012 + * \endvar + */ + { LFUN_IPA_INSERT, "ipa-insert", Noop, Edit }, /*! * \var lyx::FuncCode lyx::LFUN_NOMENCL_INSERT Modified: lyx-devel/trunk/src/Makefile.am ============================================================================== --- lyx-devel/trunk/src/Makefile.am Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/src/Makefile.am Tue Mar 6 08:54:22 2012 (r40867) @@ -558,6 +558,7 @@ insets/InsetInclude.cpp \ insets/InsetIndex.cpp \ insets/InsetInfo.cpp \ + insets/InsetIPA.cpp \ insets/InsetLabel.cpp \ insets/InsetLayout.cpp \ insets/InsetLine.cpp \ @@ -614,6 +615,7 @@ insets/InsetInclude.h \ insets/InsetIndex.h \ insets/InsetInfo.h \ + insets/InsetIPA.h \ insets/InsetPreview.h \ insets/InsetLabel.h \ insets/InsetLayout.h \ Modified: lyx-devel/trunk/src/Text3.cpp ============================================================================== --- lyx-devel/trunk/src/Text3.cpp Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/src/Text3.cpp Tue Mar 6 08:54:22 2012 (r40867) @@ -1649,6 +1649,7 @@ case LFUN_INDEX_INSERT: case LFUN_PREVIEW_INSERT: case LFUN_SCRIPT_INSERT: + case LFUN_IPA_INSERT: // Open the inset, and move the current selection // inside it. doInsertInset(cur, this, cmd, true, true); @@ -2445,6 +2446,9 @@ && cur.buffer()->params().branchlist().empty()) enable = false; break; + case LFUN_IPA_INSERT: + code = IPA_CODE; + break; case LFUN_PHANTOM_INSERT: code = PHANTOM_CODE; break; Modified: lyx-devel/trunk/src/factory.cpp ============================================================================== --- lyx-devel/trunk/src/factory.cpp Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/src/factory.cpp Tue Mar 6 08:54:22 2012 (r40867) @@ -38,6 +38,7 @@ #include "insets/InsetInclude.h" #include "insets/InsetIndex.h" #include "insets/InsetInfo.h" +#include "insets/InsetIPA.h" #include "insets/InsetLabel.h" #include "insets/InsetLine.h" #include "insets/InsetMarginal.h" @@ -184,6 +185,9 @@ return new InsetIndex(buf, InsetIndexParams(arg)); } + case LFUN_IPA_INSERT: + return new InsetIPA(buf); + case LFUN_NOMENCL_INSERT: { InsetCommandParams icp(NOMENCL_CODE); icp["symbol"] = cmd.argument(); @@ -615,6 +619,8 @@ inset.reset(new InsetFloatList(buf)); } else if (tmptok == "Info") { inset.reset(new InsetInfo(buf)); + } else if (tmptok == "IPA") { + inset.reset(new InsetIPA(buf)); } else if (tmptok == "Preview") { inset.reset(new InsetPreview(buf)); } else { Modified: lyx-devel/trunk/src/insets/InsetCode.h ============================================================================== --- lyx-devel/trunk/src/insets/InsetCode.h Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/src/insets/InsetCode.h Tue Mar 6 08:54:22 2012 (r40867) @@ -231,6 +231,8 @@ /// SCRIPT_CODE, // 105 /// + IPA_CODE, + /// INSET_CODE_SIZE }; Added: lyx-devel/trunk/src/insets/InsetIPA.cpp ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ lyx-devel/trunk/src/insets/InsetIPA.cpp Tue Mar 6 08:54:22 2012 (r40867) @@ -0,0 +1,199 @@ +/** + * \file InsetIPA.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Jürgen Spitzmüller + * + * Full author contact details are available in file CREDITS. + */ +#include "config.h" + +#include "InsetIPA.h" + +#include "Buffer.h" +#include "BufferParams.h" +#include "BufferView.h" +#include "Cursor.h" +#include "LaTeXFeatures.h" +#include "Lexer.h" +#include "LyXRC.h" +#include "MetricsInfo.h" +#include "OutputParams.h" +#include "RenderPreview.h" + +#include "frontends/Painter.h" + +#include "graphics/PreviewImage.h" + +#include <sstream> + +using namespace std; + +namespace lyx { + + +InsetIPA::InsetIPA(Buffer * buf) + : InsetText(buf), + preview_(new RenderPreview(this)), use_preview_(true) +{ + setAutoBreakRows(true); + setDrawFrame(true); + setFrameColor(Color_insetframe); +} + + +InsetIPA::~InsetIPA() +{} + + +InsetIPA::InsetIPA(InsetIPA const & other) + : InsetText(other) +{ + preview_.reset(new RenderPreview(*other.preview_, this)); +} + + +void InsetIPA::write(ostream & os) const +{ + os << "IPA" << "\n"; + text().write(os); +} + + +void InsetIPA::addPreview(DocIterator const & inset_pos, + graphics::PreviewLoader &) const +{ + preparePreview(inset_pos); +} + + +void InsetIPA::preparePreview(DocIterator const & pos) const +{ + TexRow texrow; + odocstringstream str; + otexstream os(str, texrow); + OutputParams runparams(&pos.buffer()->params().encoding()); + latex(os, runparams); + docstring const snippet = str.str(); + preview_->addPreview(snippet, *pos.buffer()); +} + + +bool InsetIPA::previewState(BufferView * bv) const +{ + if (!editing(bv) && (RenderPreview::status() == LyXRC::PREVIEW_ON || + RenderPreview::status() == LyXRC::PREVIEW_NO_MATH)) { + graphics::PreviewImage const * pimage = + preview_->getPreviewImage(bv->buffer()); + return pimage && pimage->image(); + } + return false; +} + + +void InsetIPA::reloadPreview(DocIterator const & pos) const +{ + preparePreview(pos); + preview_->startLoading(*pos.buffer()); +} + + +void InsetIPA::draw(PainterInfo & pi, int x, int y) const +{ + use_preview_ = previewState(pi.base.bv); + + if (use_preview_) { + preview_->draw(pi, x + TEXT_TO_INSET_OFFSET, y); + setPosCache(pi, x, y); + return; + } + InsetText::draw(pi, x, y); +} + + +void InsetIPA::edit(Cursor & cur, bool front, EntryDirection entry_from) +{ + cur.push(*this); + InsetText::edit(cur, front, entry_from); +} + + +Inset * InsetIPA::editXY(Cursor & cur, int x, int y) +{ + if (use_preview_) { + edit(cur, true, ENTRY_DIRECTION_IGNORE); + return this; + } + cur.push(*this); + return InsetText::editXY(cur, x, y); +} + + +void InsetIPA::metrics(MetricsInfo & mi, Dimension & dim) const +{ + if (previewState(mi.base.bv)) { + preview_->metrics(mi, dim); + mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET; + + dim.wid = max(dim.wid, 4); + dim.asc = max(dim.asc, 4); + + dim.asc += TEXT_TO_INSET_OFFSET; + dim.des += TEXT_TO_INSET_OFFSET; + dim.wid += TEXT_TO_INSET_OFFSET; + dim_ = dim; + dim.wid += TEXT_TO_INSET_OFFSET; + // insert a one pixel gap + dim.wid += 1; + // Cache the inset dimension. + setDimCache(mi, dim); + Dimension dim_dummy; + MetricsInfo mi_dummy = mi; + InsetText::metrics(mi_dummy, dim_dummy); + return; + } + InsetText::metrics(mi, dim); +} + + +bool InsetIPA::notifyCursorLeaves(Cursor const & old, Cursor & cur) +{ + reloadPreview(old); + cur.screenUpdateFlags(Update::Force); + return InsetText::notifyCursorLeaves(old, cur); +} + + +void InsetIPA::validate(LaTeXFeatures & features) const +{ + features.require("tipa"); + features.require("tipx"); +} + + +void InsetIPA::latex(otexstream & os, OutputParams const & runparams) const +{ + bool const multipar = (text().paragraphs().size() > 1); + if (multipar) + os << "\\begin{IPA}\n"; + else + os << "\\textipa{"; + InsetText::latex(os, runparams); + if (multipar) + os << "\n\\end{IPA}"; + else + os << "}"; +} + + +bool InsetIPA::insetAllowed(InsetCode code) const +{ + if (code == ERT_CODE) + return true; + else + return false; +} + + +} // namespace lyx Added: lyx-devel/trunk/src/insets/InsetIPA.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ lyx-devel/trunk/src/insets/InsetIPA.h Tue Mar 6 08:54:22 2012 (r40867) @@ -0,0 +1,101 @@ +// -*- C++ -*- +/** + * \file InsetIPA.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Jürgen Spitzmüller + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef INSETIPA_H +#define INSETIPA_H + +#include "InsetText.h" + +#include "Dimension.h" + +#include <boost/scoped_ptr.hpp> + +namespace lyx { + +class RenderPreview; + +namespace graphics { + class PreviewLoader; +} + +/// An IPA inset with instant preview +class InsetIPA : public InsetText { + +public: + /// + InsetIPA(Buffer *); + /// + ~InsetIPA(); + /// + InsetIPA(InsetIPA const & other); + + /// \name Methods inherited from Inset class + //@{ + Inset * clone() const { return new InsetIPA(*this); } + + bool neverIndent() const { return true; } + + InsetCode lyxCode() const { return IPA_CODE; } + + docstring layoutName() const { return from_ascii("IPA"); } + + bool descendable(BufferView const & /*bv*/) const { return true; } + + void metrics(MetricsInfo & mi, Dimension & dim) const; + + Inset * editXY(Cursor & cur, int x, int y); + + void draw(PainterInfo & pi, int x, int y) const; + + void addPreview(DocIterator const & inset_pos, + graphics::PreviewLoader & ploader) const; + + bool notifyCursorLeaves(Cursor const & old, Cursor & cur); + + void write(std::ostream & os) const; + + void edit(Cursor & cur, bool front, EntryDirection entry_from); + + /// + void latex(otexstream &, OutputParams const &) const; + /// + void validate(LaTeXFeatures & features) const; + /// + bool allowSpellCheck() const { return false; } + /// + bool insetAllowed(InsetCode code) const; + //@} + +protected: + /// Retrieves the preview state. Returns true if preview + /// is enabled and the preview image is availabled. + bool previewState(BufferView * bv) const; + /// Recreates the preview if preview is enabled. + void reloadPreview(DocIterator const & pos) const; + /// Prepare the preview if preview is enabled. + void preparePreview(DocIterator const & pos) const; + + /// + boost::scoped_ptr<RenderPreview> preview_; + /// + mutable bool use_preview_; + +private: + /// + mutable Dimension dim_; +}; + + +} // namespace lyx + + +#endif + Modified: lyx-devel/trunk/src/version.h ============================================================================== --- lyx-devel/trunk/src/version.h Tue Mar 6 00:32:30 2012 (r40866) +++ lyx-devel/trunk/src/version.h Tue Mar 6 08:54:22 2012 (r40867) @@ -30,7 +30,7 @@ // Do not remove the comment below, so we get merge conflict in // independent branches. Instead add your own. -#define LYX_FORMAT_LYX 426 // uwestoehr: support for verbatim +#define LYX_FORMAT_LYX 427 // spitz: tipa inset #define LYX_FORMAT_TEX2LYX 426 // uwestoehr: support for verbatim #if LYX_FORMAT_FOR_TEX2LYX != LYX_FORMAT_FOR_LYX