mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
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. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@40867 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
24733efcee
commit
f626cfb7a3
@ -535,6 +535,44 @@ def revert_verbatim(document):
|
||||
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 @@ convert = [
|
||||
[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]],
|
||||
|
@ -388,7 +388,7 @@ Menuset
|
||||
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"
|
||||
|
@ -451,6 +451,7 @@ enum FuncCode
|
||||
LFUN_BUFFER_EXPORT_AS, // tommaso 20111006
|
||||
// 350
|
||||
LFUN_CLIPBOARD_PASTE_SIMPLE, // tommaso, 20111028
|
||||
LFUN_IPA_INSERT, // spitz, 20120305
|
||||
|
||||
LFUN_LASTACTION // end of the table
|
||||
};
|
||||
|
@ -542,6 +542,14 @@ void LyXAction::init()
|
||||
* \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
|
||||
|
@ -558,6 +558,7 @@ SOURCEFILESINSETS = \
|
||||
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 @@ HEADERFILESINSETS = \
|
||||
insets/InsetInclude.h \
|
||||
insets/InsetIndex.h \
|
||||
insets/InsetInfo.h \
|
||||
insets/InsetIPA.h \
|
||||
insets/InsetPreview.h \
|
||||
insets/InsetLabel.h \
|
||||
insets/InsetLayout.h \
|
||||
|
@ -1649,6 +1649,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
|
||||
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 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
|
||||
&& cur.buffer()->params().branchlist().empty())
|
||||
enable = false;
|
||||
break;
|
||||
case LFUN_IPA_INSERT:
|
||||
code = IPA_CODE;
|
||||
break;
|
||||
case LFUN_PHANTOM_INSERT:
|
||||
code = PHANTOM_CODE;
|
||||
break;
|
||||
|
@ -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 @@ Inset * createInsetHelper(Buffer * buf, FuncRequest const & cmd)
|
||||
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 * readInset(Lexer & lex, Buffer * buf)
|
||||
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 {
|
||||
|
@ -231,6 +231,8 @@ enum InsetCode {
|
||||
///
|
||||
SCRIPT_CODE, // 105
|
||||
///
|
||||
IPA_CODE,
|
||||
///
|
||||
INSET_CODE_SIZE
|
||||
};
|
||||
|
||||
|
199
src/insets/InsetIPA.cpp
Normal file
199
src/insets/InsetIPA.cpp
Normal file
@ -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
|
101
src/insets/InsetIPA.h
Normal file
101
src/insets/InsetIPA.h
Normal file
@ -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
|
||||
|
@ -30,7 +30,7 @@ extern char const * const lyx_version_info;
|
||||
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user